From: David Lecompte <3gpp@metani.eu> Date: Wed, 29 Jul 2026 15:12:00 +0000 (+0200) Subject: 38331-convert.sh directly converts docx to text and generates ASN.1 with comments... X-Git-Url: https://nuage.metani.fr/gitweb/3GPP.git/commitdiff_plain/9fbf535ed3783dcb7f399c7da0c08099f6aa951d?ds=sidebyside;hp=be0799272ac0e49ed50abcf3b42868f00c6a6ce7 38331-convert.sh directly converts docx to text and generates ASN.1 with comments in two formats asn1-split.awk creates one .asn file per module --- diff --git a/awk/asn1-split.awk b/awk/asn1-split.awk new file mode 100755 index 0000000..bd675ac --- /dev/null +++ b/awk/asn1-split.awk @@ -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 index 0000000..cd8267b --- /dev/null +++ b/bin/38331-convert.sh @@ -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