]> nuage.metani.fr Git - 3GPP.git/commitdiff
38331-convert.sh directly converts docx to text and generates ASN.1 with comments...
authorDavid Lecompte <3gpp@metani.eu>
Wed, 29 Jul 2026 15:12:00 +0000 (17:12 +0200)
committerDavid Lecompte <3gpp@metani.eu>
Wed, 29 Jul 2026 15:12:00 +0000 (17:12 +0200)
asn1-split.awk creates one .asn file per module

awk/asn1-split.awk [new file with mode: 0755]
bin/38331-convert.sh [new file with mode: 0755]

diff --git a/awk/asn1-split.awk b/awk/asn1-split.awk
new file mode 100755 (executable)
index 0000000..bd675ac
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/awk -f
+
+BEGIN {
+    # A record is an IE heading
+    RS = "-- =+\n-- IE: [A-Z][A-Za-z0-9-]+"
+
+    # A field is a line
+    FS = "\n"
+
+    # Usage explanation
+    if (ARGC != "2") {
+       print "Usage: " ARGV[0] " file.asn"
+       print "Splits file.asn generated by txt2asn into one file per module"
+       exit
+    }
+    file_prefix = ARGV[1]
+    gsub(/.asn$/, "", file_prefix)
+
+    outfile = ""
+    heading = ""
+}
+{
+    # Search for the start of a module definition in every field (= line) of the IE
+    for (i = 1; i <= NF; i++) {
+       if ($i ~ /[[A-Z][A-Za-z0-9-]+ DEFINITIONS AUTOMATIC TAGS ::=/) {
+           split($i, module_name, " ")
+           outfile = file_prefix "-" module_name[1] ".asn"
+       }
+    }
+
+    # See below about heading
+    if (outfile != "") {
+       print heading $0 > outfile
+    }
+
+    # RT is the record terminator i.e., the string that matched RS
+    # It actually is the heading of the next record, so store it
+    # to be printed with the next record.
+    
+    heading = RT
+}
+    
diff --git a/bin/38331-convert.sh b/bin/38331-convert.sh
new file mode 100755 (executable)
index 0000000..cd8267b
--- /dev/null
@@ -0,0 +1,98 @@
+#!/bin/bash
+
+if [[ ! $# -eq 1 ]] ; then
+    echo "Usage: ${0##*/} 38331-xyz.docx"
+    echo "38331-xyz.docx is a version of TS 38.331"
+    echo "Creates one .asn pure ASN.1 text file per ASN.1 module in TS 38.331"
+    echo "Message, IE, field and presence condition descriptions are included as comments"
+    echo "Produces 2 versions:"
+    echo "    - one with descriptions of fields and presence conditions at the end of the IE definition"
+    echo "    - one with those descriptions before the concerned field(s)"
+    exit 1
+fi
+
+if [[ ! -w . ]] ; then
+    echo "Cannot write to current directory"
+    exit 1
+fi
+
+if [[ ! -f "$1" ]] || [[ ! -r "$1" ]] ; then
+    echo "$1 is not a readable file"
+    exit
+fi    
+
+if [[ -e "${1%.docx}.txt" ]] ; then
+    echo "${1%.docx}.txt already exists: skipping conversion"
+else
+    platform=$(uname)
+    case $platform in
+       Linux) libreoffice="libreoffice" ;;
+       CYGWIN*) libreoffice="soffice" ;;
+       *) echo "Unkown platform $platform"
+          exit 1;;
+    esac
+
+    if [[ ! -x $(which "$libreoffice") ]] ; then
+       echo "Cannot find libreoffice executable"
+       echo "Make sure it is installed and the PATH variable includes its path"
+       exit 1
+    fi
+    $libreoffice --convert-to txt "$1"
+    
+    if [[ ! -f "${1%.docx}.txt" ]] || [[ ! -r "${1%.docx}.txt" ]] ; then
+       echo "libreoffice did not create ${1%.docx}.txt"
+       exit
+    fi
+
+    case $platform in
+       # Replace EN-DASH (UTF-8 encoding) at line start with -
+       Linux) LC_ALL=C sed -i $'s/^\u2013/-/g' "${1%.docx}.txt" ;;
+       
+       # Replace EN-DASH (Windows-1252 encoding) at line start with -
+       # Remove CR (0x0d) put by libreoffice in windows before each LF (0x0a)
+       CYGWIN*) LC_ALL=C sed -i $'s/^\x96/-/g; s/\r$//' "${1%.docx}.txt" ;;
+       *) echo "Unkown platform $platform"
+          exit 1;;
+    esac
+    
+    # Changes things that should not be so in the specification
+    # Change "-- Cond N3C MP" to "-- Cond N3C-MP" (to respect condition naming rules)
+    LC_ALL=C sed -i 's/-- Cond N3C MP/-- Cond N3C-MP/' "${1%.docx}.txt"
+    LC_ALL=C sed -i 's/^N3C MP/N3C-MP/' "${1%.docx}.txt"
+    LC_ALL=C sed -i 's/-- Cond HOAndServCellAdd,$/-- Cond HOAndServCellAdd/' "${1%.docx}.txt"
+fi       
+
+cat "${1%.docx}.txt" | awk '/^-- ASN1START$/,/^-- ASN1STOP$/' | awk '!/^[[:space:]]*--/ && !/^[[:space:]]*$/'| sed -e 's/--.*$//g' > "${1%.docx}.asncheck"
+
+if [[ ! -e "${1%.docx}.asncheck" ]] ; then
+    echo "${1%.docx}.asn generation failed"
+    exit
+fi
+
+txt2asn.awk "${1%.docx}.txt" > "${1%.docx}-descriptions-at-IEs-end.asn"
+cat "${1%.docx}-descriptions-at-IEs-end.asn" | awk '!/^[[:space:]]*--/ && !/^[[:space:]]*$/'| sed -e 's/--.*$//g' > "${1%.docx}-descriptions-at-IEs-end.asncheck"
+compare1=$(diff -b -B "${1%.docx}.asncheck" "${1%.docx}-descriptions-at-IEs-end.asncheck")
+if [[ "$compare1" ]] ; then
+    echo "The ASN.1 in ${1%.docx}-descriptions-at-IEs-end.asn does not fully match with the ASN.1 in ${1%.docx}.asncheck"
+    echo "Check with:"
+    echo "  diff -b -B ${1%.docx}.asncheck ${1%.docx}-descriptions-at-IEs-end.asncheck"
+else
+    rm "${1%.docx}-descriptions-at-IEs-end.asncheck"
+fi
+
+txt2asn-integrated.awk "${1%.docx}.txt" > "${1%.docx}-description-before-field.asn"
+cat "${1%.docx}-description-before-field.asn" | awk '!/^[[:space:]]*--/ && !/^[[:space:]]*$/'| sed -e 's/--.*$//g' > "${1%.docx}-description-before-field.asncheck"
+compare2=$(diff -b -B "${1%.docx}.asncheck" "${1%.docx}-description-before-field.asncheck")
+if [[ "$compare2" ]] ; then
+    echo "The ASN.1 in ${1%.docx}-description-before-field.asn does not fully match with the ASN.1 in ${1%.docx}.asncheck"
+    echo "Check with:"
+    echo "  diff -b -B ${1%.docx}.asncheck ${1%.docx}-description-before-field.asncheck"
+else
+    rm "${1%.docx}-description-before-field.asncheck"
+fi
+
+if [[ "$compare1" ]] || [[ "$compare1" ]] ; then
+    exit
+else
+    rm "${1%.docx}.asncheck"
+fi