From f22184d31ca3bc808cc156b47fd5320658623c66 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Fri, 27 Oct 2017 18:40:32 -0700 Subject: [PATCH 01/41] force recompile T object --- tests/tests-randomized/check-bundles.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/tests-randomized/check-bundles.sh b/tests/tests-randomized/check-bundles.sh index 588cc9dbd..d3c7247b8 100755 --- a/tests/tests-randomized/check-bundles.sh +++ b/tests/tests-randomized/check-bundles.sh @@ -52,6 +52,13 @@ make_clean_before_bundle() { make_clean_before_test() { if [ "${need_clean_before_test}" = "1" ] ; then Make clean + else + # Low resolution file system mtime prevents rapid testing + # without recompilation. We have to clean at least the most + # critical portion of the objects. This will reach our objective + # of fast compile times (since most of skeletons are not recompiled), + # but won't yield a stale T.o object where newer T.c source exists. + rm -f T.o || : fi } From a53bdf16a0cc9927294c2e0c56de7900d9755d35 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Tue, 31 Oct 2017 17:21:37 -0700 Subject: [PATCH 02/41] removed autotools intermediate files from source code --- config.sub | 1616 ---------------------------------------------------- 1 file changed, 1616 deletions(-) delete mode 100755 config.sub diff --git a/config.sub b/config.sub deleted file mode 100755 index fab0aa355..000000000 --- a/config.sub +++ /dev/null @@ -1,1616 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. - -timestamp='2006-09-20' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ - uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray) - os= - basic_machine=$1 - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64vr | mips64vrel \ - | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | mt \ - | msp430 \ - | nios | nios2 \ - | ns16k | ns32k \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ - | pyramid \ - | score \ - | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu | strongarm \ - | tahoe | thumb | tic4x | tic80 | tron \ - | v850 | v850e \ - | we32k \ - | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ - | z8k) - basic_machine=$basic_machine-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ - | pyramid-* \ - | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tron-* \ - | v850-* | v850e-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ - | xstormy16-* | xtensa-* \ - | ymp-* \ - | z8k-*) - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16c) - basic_machine=cr16c-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tic55x | c55x*) - basic_machine=tic55x-unknown - os=-coff - ;; - tic6x | c6x*) - basic_machine=tic6x-unknown - os=-coff - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; - -zvmoe) - os=-zvmoe - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: From ee8482a55de40f8728f0f7bf25069bc2c509ced9 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Tue, 31 Oct 2017 18:26:15 -0700 Subject: [PATCH 03/41] avoid complaints about _BSD_SOURCE on ubuntu --- skeletons/asn_system.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/skeletons/asn_system.h b/skeletons/asn_system.h index ce46242ca..fa8cf1165 100644 --- a/skeletons/asn_system.h +++ b/skeletons/asn_system.h @@ -12,6 +12,10 @@ #include "config.h" #endif +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE 1 +#endif + #ifndef _BSD_SOURCE #define _BSD_SOURCE /* for snprintf() on some linux systems */ #endif From 3f52df00df500231571db3dc361d4e31f5bf74d1 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Tue, 31 Oct 2017 19:35:50 -0700 Subject: [PATCH 04/41] removed autotools intermediate files from source code --- depcomp | 584 ----------------------------------------------------- stamp-h.in | 1 - 2 files changed, 585 deletions(-) delete mode 100755 depcomp delete mode 100644 stamp-h.in diff --git a/depcomp b/depcomp deleted file mode 100755 index ca5ea4e1e..000000000 --- a/depcomp +++ /dev/null @@ -1,584 +0,0 @@ -#! /bin/sh -# depcomp - compile a program generating dependencies as side-effects - -scriptversion=2006-10-15.18 - -# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006 Free Software -# Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -case $1 in - '') - echo "$0: No command. Try \`$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: depcomp [--help] [--version] PROGRAM [ARGS] - -Run PROGRAMS ARGS to compile a file, generating dependencies -as side-effects. - -Environment variables: - depmode Dependency tracking mode. - source Source file read by `PROGRAMS ARGS'. - object Object file output by `PROGRAMS ARGS'. - DEPDIR directory where to store dependencies. - depfile Dependency file to output. - tmpdepfile Temporary file to use when outputing dependencies. - libtool Whether libtool is used (yes/no). - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "depcomp $scriptversion" - exit $? - ;; -esac - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi - -# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. -depfile=${depfile-`echo "$object" | - sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. -## Unfortunately, FreeBSD c89 acceptance of flags depends upon -## the command line argument order; so add the flags where they -## appear in depend2.am. Note that the slowdown incurred here -## affects only configure: in makefiles, %FASTDEP% shortcuts this. - for arg - do - case $arg in - -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; - *) set fnord "$@" "$arg" ;; - esac - shift # fnord - shift # $arg - done - "$@" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz -## The second -e expression handles DOS-style file names with drive letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the `deleted header file' problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. - tr ' ' ' -' < "$tmpdepfile" | -## Some versions of gcc put a space before the `:'. On the theory -## that the space means something, we add a space to the output as -## well. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like `#:fec' to the end of the - # dependency line. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ - tr ' -' ' ' >> $depfile - echo >> $depfile - - # The second pass generates a dummy entry for each header file. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> $depfile - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. In older versions, this file always lives in the - # current directory. Also, the AIX compiler puts `$object:' at the - # start of each line; $object doesn't have directory information. - # Version 6 uses the directory in both cases. - stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` - tmpdepfile="$stripped.u" - if test "$libtool" = yes; then - "$@" -Wc,-M - else - "$@" -M - fi - stat=$? - - if test -f "$tmpdepfile"; then : - else - stripped=`echo "$stripped" | sed 's,^.*/,,'` - tmpdepfile="$stripped.u" - fi - - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - - if test -f "$tmpdepfile"; then - outname="$stripped.o" - # Each line is of the form `foo.o: dependent.h'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" - sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -icc) - # Intel's C compiler understands `-MD -MF file'. However on - # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c - # ICC 7.0 will fill foo.d with something like - # foo.o: sub/foo.c - # foo.o: sub/foo.h - # which is wrong. We want: - # sub/foo.o: sub/foo.c - # sub/foo.o: sub/foo.h - # sub/foo.c: - # sub/foo.h: - # ICC 7.1 will output - # foo.o: sub/foo.c sub/foo.h - # and will wrap long lines using \ : - # foo.o: sub/foo.c ... \ - # sub/foo.h ... \ - # ... - - "$@" -MD -MF "$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each line is of the form `foo.o: dependent.h', - # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | - sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp2) - # The "hp" stanza above does not work with aCC (C++) and HP's ia64 - # compilers, which have integrated preprocessors. The correct option - # to use with these is +Maked; it writes dependencies to a file named - # 'foo.d', which lands next to the object file, wherever that - # happens to be. - # Much of this is similar to the tru64 case; see comments there. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir.libs/$base.d - "$@" -Wc,+Maked - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - "$@" +Maked - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" - # Add `dependent.h:' lines. - sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" "$tmpdepfile2" - ;; - -tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in `foo.d' instead, so we check for that too. - # Subdirectories are respected. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - - if test "$libtool" = yes; then - # With Tru64 cc, shared objects can also be used to make a - # static library. This mechanism is used in libtool 1.4 series to - # handle both shared and static libraries in a single compilation. - # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. - # - # With libtool 1.5 this exception was removed, and libtool now - # generates 2 separate objects for the 2 libraries. These two - # compilations output dependencies in $dir.libs/$base.o.d and - # in $dir$base.o.d. We have to check for both files, because - # one of the two compilations can be disabled. We should prefer - # $dir$base.o.d over $dir.libs/$base.o.d because the latter is - # automatically cleaned when .libs/ is deleted, while ignoring - # the former would cause a distcleancheck panic. - tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 - tmpdepfile2=$dir$base.o.d # libtool 1.5 - tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 - tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 - "$@" -Wc,-MD - else - tmpdepfile1=$dir$base.o.d - tmpdepfile2=$dir$base.d - tmpdepfile3=$dir$base.d - tmpdepfile4=$dir$base.d - "$@" -MD - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a tab and a space in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - test -z "$dashmflag" && dashmflag=-M - # Require at least two characters before searching for `:' - # in the target name. This is to cope with DOS-style filenames: - # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. - "$@" $dashmflag | - sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - tr ' ' ' -' < "$tmpdepfile" | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - "$@" || exit $? - # Remove any Libtool call - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - # X makedepend - shift - cleared=no - for arg in "$@"; do - case $cleared in - no) - set ""; shift - cleared=yes ;; - esac - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift ;; - # Strip any option that makedepend may not understand. Remove - # the object too, otherwise makedepend will parse it as a source file. - -*|$object) - ;; - *) - set fnord "$@" "$arg"; shift ;; - esac - done - obj_suffix="`echo $object | sed 's/^.*\././'`" - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - sed '1,2d' "$tmpdepfile" | tr ' ' ' -' | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - "$@" -E | - sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | - sed '$ s: \\$::' > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - "$@" || exit $? - IFS=" " - for arg - do - case "$arg" in - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; - *) - set fnord "$@" "$arg" - shift - shift - ;; - esac - done - "$@" -E | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" - echo " " >> "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/stamp-h.in b/stamp-h.in deleted file mode 100644 index 9788f7023..000000000 --- a/stamp-h.in +++ /dev/null @@ -1 +0,0 @@ -timestamp From c9b2f28b982f84b017eb48b1ba41135197c8a2e2 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sun, 5 Nov 2017 20:32:15 -0800 Subject: [PATCH 05/41] replace incompatible awk with C --- .gitignore | 3 + tests/tests-randomized/Makefile.am | 2 + tests/tests-randomized/check-bundles.sh | 9 +-- tests/tests-randomized/test-param-helper.c | 73 ++++++++++++++++++++++ 4 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 tests/tests-randomized/test-param-helper.c diff --git a/.gitignore b/.gitignore index c38ee7743..306fcf878 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,9 @@ stamp-h* /tests/tests-skeletons/check-* !/tests/tests-skeletons/check-*.c +# /tests/tests-randomized +/tests/tests-randomized/test-param-helper + # /doc/docsrc doc/docsrc/*.aux doc/docsrc/*.dvi diff --git a/tests/tests-randomized/Makefile.am b/tests/tests-randomized/Makefile.am index 9f1698b36..f6a04e2be 100644 --- a/tests/tests-randomized/Makefile.am +++ b/tests/tests-randomized/Makefile.am @@ -1,5 +1,6 @@ @CODE_COVERAGE_RULES@ +check_PROGRAMS = test-param-helper dist_check_SCRIPTS = check-bundles.sh #Filter out the coverage options from CFLAGS as we don't need @@ -19,6 +20,7 @@ TESTS_ENVIRONMENT= \ FUZZ_TIME="${FUZZ_TIME}" \ ASAN_ENV_FLAGS="@ASAN_ENV_FLAGS@" \ srcdir=${srcdir} \ + builddir=${builddir} \ abs_top_srcdir=${abs_top_srcdir} \ abs_top_builddir=${abs_top_builddir} \ ${srcdir}/check-bundles.sh diff --git a/tests/tests-randomized/check-bundles.sh b/tests/tests-randomized/check-bundles.sh index d3c7247b8..abf439c0c 100755 --- a/tests/tests-randomized/check-bundles.sh +++ b/tests/tests-randomized/check-bundles.sh @@ -29,6 +29,7 @@ usage() { RNDTEMP="${RNDTEMP:-.tmp.random}" srcdir="${srcdir:-.}" +builddir="${builddir:-.}" abs_top_srcdir="${abs_top_srcdir:-`pwd`/../../}" abs_top_builddir="${abs_top_builddir:-`pwd`/../../}" MAKE="${MAKE:-make}" @@ -140,13 +141,7 @@ get_param() { default="$2" asn="$3" - if nawk '' >/dev/null 2>&1 ; then - AWK=nawk - else - AWK=awk - fi - - echo "$asn" | ${AWK} "BEGIN{FS=\"[^${param}=0-9]+\"};/$param=/{for(i=1;i<=NF;i++)if(substr(\$i,0,length(\"${param}=\"))==\"${param}=\")PARAM=substr(\$i,length(\"${param}=\")+1)}END{if(PARAM)print PARAM;else print \"${default}\";}" + "${builddir}/test-param-helper" "${param}" "${default}" "${asn}" } # compile_and_test "" "" diff --git a/tests/tests-randomized/test-param-helper.c b/tests/tests-randomized/test-param-helper.c new file mode 100644 index 000000000..ed8118601 --- /dev/null +++ b/tests/tests-randomized/test-param-helper.c @@ -0,0 +1,73 @@ +/* + * Since working awk is not present on every supported platform + * (notably Solaris), and nawk is not the same on Solaris and Linux, + * this program is a replacement for it to extract test parameter from the. + * string specified in the command line. + */ +#include +#include +#include +#include + +static void +usage(const char *progname) { + fprintf(stderr, "Search PARAM=VALUE pattern in the given string\n"); + fprintf(stderr, "Usage: %s \n", + progname); +} + +static const char * +search(const char *param, const char *haystack) { + + const char *p = strstr(haystack, param); + if(p && p[strlen(param)] == '=') { + const char *param_begin = &p[strlen(param) + 1]; + const char *param_end = param_begin; + for(param_end = param_begin; param_end; param_end++) { + switch(*param_end) { + case '0' ... '9': + continue; + default: + break; + } + break; + } + + static char static_buf[64]; + + if((param_end - param_begin) <= 0) { + fprintf(stderr, "Parameter %s is malformed after '='\n", param); + return NULL; + } + + if((param_end - param_begin) >= (ssize_t)sizeof(static_buf)) { + fprintf(stderr, "Parameter %s value exceeds buffer size %zu\n", + param, sizeof(static_buf)); + return NULL; + } + + memcpy(static_buf, param_begin, param_end - param_begin); + static_buf[param_end - param_begin] = '\0'; + return static_buf; + } else if(p) { + fprintf(stderr, "Parameter %s should contain '='\n", param); + return NULL; + } + + return NULL; +} + +int +main(int ac, char **av) { + if(ac != 4) { + usage(av[0]); + exit(EX_USAGE); + } + + const char *value = search(av[1], av[3]); + if(value) { + printf("%s\n", value); + } else { + printf("%s\n", av[2]); + } +} From ce2068a50757c3607117583bdf7e0765c56a8f82 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sun, 5 Nov 2017 21:08:57 -0800 Subject: [PATCH 06/41] fix builddir --- tests/tests-randomized/Makefile.am | 2 +- tests/tests-randomized/check-bundles.sh | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/tests-randomized/Makefile.am b/tests/tests-randomized/Makefile.am index f6a04e2be..99267a150 100644 --- a/tests/tests-randomized/Makefile.am +++ b/tests/tests-randomized/Makefile.am @@ -20,7 +20,7 @@ TESTS_ENVIRONMENT= \ FUZZ_TIME="${FUZZ_TIME}" \ ASAN_ENV_FLAGS="@ASAN_ENV_FLAGS@" \ srcdir=${srcdir} \ - builddir=${builddir} \ + abs_builddir=${abs_builddir} \ abs_top_srcdir=${abs_top_srcdir} \ abs_top_builddir=${abs_top_builddir} \ ${srcdir}/check-bundles.sh diff --git a/tests/tests-randomized/check-bundles.sh b/tests/tests-randomized/check-bundles.sh index abf439c0c..5cf892fc6 100755 --- a/tests/tests-randomized/check-bundles.sh +++ b/tests/tests-randomized/check-bundles.sh @@ -29,9 +29,10 @@ usage() { RNDTEMP="${RNDTEMP:-.tmp.random}" srcdir="${srcdir:-.}" -builddir="${builddir:-.}" abs_top_srcdir="${abs_top_srcdir:-`pwd`/../../}" abs_top_builddir="${abs_top_builddir:-`pwd`/../../}" +abs_builddir="${abs_builddir:-`pwd`}" +export abs_builddir MAKE="${MAKE:-make}" FUZZ_TIME="${FUZZ_TIME:-10}" @@ -141,7 +142,7 @@ get_param() { default="$2" asn="$3" - "${builddir}/test-param-helper" "${param}" "${default}" "${asn}" + "${abs_builddir}/test-param-helper" "${param}" "${default}" "${asn}" } # compile_and_test "" "" From 8baaf6b0d23812b0ac629fb7a40c905841c21b29 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sun, 5 Nov 2017 21:39:58 -0800 Subject: [PATCH 07/41] fix randomized failures on fast enough systems --- tests/tests-randomized/check-bundles.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests-randomized/check-bundles.sh b/tests/tests-randomized/check-bundles.sh index 5cf892fc6..27c95429f 100755 --- a/tests/tests-randomized/check-bundles.sh +++ b/tests/tests-randomized/check-bundles.sh @@ -60,7 +60,7 @@ make_clean_before_test() { # critical portion of the objects. This will reach our objective # of fast compile times (since most of skeletons are not recompiled), # but won't yield a stale T.o object where newer T.c source exists. - rm -f T.o || : + rm -f T.o libasncodec.a || : fi } From 3bcab4ebfa76609589cf58630144131aff351f88 Mon Sep 17 00:00:00 2001 From: Jon Ringle Date: Thu, 2 Nov 2017 17:05:15 -0400 Subject: [PATCH 08/41] Add test case for issue #178 --- .../158-sequence-of-sequence-nested-OK.asn1 | 24 ++ ...-sequence-nested-OK.asn1.-Pfcompound-names | 269 ++++++++++++++++++ tests/tests-c-compiler/Makefile.am | 4 + .../check-src/check-158.-fcompound-names.c | 24 ++ 4 files changed, 321 insertions(+) create mode 100644 tests/tests-asn1c-compiler/158-sequence-of-sequence-nested-OK.asn1 create mode 100644 tests/tests-asn1c-compiler/158-sequence-of-sequence-nested-OK.asn1.-Pfcompound-names create mode 100644 tests/tests-c-compiler/check-src/check-158.-fcompound-names.c diff --git a/tests/tests-asn1c-compiler/158-sequence-of-sequence-nested-OK.asn1 b/tests/tests-asn1c-compiler/158-sequence-of-sequence-nested-OK.asn1 new file mode 100644 index 000000000..16de4fab8 --- /dev/null +++ b/tests/tests-asn1c-compiler/158-sequence-of-sequence-nested-OK.asn1 @@ -0,0 +1,24 @@ + +-- OK: Everything is fine + +-- iso.org.dod.internet.private.enterprise (1.3.6.1.4.1) +-- .spelio.software.asn1c.test (9363.1.5.1) +-- .158 + +ModuleTestSequenceOfSequenceNested + { iso org(3) dod(6) internet(1) private(4) enterprise(1) + spelio(9363) software(1) asn1c(5) test(1) 158 } + DEFINITIONS IMPLICIT TAGS ::= +BEGIN + + SeqWithNestedSOS ::= SEQUENCE { + someString [0] UTF8String, + sos [1] SEQUENCE OF SEQUENCE { + anotherString [2] UTF8String, + nested-sos [3] SEQUENCE OF SEQUENCE { + nested-string [4] UTF8String + } + } + } + +END diff --git a/tests/tests-asn1c-compiler/158-sequence-of-sequence-nested-OK.asn1.-Pfcompound-names b/tests/tests-asn1c-compiler/158-sequence-of-sequence-nested-OK.asn1.-Pfcompound-names new file mode 100644 index 000000000..9e98f3465 --- /dev/null +++ b/tests/tests-asn1c-compiler/158-sequence-of-sequence-nested-OK.asn1.-Pfcompound-names @@ -0,0 +1,269 @@ + +/*** <<< INCLUDES [SeqWithNestedSOS] >>> ***/ + +#include +#include +#include +#include + +/*** <<< FWD-DEFS [SeqWithNestedSOS] >>> ***/ + +typedef struct SeqWithNestedSOS__sos__Member { + UTF8String_t anotherString; + struct SeqWithNestedSOS__sos__Member__nested_sos { + A_SEQUENCE_OF(typedef struct SeqWithNestedSOS__sos__Member__nested_sos__Member { + UTF8String_t nested_string; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; + } SeqWithNestedSOS__sos__Member__nested_sos__Member; + SeqWithNestedSOS__sos__Member__nested_sos__Member) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; + } nested_sos; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} SeqWithNestedSOS__sos__Member; + +/*** <<< TYPE-DECLS [SeqWithNestedSOS] >>> ***/ + +typedef struct SeqWithNestedSOS { + UTF8String_t someString; + struct SeqWithNestedSOS__sos { + A_SEQUENCE_OF(SeqWithNestedSOS__sos__Member) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; + } sos; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} SeqWithNestedSOS_t; + +/*** <<< FUNC-DECLS [SeqWithNestedSOS] >>> ***/ + +extern asn_TYPE_descriptor_t asn_DEF_SeqWithNestedSOS; + +/*** <<< STAT-DEFS [SeqWithNestedSOS] >>> ***/ + +static asn_TYPE_member_t asn_MBR_Member_7[] = { + { ATF_NOFLAGS, 0, offsetof(struct SeqWithNestedSOS__sos__Member__nested_sos__Member, nested_string), + .tag = (ASN_TAG_CLASS_CONTEXT | (4 << 2)), + .tag_mode = -1, /* IMPLICIT tag at current level */ + .type = &asn_DEF_UTF8String, + .type_selector = 0, + { .oer_constraints = 0, .per_constraints = 0, .general_constraints = 0 }, + 0, 0, /* No default value */ + .name = "nested-string" + }, +}; +static const ber_tlv_tag_t asn_DEF_Member_tags_7[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static const asn_TYPE_tag2member_t asn_MAP_Member_tag2el_7[] = { + { (ASN_TAG_CLASS_CONTEXT | (4 << 2)), 0, 0, 0 } /* nested-string */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_Member_specs_7 = { + sizeof(struct SeqWithNestedSOS__sos__Member__nested_sos__Member), + offsetof(struct SeqWithNestedSOS__sos__Member__nested_sos__Member, _asn_ctx), + .tag2el = asn_MAP_Member_tag2el_7, + .tag2el_count = 1, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* First extension addition */ +}; +static /* Use -fall-defs-global to expose */ +asn_TYPE_descriptor_t asn_DEF_Member_7 = { + "SEQUENCE", + "SEQUENCE", + &asn_OP_SEQUENCE, + asn_DEF_Member_tags_7, + sizeof(asn_DEF_Member_tags_7) + /sizeof(asn_DEF_Member_tags_7[0]), /* 1 */ + asn_DEF_Member_tags_7, /* Same as above */ + sizeof(asn_DEF_Member_tags_7) + /sizeof(asn_DEF_Member_tags_7[0]), /* 1 */ + { 0, 0, SEQUENCE_constraint }, + asn_MBR_Member_7, + 1, /* Elements count */ + &asn_SPC_Member_specs_7 /* Additional specs */ +}; + +static asn_TYPE_member_t asn_MBR_nested_sos_6[] = { + { ATF_POINTER, 0, 0, + .tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), + .tag_mode = 0, + .type = &asn_DEF_Member_7, + .type_selector = 0, + { .oer_constraints = 0, .per_constraints = 0, .general_constraints = 0 }, + 0, 0, /* No default value */ + .name = "" + }, +}; +static const ber_tlv_tag_t asn_DEF_nested_sos_tags_6[] = { + (ASN_TAG_CLASS_CONTEXT | (3 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_SET_OF_specifics_t asn_SPC_nested_sos_specs_6 = { + sizeof(struct SeqWithNestedSOS__sos__Member__nested_sos), + offsetof(struct SeqWithNestedSOS__sos__Member__nested_sos, _asn_ctx), + 0, /* XER encoding is XMLDelimitedItemList */ +}; +static /* Use -fall-defs-global to expose */ +asn_TYPE_descriptor_t asn_DEF_nested_sos_6 = { + "nested-sos", + "nested-sos", + &asn_OP_SEQUENCE_OF, + asn_DEF_nested_sos_tags_6, + sizeof(asn_DEF_nested_sos_tags_6) + /sizeof(asn_DEF_nested_sos_tags_6[0]) - 1, /* 1 */ + asn_DEF_nested_sos_tags_6, /* Same as above */ + sizeof(asn_DEF_nested_sos_tags_6) + /sizeof(asn_DEF_nested_sos_tags_6[0]), /* 2 */ + { 0, 0, SEQUENCE_OF_constraint }, + asn_MBR_nested_sos_6, + 1, /* Single element */ + &asn_SPC_nested_sos_specs_6 /* Additional specs */ +}; + +static asn_TYPE_member_t asn_MBR_Member_4[] = { + { ATF_NOFLAGS, 0, offsetof(struct SeqWithNestedSOS__sos__Member, anotherString), + .tag = (ASN_TAG_CLASS_CONTEXT | (2 << 2)), + .tag_mode = -1, /* IMPLICIT tag at current level */ + .type = &asn_DEF_UTF8String, + .type_selector = 0, + { .oer_constraints = 0, .per_constraints = 0, .general_constraints = 0 }, + 0, 0, /* No default value */ + .name = "anotherString" + }, + { ATF_NOFLAGS, 0, offsetof(struct SeqWithNestedSOS__sos__Member, nested_sos), + .tag = (ASN_TAG_CLASS_CONTEXT | (3 << 2)), + .tag_mode = 0, + .type = &asn_DEF_nested_sos_6, + .type_selector = 0, + { .oer_constraints = 0, .per_constraints = 0, .general_constraints = 0 }, + 0, 0, /* No default value */ + .name = "nested-sos" + }, +}; +static const ber_tlv_tag_t asn_DEF_Member_tags_4[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static const asn_TYPE_tag2member_t asn_MAP_Member_tag2el_4[] = { + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 0, 0, 0 }, /* anotherString */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 1, 0, 0 } /* nested-sos */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_Member_specs_4 = { + sizeof(struct SeqWithNestedSOS__sos__Member), + offsetof(struct SeqWithNestedSOS__sos__Member, _asn_ctx), + .tag2el = asn_MAP_Member_tag2el_4, + .tag2el_count = 2, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* First extension addition */ +}; +static /* Use -fall-defs-global to expose */ +asn_TYPE_descriptor_t asn_DEF_Member_4 = { + "SEQUENCE", + "SEQUENCE", + &asn_OP_SEQUENCE, + asn_DEF_Member_tags_4, + sizeof(asn_DEF_Member_tags_4) + /sizeof(asn_DEF_Member_tags_4[0]), /* 1 */ + asn_DEF_Member_tags_4, /* Same as above */ + sizeof(asn_DEF_Member_tags_4) + /sizeof(asn_DEF_Member_tags_4[0]), /* 1 */ + { 0, 0, SEQUENCE_constraint }, + asn_MBR_Member_4, + 2, /* Elements count */ + &asn_SPC_Member_specs_4 /* Additional specs */ +}; + +static asn_TYPE_member_t asn_MBR_sos_3[] = { + { ATF_POINTER, 0, 0, + .tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), + .tag_mode = 0, + .type = &asn_DEF_Member_4, + .type_selector = 0, + { .oer_constraints = 0, .per_constraints = 0, .general_constraints = 0 }, + 0, 0, /* No default value */ + .name = "" + }, +}; +static const ber_tlv_tag_t asn_DEF_sos_tags_3[] = { + (ASN_TAG_CLASS_CONTEXT | (1 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_SET_OF_specifics_t asn_SPC_sos_specs_3 = { + sizeof(struct SeqWithNestedSOS__sos), + offsetof(struct SeqWithNestedSOS__sos, _asn_ctx), + 0, /* XER encoding is XMLDelimitedItemList */ +}; +static /* Use -fall-defs-global to expose */ +asn_TYPE_descriptor_t asn_DEF_sos_3 = { + "sos", + "sos", + &asn_OP_SEQUENCE_OF, + asn_DEF_sos_tags_3, + sizeof(asn_DEF_sos_tags_3) + /sizeof(asn_DEF_sos_tags_3[0]) - 1, /* 1 */ + asn_DEF_sos_tags_3, /* Same as above */ + sizeof(asn_DEF_sos_tags_3) + /sizeof(asn_DEF_sos_tags_3[0]), /* 2 */ + { 0, 0, SEQUENCE_OF_constraint }, + asn_MBR_sos_3, + 1, /* Single element */ + &asn_SPC_sos_specs_3 /* Additional specs */ +}; + +static asn_TYPE_member_t asn_MBR_SeqWithNestedSOS_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct SeqWithNestedSOS, someString), + .tag = (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + .tag_mode = -1, /* IMPLICIT tag at current level */ + .type = &asn_DEF_UTF8String, + .type_selector = 0, + { .oer_constraints = 0, .per_constraints = 0, .general_constraints = 0 }, + 0, 0, /* No default value */ + .name = "someString" + }, + { ATF_NOFLAGS, 0, offsetof(struct SeqWithNestedSOS, sos), + .tag = (ASN_TAG_CLASS_CONTEXT | (1 << 2)), + .tag_mode = 0, + .type = &asn_DEF_sos_3, + .type_selector = 0, + { .oer_constraints = 0, .per_constraints = 0, .general_constraints = 0 }, + 0, 0, /* No default value */ + .name = "sos" + }, +}; +static const ber_tlv_tag_t asn_DEF_SeqWithNestedSOS_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static const asn_TYPE_tag2member_t asn_MAP_SeqWithNestedSOS_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* someString */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* sos */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_SeqWithNestedSOS_specs_1 = { + sizeof(struct SeqWithNestedSOS), + offsetof(struct SeqWithNestedSOS, _asn_ctx), + .tag2el = asn_MAP_SeqWithNestedSOS_tag2el_1, + .tag2el_count = 2, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* First extension addition */ +}; +asn_TYPE_descriptor_t asn_DEF_SeqWithNestedSOS = { + "SeqWithNestedSOS", + "SeqWithNestedSOS", + &asn_OP_SEQUENCE, + asn_DEF_SeqWithNestedSOS_tags_1, + sizeof(asn_DEF_SeqWithNestedSOS_tags_1) + /sizeof(asn_DEF_SeqWithNestedSOS_tags_1[0]), /* 1 */ + asn_DEF_SeqWithNestedSOS_tags_1, /* Same as above */ + sizeof(asn_DEF_SeqWithNestedSOS_tags_1) + /sizeof(asn_DEF_SeqWithNestedSOS_tags_1[0]), /* 1 */ + { 0, 0, SEQUENCE_constraint }, + asn_MBR_SeqWithNestedSOS_1, + 2, /* Elements count */ + &asn_SPC_SeqWithNestedSOS_specs_1 /* Additional specs */ +}; + diff --git a/tests/tests-c-compiler/Makefile.am b/tests/tests-c-compiler/Makefile.am index 832d90886..19d5915f2 100644 --- a/tests/tests-c-compiler/Makefile.am +++ b/tests/tests-c-compiler/Makefile.am @@ -60,12 +60,16 @@ TESTS += check-src/check-72.-fcompound-names.c TESTS += check-src/check-73.c TESTS += check-src/check-92.-findirect-choice.c TESTS += check-src/check-92.c +TESTS += check-src/check-158.-fcompound-names.c if TEST_64BIT TESTS += check-src/check64-134.-gen-PER.c TESTS += check-src/check64-136.-gen-OER.c endif +XFAIL_TESTS = +XFAIL_TESTS += check-src/check-158.-fcompound-names.c + EXTRA_DIST = \ data-62 \ data-70 \ diff --git a/tests/tests-c-compiler/check-src/check-158.-fcompound-names.c b/tests/tests-c-compiler/check-src/check-158.-fcompound-names.c new file mode 100644 index 000000000..322742d11 --- /dev/null +++ b/tests/tests-c-compiler/check-src/check-158.-fcompound-names.c @@ -0,0 +1,24 @@ +#undef NDEBUG +#include +#include +#include +#include +#include + +#include + +int +main(int ac, char **av) { + Type_t t; + + (void)ac; /* Unused argument */ + (void)av; /* Unused argument */ + + memset(&t, 0, sizeof(t)); + + /* + * No plans to fill it up: just checking whether it compiles or not. + */ + + return 0; +} From adfcde29cdba95a9b8a765adf2231963c638ff75 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sun, 5 Nov 2017 22:45:54 -0800 Subject: [PATCH 09/41] generic hashing mechanism --- libasn1common/Makefile.am | 3 +- libasn1common/genhash.c | 811 ++++++++++++++++++++++++++++++++++++++ libasn1common/genhash.h | 230 +++++++++++ 3 files changed, 1043 insertions(+), 1 deletion(-) create mode 100644 libasn1common/genhash.c create mode 100644 libasn1common/genhash.h diff --git a/libasn1common/Makefile.am b/libasn1common/Makefile.am index 92ef8d51f..78f05fd27 100644 --- a/libasn1common/Makefile.am +++ b/libasn1common/Makefile.am @@ -7,5 +7,6 @@ noinst_LTLIBRARIES = libasn1common.la libasn1common_la_SOURCES = \ asn1_ref.c asn1_ref.h \ asn1_buffer.c asn1_buffer.h \ - asn1_namespace.c asn1_namespace.h + asn1_namespace.c asn1_namespace.h \ + genhash.c genhash.h diff --git a/libasn1common/genhash.c b/libasn1common/genhash.c new file mode 100644 index 000000000..275e23e23 --- /dev/null +++ b/libasn1common/genhash.c @@ -0,0 +1,811 @@ +/* + * Copyright (c) 2002-2005 Lev Walkin . All rights reserved. + * Copyright (c) 2001-2004 Netli, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: genhash.c 447 2005-06-07 06:51:10Z vlm $ + */ +/* + * Implementation of a hash data structure. + * This particular implementation is supposed to be space-efficient + * particularly in the case of tiny number of hash elements. + * It also has an aggressive hash buckets expanding technique, which allows + * to deal with increasing number of elements without a loss of search speed. + * + * Generally, one structure of type genhash_t is allocated per hash set. + * This structure is supposed to hold all information related to the current + * set, and also holds a tiny number of hash elements, when hash hasn't yet + * grown up. When the number of elements reaches some point, part of the + * genhash_t structure is reused to contain the pointers to the actual + * hash buckets and LRU (Least Recently Used) list's head and tail. + * Elements which were held inside genhash_t will be moved to the hash buckets. + * + * Said above effectively means two modes of operation: TINY and NORMAL. + * They can be distinguished by examining the h->numbuckets value, which + * is 0 for TINY and greater for NORMAL mode. + * + * In the TINY mode we use a lower part of the genhash_t structure + * (lower 32 bytes from 64 bytes of genhash_t) to hold up to IH_VALUE (4) + * key/value pairs. + * + * In the NORMAL mode we use the lower part of the genhash_t structure + * to hold a set of pointers, including a pointer to the hash buckets. + * We agressively expand hash buckets size when adding new elements + * to lower the number of key comparisons. + */ + +#include +#include +#include +#include +#include +#include "genhash.h" + +/* 1M entries, 4M RAM */ +#define DEFAULT_MAXIMUM_HASH_BUCKETS_NUMBER (1024 * 1024) +static int maximum_hash_buckets_number = DEFAULT_MAXIMUM_HASH_BUCKETS_NUMBER; + +/* + * A single hash element structure which binds a value to its key. + */ +typedef struct genhash_el_s { + unsigned int key_hash; /* Saved hash of the key */ + void *key; + void *value; + struct genhash_el_s *hash_next; /* Collision list inside the bucket */ + struct genhash_el_s *hash_prev; + struct genhash_el_s *lru_prev; /* Per-hash LRU list */ + struct genhash_el_s *lru_next; +} genhash_el; + +/* + * A hash structure with buckets etc. + */ +struct genhash_s { + int (*keycmpf) (const void *lkey1, const void *rkey2); + unsigned int (*keyhashf) (const void *key); /* hash function */ + void (*keydestroyf) (void *key); /* key destructor */ + void (*valuedestroyf) (void *value); /* value destructor */ + + int numelements; /* Total number of hash elements */ + int numbuckets; /* 0 means "use _TINY" */ + int lru_limit; /* Must be initialized explicitly */ + genhash_iter_t *iters; /* Active iterators */ + + /* 32-byte boundary here */ + + union { +#define IH_VALUES 4 /* Internally held key/value pairs for TINY mode */ + struct _internal_tiny_s { + void *keys[IH_VALUES]; + void *values[IH_VALUES]; + } _TINY; /* 32-byte structure */ + struct _internal_normal_s { + genhash_el *lru_head; /* LRU list head */ + genhash_el *lru_tail; /* LRU list tail */ + genhash_el **buckets; /* Hash buckets */ + /* void *unused; */ + } _NORMAL; + } un; +#define tiny_keys un._TINY.keys +#define tiny_values un._TINY.values +#define lru_head un._NORMAL.lru_head +#define lru_tail un._NORMAL.lru_tail +#define buckets un._NORMAL.buckets +}; + + +static int +_genhash_normal_add(genhash_t *h, genhash_el *el, void *key, void *value); + + +genhash_t * +genhash_new( + int (*keycmpf) (const void *key1, const void *key2), + unsigned int (*keyhashf) (const void *key), + void (*keydestroyf) (void *key), + void (*valuedestroyf) (void *value) +) { + genhash_t *h; + + h = (genhash_t *)malloc(sizeof(genhash_t)); + if (!h) + return NULL; + + memset(h, 0, sizeof(genhash_t)); + + genhash_reinit(h, keycmpf, keyhashf, keydestroyf, valuedestroyf); + + return h; +} + +int +genhash_reinit( + genhash_t *h, + int (*keycmpf) (const void *key1, const void *key2), + unsigned int (*keyhashf) (const void *key), + void (*keydestroyf) (void *key), + void (*valuedestroyf) (void *value) +) { + + assert(keycmpf && keyhashf); + + h->keycmpf = keycmpf; + h->keyhashf = keyhashf; + h->keydestroyf = keydestroyf; + h->valuedestroyf = valuedestroyf; + + return 0; +} + +int +genhash_count(genhash_t *h) { + if(h) { + return h->numelements; + } else { + return 0; + } +} + + +static void +_remove_normal_hash_el(genhash_t *h, genhash_el *el) { + genhash_iter_t *iter; + void *kd_arg; + void *vd_arg; + + /* Remove from the collision list */ + if (el->hash_prev) { + if((el->hash_prev->hash_next = el->hash_next)) + el->hash_next->hash_prev = el->hash_prev; + + } else { + if((h->buckets[el->key_hash % h->numbuckets] = el->hash_next)) + el->hash_next->hash_prev = NULL; + } + + /* Remove from LRU list */ + if(el->lru_prev) { + if((el->lru_prev->lru_next = el->lru_next)) + el->lru_next->lru_prev = el->lru_prev; + else + h->lru_tail = el->lru_prev; + } else { + if(h->lru_head == el) { + if((h->lru_head = el->lru_next) == NULL) + h->lru_tail = NULL; + else + h->lru_head->lru_prev = NULL; + } + } + + /* Remember key and value */ + kd_arg = el->key; + vd_arg = el->value; + + /* Move iterators off the element being deleted */ + for(iter = h->iters; iter; iter = iter->iter_next) { + assert(iter->hash_ptr == h); + if(iter->un.location == el) { + iter->un.location = iter->order_lru_first + ? el->lru_prev : el->lru_next; + } + } + + free(el); + h->numelements--; + + /* Remove key and value */ + if (h->keydestroyf) h->keydestroyf(kd_arg); + if (h->valuedestroyf) h->valuedestroyf(vd_arg); +} + +static inline void +_genhash_normal_el_move2top(genhash_t *h, genhash_el *el) { + + /* Disable sorting if iterators are running */ + if(h->iters) return; + + /* Move to the top of the hash bucket */ + if(el->hash_prev) { + int bucket = el->key_hash % h->numbuckets; + + /* Remove from the current location */ + if((el->hash_prev->hash_next = el->hash_next)) + el->hash_next->hash_prev = el->hash_prev; + + /* Move to the top of the hash bucket */ + if((el->hash_next = h->buckets[bucket])) + el->hash_next->hash_prev = el; + h->buckets[bucket] = el; + el->hash_prev = NULL; + } + + /* Move to the top of LRU list */ + if(h->lru_limit && el->lru_prev) { + + /* Remove from current location */ + if((el->lru_prev->lru_next = el->lru_next)) + el->lru_next->lru_prev = el->lru_prev; + else + h->lru_tail = el->lru_prev; + + /* Append to the head */ + el->lru_prev = NULL; + h->lru_head->lru_prev = el; + el->lru_next = h->lru_head; + h->lru_head = el; + } +} + +static int +_expand_hash(genhash_t *h) { + int newbuckets_count; + genhash_el **newbuckets; + + /* + * Compute a new number of buckets value. + */ + if(h->numbuckets) { + newbuckets_count = h->numbuckets << 2; + /* Too big hash table */ + if(newbuckets_count > maximum_hash_buckets_number) { + if(h->numbuckets < maximum_hash_buckets_number) { + newbuckets_count = maximum_hash_buckets_number; + } else { + /* No need to set errno here. */ + return -1; + } + } + } else { + /* 8 buckets -> 32 bytes of memory */ + newbuckets_count = IH_VALUES << 1; + if(newbuckets_count > maximum_hash_buckets_number) { + if(maximum_hash_buckets_number) { + newbuckets_count = maximum_hash_buckets_number; + } else { + /* Allowed to store only IH_VALUES elements */ + errno = EPERM; + return -1; + } + } + } + + /* + * Allocate a new storage for buckets. + */ + newbuckets = malloc(newbuckets_count * sizeof(*newbuckets)); + if(newbuckets) { + memset(newbuckets, 0, newbuckets_count * sizeof(*newbuckets)); + } else { + return -1; + } + + if(h->numbuckets) { + genhash_el *el; + int bucket; + + /* + * Rehash elements from old h->buckets to newbuckets. + * No need to touch LRU pointers and other stuff - it is okay. + */ + for(el = h->lru_tail; el; el = el->lru_prev) { + bucket = el->key_hash % newbuckets_count; + el->hash_prev = NULL; + if((el->hash_next = newbuckets[bucket])) + el->hash_next->hash_prev = el; + newbuckets[bucket] = el; + } + + free(h->buckets); + h->buckets = newbuckets; + h->numbuckets = newbuckets_count; + } else { + /* + * Moving from inline tiny storage into buckets. + */ + genhash_el *els[IH_VALUES] = { NULL }; + struct _internal_tiny_s tiny_substruct; + int i; + int saved_numelements; + int saved_lru_limit; + genhash_iter_t *iter; + + /* Pre-allocate hash elements (for "undo") */ + for(i = 0; i < h->numelements; i++) { + els[i] = (genhash_el *)malloc(sizeof(genhash_el)); + if(els[i] == NULL) { + for(i = 0; i < h->numelements; i++) + if(els[i]) + free(els[i]); + free(newbuckets); + return -1; + } + } + + /* Save part of the union */ + tiny_substruct = h->un._TINY; + /* Re-initialize this part in NORMAL model */ + memset(&h->un._NORMAL, 0, sizeof(h->un._NORMAL)); + + /* There was no allocated buckets, when in tiny hash mode. */ + h->buckets = newbuckets; + h->numbuckets = newbuckets_count; + + saved_numelements = h->numelements; + saved_lru_limit = h->lru_limit; + h->numelements = 0; + h->lru_limit = 0; /* Disable LRU expiration for a while */ + + for(i = saved_numelements - 1; i >= 0; --i) { + /* + * genhash_normal_add won't fail, if we supply + * an already allocated genhash_el *. + */ + (void)_genhash_normal_add(h, els[i], + tiny_substruct.keys[i], + tiny_substruct.values[i]); + } + + /* Now, scan through iterators and convert them TINY->NORMAL */ + for(iter = h->iters; iter; iter = iter->iter_next) { + assert(iter->hash_ptr == h); + if(iter->un.item_number < 0 + || iter->un.item_number >= saved_numelements) { + iter->un.location = 0; + } else { + iter->un.location = els[iter->un.item_number]; + } + } + + h->lru_limit = saved_lru_limit; + } + + return 0; +} + +/* + * Won't return with error if el is provided. + */ +static int +_genhash_normal_add(genhash_t *h, genhash_el *el, void *key, void *value) { + genhash_el **bucket; + + if(el == NULL) { + el = malloc(sizeof (*el)); + if(el == NULL) { + /* Errno will be set by malloc() */ + return -1; + } + } + + /* Maintain maximum number of entries */ + if(h->lru_limit) { + while(h->numelements >= h->lru_limit) + _remove_normal_hash_el(h, h->lru_tail); + } + + memset(el, 0, sizeof(genhash_el)); + + /* Compute the index of the collision list */ + el->key_hash = h->keyhashf(key); + bucket = &h->buckets[el->key_hash % h->numbuckets]; + + el->key = key; + el->value = value; + + /* + * Add to the collision list + */ + el->hash_prev = NULL; + if((el->hash_next = *bucket)) + (*bucket)->hash_prev = el; + *bucket = el; + + /* + * Add to the LRU list. + */ + if(h->lru_head) { + el->lru_next = h->lru_head; + el->lru_next->lru_prev = el; + h->lru_head = el; + } else { + h->lru_head = el; + h->lru_tail = el; + } + + h->numelements++; + + return 0; +} + + +int +genhash_add(genhash_t *h, void *key, void *value) { + + if(key == NULL) { + errno = EINVAL; + return -1; + } + + if(h->numbuckets == 0) { + + /* We have a tiny internally-held set of elements */ + if(h->numelements < IH_VALUES) { + h->tiny_keys[h->numelements] = key; + h->tiny_values[h->numelements] = value; + h->numelements++; + return 0; + } + + if(_expand_hash(h) == -1) + return -1; + + } else { + + if((h->numelements / h->numbuckets) > 2) + (void)_expand_hash(h); + } + + return _genhash_normal_add(h, NULL, key, value); +} + +int +genhash_addunique(genhash_t *h, void *key, void *value) { + if(genhash_get(h, key)) { + errno = EEXIST; + return -1; + } + return genhash_add(h, key, value); +} + +void * +genhash_get(genhash_t *h, const void *key) { + + if(h->numbuckets) { + + genhash_el *walk; + int bucket = h->keyhashf(key) % h->numbuckets; + + for(walk = h->buckets[bucket]; + walk; walk = walk->hash_next) { + + if (h->keycmpf(walk->key, key) == 0) { + _genhash_normal_el_move2top(h, walk); + return walk->value; + } + } + + } else { + /* TINY mode */ + int i; + + assert(h->numelements <= IH_VALUES); + for(i = 0; i < h->numelements; i++) { + if(h->keycmpf(h->tiny_keys[i], key) == 0) + /* Don't reorder in TINY mode */ + return h->tiny_values[i]; + } + + } + + errno = ESRCH; + return NULL; +} + +int +genhash_del(genhash_t *h, void *key) { + + if(h->numbuckets) { + /* NORMAL mode */ + genhash_el *walk; + int bucket; + + if(h->numelements == 0) { + errno = ESRCH; + return -1; /* not found */ + } + + bucket = h->keyhashf(key) % h->numbuckets; + + for(walk = h->buckets[bucket]; walk; walk = walk->hash_next) + if(h->keycmpf(walk->key, key) == 0) + break; + + if(walk) { + _remove_normal_hash_el(h, walk); + return 0; + } + } else { + /* TINY mode */ + int i; + + /* Look for matching key */ + for(i = 0; i < h->numelements; i++) + if(h->keycmpf(h->tiny_keys[i], key) == 0) + break; + + if(i < h->numelements) { + /* Remember values */ + void *kd_arg = h->tiny_keys[i]; + void *vd_arg = h->tiny_values[i]; + + h->numelements--; + + if(h->iters) { + /* If iterators are involved, we have to + * shift elements to maintain iteration order + * and avoid duplications */ + genhash_iter_t *iter; + memmove(&h->tiny_keys[i], + &h->tiny_keys[i+1], + (h->numelements - i) + * sizeof(h->tiny_keys[0])); + memmove(&h->tiny_values[i], + &h->tiny_values[i+1], + (h->numelements - i) + * sizeof(h->tiny_values[0])); + /* Shift the iterator's indexes */ + for(iter = h->iters; iter; + iter = iter->iter_next) { + int in = iter->un.item_number; + if(iter->order_lru_first) { + if(in > i) + iter->un.item_number--; + } else { + if(in >= i) + iter->un.item_number--; + } + } + } else { + /* Substitute it with the last one */ + /* No harm if overwriting itself */ + h->tiny_keys[i] = h->tiny_keys[h->numelements]; + h->tiny_values[i] = h->tiny_values[h->numelements]; + } + h->tiny_keys[h->numelements] = 0; + h->tiny_values[h->numelements] = 0; + /* Delete for real */ + if(h->keydestroyf) h->keydestroyf(kd_arg); + if(h->valuedestroyf) h->valuedestroyf(vd_arg); + return 0; + } + } + + errno = ESRCH; + return -1; +} + +/* + * Initialize a hash iterator. + */ +int +genhash_iter_init(genhash_iter_t *iter, genhash_t *h, int reverse_order) { + + iter->hash_ptr = h; + iter->iter_prev = 0; /* Add itself to the iterators list */ + iter->iter_next = h->iters; + h->iters = iter; + iter->order_lru_first = reverse_order; + + if(h->numbuckets) { + /* NORMAL mode */ + if(reverse_order) { + /* Least recent first order */ + iter->un.location = h->lru_tail; + } else { + /* Most recent first order */ + iter->un.location = h->lru_head; + } + } else { + /* TINY mode */ + if(reverse_order) { + iter->un.item_number = 0; + } else { + iter->un.item_number = h->numelements - 1; + } + } + + return h->numelements; +} + +int +genhash_iter(genhash_iter_t *iter, void *key_p, void *val_p) { + void **key = key_p; + void **val = val_p; + genhash_t *h = iter->hash_ptr; + + if(h->numbuckets) { + /* NORMAL mode */ + genhash_el *cur_el = iter->un.location; + if(!cur_el) + /* Already finished */ + return 0; + + if(key) *key = cur_el->key; + if(val) *val = cur_el->value; + + /* Move pointer to the next hash element */ + iter->un.location = iter->order_lru_first + ? cur_el->lru_prev : cur_el->lru_next; + } else { + /* TINY mode */ + if(iter->un.item_number < 0 + || iter->un.item_number >= h->numelements + || h->tiny_keys[iter->un.item_number] == 0) + return 0; + + if(key) *key = h->tiny_keys[iter->un.item_number]; + if(val) *val = h->tiny_values[iter->un.item_number]; + + /* Advance to the next element */ + if(iter->order_lru_first) + iter->un.item_number++; + else + iter->un.item_number--; + } + + + return 1; +} + +void +genhash_iter_done(genhash_iter_t *iter) { + assert(iter->hash_ptr->iters); + /* Remove itself from the iterators list */ + if(iter->iter_next) + iter->iter_next->iter_prev = iter->iter_prev; + if(iter->iter_prev) + iter->iter_prev->iter_next = iter->iter_next; + else + iter->hash_ptr->iters = iter->iter_next; /* Shift the head */ + iter->hash_ptr = (void *)0xdeadbeef; +} + +int +genhash_set_lru_limit(genhash_t *h, int value) { + if(h) { + int prev_limit = h->lru_limit; + if(value >= 0) + h->lru_limit = value; + return prev_limit; + } else { + errno = EINVAL; + return -1; + } +} + +int +genhash_set_buckets_limit(int value) { + int prev_limit = maximum_hash_buckets_number; + if(value > 0) { + maximum_hash_buckets_number = value; + } + return prev_limit; +} + +void +genhash_destroy(genhash_t *h) { + if(h) { + assert(h->iters == 0); /* All iterators MUST be _done(). */ + genhash_empty(h, 1, 1); + free(h); + } +} + +void +genhash_empty(genhash_t *h, int freekeys, int freevalues) { + genhash_iter_t *iter; + + if(h == NULL) return; + + /* + * Don't free what could not be freed. + */ + if(h->keydestroyf == NULL) freekeys = 0; + if(h->valuedestroyf == NULL) freevalues = 0; + + if(h->numbuckets == 0) { + while(h->numelements > 0) { + int n = --h->numelements; + void *kd_arg = h->tiny_keys[n]; + void *vd_arg = h->tiny_values[n]; + + if (freekeys) h->keydestroyf(kd_arg); + if (freevalues) h->valuedestroyf(vd_arg); + } + } else { + genhash_el *el, *el_next; + + for(el = h->lru_head; el; el = el_next) { + void *kd_arg = el->key; + void *vd_arg = el->value; + el_next = el->lru_next; + free(el); + + h->numelements --; + + if (freekeys) h->keydestroyf(kd_arg); + if (freevalues) h->valuedestroyf(vd_arg); + } + free(h->buckets); + h->numbuckets = 0; /* Move back to TINY model */ + } + memset(&h->un, 0, sizeof(h->un)); + + /* Invalidate iterators in TINY model */ + for(iter = h->iters; iter; iter = iter->iter_next) { + assert(iter->hash_ptr == h); + iter->un.item_number = -1; + } + + assert(h->numelements == 0); +} + + +/*----- Simple hash and compare functions for common data types ------*/ + +unsigned int +hashf_int (const void *key) { + return (*(const int *)key ^ (*(const int *)key >> 16)); +} + +int +cmpf_int (const void *key1, const void *key2) { + return (*(const int *)key1 != *(const int *)key2); +} + +unsigned int +hashf_void (const void *key) { + return ((int)key ^ ((int)key >> 16)); +} + +int +cmpf_void (const void *key1, const void *key2) { + return (key1 != key2); +} + + +/* + * Phong's linear congruential hash + */ +#define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c)) + +unsigned int +hashf_string(const void *keyarg) { + register const unsigned char *key; + register unsigned int h; + register unsigned char c; + + key = keyarg; + for (h = 0; (c = *key++);) + dcharhash(h, c); + + return (h); +} + +int +cmpf_string(const void *key1, const void *key2) { + return strcmp((const char *)key1, (const char *)key2); +} + diff --git a/libasn1common/genhash.h b/libasn1common/genhash.h new file mode 100644 index 000000000..8fff9a6cf --- /dev/null +++ b/libasn1common/genhash.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2002-2005 Lev Walkin . All rights reserved. + * Copyright (c) 2001-2004 Netli, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: genhash.h 447 2005-06-07 06:51:10Z vlm $ + */ +#ifndef __GENHASH_H__ +#define __GENHASH_H__ + +/* + * General purpose hashing framework. + * Refer to the corresponding .c source file for the detailed description. + * + * WARNING: Generally, functions don't allow NULL's to be passed + * as the genhash_t pointers, if not explicitly stated otherwise. + */ + +typedef struct genhash_s genhash_t; + +/* + * Create a new hash table + * keycmpf : function which returns 0 if keys are equal, else !0 + * keyhashf : function which computes the hash value of a key + * keydestroyf : function for destroying keys, can be NULL for no destructor + * valuedestroyf: function for destroying values, can be NULL for no destructor + */ +genhash_t *genhash_new( + int (*keycmpf) (const void *key1, const void *key2), + unsigned int (*keyhashf) (const void *key), + void (*keydestroyf) (void *key), + void (*valuedestroyf) (void *value)); + +/* + * Re-initialize genhash structure with new callback functions. + * (Rarely ever used). + */ +int genhash_reinit( + genhash_t *hash, + int (*keycmpf) (const void *key1, const void *key2), + unsigned int (*keyhashf) (const void *key), + void (*keydestroyf) (void *key), + void (*valuedestroyf) (void *value)); + +/* + * Initialize the LRU-driven elements count limiting + * and/or set a new Least Recently Used list size limit. + * If a new entry is being added to the hash, the least recently used entry + * (one at the bottom of the LRU list) will be automatically deleted. + * The deletion may be skipped if the hash is very small + * (currently, "small" means no longer than 4 entries). + * This function is immune to NULL argument. + * + * RETURN VALUES: + * The previous LRU limit, or -1/EINVAL when h is NULL. + * EXAMPLE: + * genhash_set_lru_limit(h, 1500); // Maximum 1500 entries in the hash + */ +int genhash_set_lru_limit(genhash_t *h, int new_lru_limit); + +/* + * Set the system-wide (!!!) limit on maximum number of buckets. + * If the value is 0, the hash is allowed to store only 4 elements inline + * (buckets allocation is suppressed). + * If the value is 1, the hash turns out into a linked list. + * The default limit is about 1M buckets. + * RETURN VALUES: + * The previous buckets number limit. + */ +int genhash_set_buckets_limit(int new_max_number_of_buckets); + +/* + * destroys a hash, freeing each key and/or value. + * Keys are always destroyed before values using the destructors + * specified upon hash creation. + * This function is immune to NULL argument. + */ +void genhash_destroy(genhash_t *h); + +/* + * Delete all elements from the hash, retaining the hash structure itself. + * Optionally, it may be told to invoke, or not invoke the corresponding + * key/value destructors. + * This function is immune to NULL argument. + * + * EXAMPLE: + * genhash_empty(h, 1, 1); // Remove all entries, invoking destructors + */ +void genhash_empty(genhash_t *h, int freekeys, int freevalues); + +/* + * Add, returns 0 on success, -1 on failure (ENOMEM). Note, you CAN add + * records with duplicate keys. No guarantees about order preservations. + * + * EXAMPLE: + * char *key_str = strdup("key"); + * char *val_str = strdup("arbitrary value"); + * if(genhash_add(h, key_str, val_str) != 0) { + * free(key_str); + * free(val_str); + * perror("genhash_add failed"); + * exit(EX_SOFTWARE); + * } + */ +int genhash_add(genhash_t *h, void *key, void *value); + +/* + * Add, but only if a mapping is not there already. + * RETURN VALUES: + * 0: Element added successfully. + * -1/EINVAL: Invalid arguments (key == NULL). + * -1/EEXIST: Duplicate entry is found. + * -1/ENOMEM: Memory allocation failed + */ +int genhash_addunique(genhash_t *h, void *key, void *value); + +/* + * Fetch - returns pointer to a value, NULL/ESRCH if not found + */ +void *genhash_get(genhash_t *h, const void *key); + +/* + * Delete - returns 0 on success, -1/ESRCH if not found. + * Keys are always destroyed before values using the destructors + * specified upon hash creation. + */ +int genhash_del(genhash_t *h, void *key); + +/* + * Return the number of elements in a hash. + * This function is immune to NULL argument. + */ +int genhash_count(genhash_t *h); + +/* + * External iterator structure for using with iterator-based walking functions. + * This declaration is NOT INTENDED TO BE USED BY AN APPLICATION DIRECTLY + * The pointer to the already allocated structure must be passed to + * genhash_iter*() functions. + */ +typedef struct genhash_iter_s { + genhash_t *hash_ptr; + union { + int item_number; + void *location; + } un; + int order_lru_first; + struct genhash_iter_s *iter_prev; + struct genhash_iter_s *iter_next; +} genhash_iter_t; + +/* + * Initialize the iterator for walking through the hash. + * The memory block to be used as iterator is provided by the (*iter) pointer. + * This memory must be allocated (possibly, on the stack) by the caller. + * OWNERSHIP: + * The initialized iterator must be disposed of by calling + * genhash_iter_done(). + * ORDER: + * By default, the elements are iterated in the "most recent first" order, + * use reverse_order to change that. For very small number of entries + * (currently, 4) the order may be IGNORED. + * RETURN VALUES: + * number of entries the hash had at the moment. + */ +int genhash_iter_init(genhash_iter_t *iter, + genhash_t *hash_to_use, int reverse_order); + +/* + * Returns the key and value of each element in optional (key) and (value), + * which must be passed as the pointers to pointers (hence these ***'s). + * OWNERSHIP: + * The key and value are pointers to the internally manageed locations. + * RETURN VALUES: + * 0 if no more elements will be returned, otherwise 1. + * EXAMPLE: + * key_type_t *key; // Pointer to key + * value_type_t *val; // Pointer to value + * genhash_iter_t iter; // Iterator structure + * genhash_iter_init(&iter, hash_ptr, 0); // Prepare iterator + * while(genhash_iter(&iter, &key, &val)) // Iterate over hash elements + * print_keyval(key, val); // Use key and value + * genhash_iter_done(&iter); // Done iterations. + */ +int genhash_iter(genhash_iter_t *iter, void */***/key, void */***/val); + +/* + * Dispose of the iterator. + * After this operations, the iterator contents unusable + * and shall not be accesed. (genhash_iter_init() is OK). + */ +void genhash_iter_done(genhash_iter_t *iter); + + +/****************************************************************************/ + +/* + * The following hashing and comparison functions are provided for + * you, or you may supply your own. + */ +unsigned int hashf_int (const void *key); /* Key is an int * */ +int cmpf_int (const void *key1, const void *key2); + +unsigned int hashf_void (const void *key); +int cmpf_void (const void *key1, const void *key2); + +unsigned int hashf_string (const void *key); +int cmpf_string (const void *key1, const void *key2); + +#endif /* __GENHASH_H__ */ From a67d11061eef998454464466eae72d6199f1f80c Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sun, 5 Nov 2017 22:46:12 -0800 Subject: [PATCH 10/41] name clashes using generic hashing --- libasn1compiler/asn1c_naming.c | 68 +++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/libasn1compiler/asn1c_naming.c b/libasn1compiler/asn1c_naming.c index c01375780..b110ab59e 100644 --- a/libasn1compiler/asn1c_naming.c +++ b/libasn1compiler/asn1c_naming.c @@ -3,6 +3,7 @@ #include "asn1c_misc.h" #include "asn1c_misc.h" #include +#include struct intl_name { asn1p_expr_t *expr; @@ -10,54 +11,64 @@ struct intl_name { const char *name; TQ_ENTRY(struct intl_name) next; }; -static TQ_HEAD(struct intl_name) used_names; + +genhash_t *used_names_hash; + +static void +name_entry_destroy(void *np) { + struct intl_name *n = np; + + union { + const char *c_buf; + char *nc_buf; + } const_cast; + + asn1p_expr_free(n->expr); + asn1p_expr_free(n->clashes_with); + const_cast.c_buf = n->name; + free(const_cast.nc_buf); + free(n); +} void c_name_clash_finder_init() { - TQ_INIT(&used_names); + assert(used_names_hash == NULL); + used_names_hash = + genhash_new(cmpf_string, hashf_string, NULL, name_entry_destroy); + assert(used_names_hash); } void c_name_clash_finder_destroy() { - struct intl_name *n; - - while((n = TQ_REMOVE(&used_names, next))) { - union { - const char *c_buf; - char *nc_buf; - } const_cast; - - asn1p_expr_free(n->expr); - asn1p_expr_free(n->clashes_with); - const_cast.c_buf = n->name; - free(const_cast.nc_buf); - free(n); - } + genhash_destroy(used_names_hash); + used_names_hash = NULL; } static void register_global_name(asn1p_expr_t *expr, const char *name) { struct intl_name *n; - TQ_FOR(n, &used_names, next) { - if(strcmp(n->name, name) == 0) { - if(!(expr->_mark & TM_NAMEGIVEN) && expr != n->expr) { - n->clashes_with = expr; - expr->ref_cnt++; - return; - } + n = genhash_get(used_names_hash, (const void *)name); + if(n) { + if(!(expr->_mark & TM_NAMEGIVEN) && (expr != n->expr)) { + n->clashes_with = expr; + expr->ref_cnt++; + return; } } if(expr->_mark & TM_NAMEGIVEN) return; + char *name_copy = strdup(name); + n = calloc(1, sizeof(*n)); assert(n); n->expr = expr; expr->ref_cnt++; - n->name = strdup(name); - TQ_ADD(&used_names, n, next); + n->name = name_copy; + int ret = genhash_add(used_names_hash, name_copy, n); + assert(ret == 0); } int @@ -66,7 +77,10 @@ c_name_clash(arg_t *arg) { size_t n_clashes = 0; const size_t max_clashes = 5; - TQ_FOR(n, &used_names, next) { + genhash_iter_t iter; + + genhash_iter_init(&iter, used_names_hash, 0); + while(genhash_iter(&iter, NULL, (void *)&n)) { if(n->clashes_with) { if(n_clashes++ > max_clashes) continue; FATAL( @@ -81,6 +95,8 @@ c_name_clash(arg_t *arg) { } } + genhash_iter_done(&iter); + if(n_clashes > max_clashes) { FATAL("... %zu more name clashes not shown", n_clashes - max_clashes); } From 1a49ced90eb525b1516c02484e166c54b379cd65 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Mon, 6 Nov 2017 00:07:00 -0800 Subject: [PATCH 11/41] use hash for name lookup --- libasn1fix/asn1fix_cws.c | 11 +- libasn1fix/asn1fix_internal.h | 1 + libasn1fix/asn1fix_retrieve.c | 67 ++-- libasn1fix/check_fixer.c | 7 +- libasn1parser/asn1p_module.c | 32 +- libasn1parser/asn1p_module.h | 9 +- libasn1parser/asn1p_xports.c | 4 +- libasn1parser/asn1p_xports.h | 2 +- libasn1parser/asn1p_y.c | 697 +++++++++++++++++----------------- libasn1parser/asn1p_y.h | 2 +- libasn1parser/asn1p_y.y | 35 +- 11 files changed, 453 insertions(+), 414 deletions(-) diff --git a/libasn1fix/asn1fix_cws.c b/libasn1fix/asn1fix_cws.c index 948c6277c..e54eaa703 100644 --- a/libasn1fix/asn1fix_cws.c +++ b/libasn1fix/asn1fix_cws.c @@ -389,7 +389,6 @@ _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_cell_s *cell, char *mivr; /* Most Immediate Value Representation */ int new_ref = 1; asn1p_t *asn; - asn1p_module_t *mod; asn1p_expr_t *type_expr = (asn1p_expr_t *)NULL; int i, ret = 0, psize; char *pp; @@ -458,9 +457,13 @@ _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_cell_s *cell, free(mivr); return -1; } else { - mod = TQ_FIRST(&(asn->modules)); - assert(mod); - expr = TQ_REMOVE(&(mod->members), next); + asn1p_module_t *mod = TQ_FIRST(&(asn->modules)); + assert(mod); + + /* This member removal is safe with respect to members hash since the + * entire asn module will be deleted down below. + */ + expr = TQ_REMOVE(&(mod->members), next); assert(expr); expr->parent_expr = NULL; diff --git a/libasn1fix/asn1fix_internal.h b/libasn1fix/asn1fix_internal.h index 5fd7e7684..c429730f1 100644 --- a/libasn1fix/asn1fix_internal.h +++ b/libasn1fix/asn1fix_internal.h @@ -22,6 +22,7 @@ #include /* Our lovely ASN.1 parser module */ #include +#include #include "asn1fix.h" #ifdef _WIN32 diff --git a/libasn1fix/asn1fix_retrieve.c b/libasn1fix/asn1fix_retrieve.c index 536f50208..40acbe5a4 100644 --- a/libasn1fix/asn1fix_retrieve.c +++ b/libasn1fix/asn1fix_retrieve.c @@ -28,35 +28,44 @@ asn1f_lookup_child(asn1p_expr_t *tc, const char *name) { return NULL; } +static asn1p_expr_t * +asn1f_lookup_in_module(asn1p_module_t *mod, const char *name) { + asn1p_expr_t *expr = genhash_get(mod->members_hash, name); + if(!expr) { + asn1p_expr_t *memb; + TQ_FOR(memb, &mod->members, next) { + if(memb->expr_type == ASN_BASIC_ENUMERATED) { + asn1p_expr_t *v = asn1f_lookup_child(memb, name); + if(v) return v; + } + } + } + + return expr; +} + asn1p_module_t * asn1f_lookup_in_imports(arg_t *arg, asn1p_module_t *mod, const char *name) { asn1p_xports_t *xp; - asn1p_module_t *fromModule; - asn1p_expr_t *tc = (asn1p_expr_t *)0; - asn1p_expr_t *memb = (asn1p_expr_t *)0; - asn1p_expr_t *v = (asn1p_expr_t *)0; /* * Search in which exactly module this name is defined. */ TQ_FOR(xp, &(mod->imports), xp_next) { - fromModule = asn1f_lookup_module(arg, xp->fromModuleName, NULL); - TQ_FOR(tc, &(xp->members), next) { - if(strcmp(name, tc->Identifier) == 0) + asn1p_module_t *fromModule = + asn1f_lookup_module(arg, xp->fromModuleName, NULL); + asn1p_expr_t *tc = (asn1p_expr_t *)0; + + TQ_FOR(tc, &(xp->xp_members), next) { + if(strcmp(name, tc->Identifier) == 0) break; if(!fromModule) continue; - TQ_FOR(memb, &(fromModule->members), next) { - if((memb->expr_type != ASN_BASIC_ENUMERATED) || - (strcmp(memb->Identifier, tc->Identifier) != 0)) - continue; - - v = asn1f_lookup_child(memb, name); - if (v) break; - } - if(v) break; + asn1p_expr_t *v = v = + asn1f_lookup_in_module(fromModule, tc->Identifier); + if(v) break; } if(tc) break; } @@ -291,8 +300,6 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t ns_item--) { struct asn1_namespace_element_s *ns_el = &my_namespace->elements[ns_item]; - asn1p_expr_t *ref_tc; /* Referenced tc */ - asn1p_expr_t *v = (asn1p_expr_t *)0; switch(ns_el->selector) { case NAM_SYMBOL: @@ -312,22 +319,12 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t DISPOSE_OF_MY_NAMESPACE(); return ns_el->u.symbol.resolution; } - case NAM_SPACE: + case NAM_SPACE: { + asn1p_expr_t *ref_tc; /* Referenced tc */ /* * Do a direct symbol search in the given module. */ - TQ_FOR(ref_tc, &(ns_el->u.space.module->members), next) { - if(ref_tc->Identifier) - if(strcmp(ref_tc->Identifier, identifier) == 0) break; - - if(ref_tc->expr_type == ASN_BASIC_ENUMERATED) { - v = asn1f_lookup_child(ref_tc, identifier); - if(v) { - ref_tc = v; - break; - } - } - } + ref_tc = asn1f_lookup_in_module(ns_el->u.space.module, identifier); if(ref_tc) { /* It is acceptable that we don't use input parameters */ if(rhs_pspecs && !ref_tc->lhs_params) { @@ -355,6 +352,7 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t DISPOSE_OF_MY_NAMESPACE(); return ref_tc; } + } /* if(!expr && !(arg->expr->_mark & TM_BROKEN) @@ -479,6 +477,11 @@ asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr, enum ftt_what what) { ref = expr->reference; break; case FTT_VALUE: + + DEBUG("%s(%s->%s) meta %d for line %d", + "VALUE", expr->Identifier, asn1f_printable_reference(ref), + expr->meta_type, expr->_lineno); + assert(expr->meta_type == AMT_VALUE); assert(expr->value); /* Expression may be a terminal type itself */ @@ -574,7 +577,7 @@ asn1f_compatible_with_exports(arg_t *arg, asn1p_module_t *mod, const char *name) return 0; } - TQ_FOR(item, &(exports->members), next) { + TQ_FOR(item, &(exports->xp_members), next) { if(strcmp(item->Identifier, name) == 0) return 0; } diff --git a/libasn1fix/check_fixer.c b/libasn1fix/check_fixer.c index 6f5f25e60..b71a8c9ec 100644 --- a/libasn1fix/check_fixer.c +++ b/libasn1fix/check_fixer.c @@ -12,6 +12,7 @@ #include #include +#include "genhash.h" #include "asn1fix.h" #include "asn1_buffer.h" #include "asn1_namespace.h" @@ -340,11 +341,7 @@ post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) { /* * Scan in search for the original. */ - TQ_FOR(expr, &(mod->members), next) { - if(strcmp(expr->Identifier, name) == 0) - break; - } - + expr = genhash_get(mod->members_hash, name); if(expr == NULL) { fprintf(stderr, "CHECKER: Value \"%s\" requested by " diff --git a/libasn1parser/asn1p_module.c b/libasn1parser/asn1p_module.c index 10aa94c1b..974668d61 100644 --- a/libasn1parser/asn1p_module.c +++ b/libasn1parser/asn1p_module.c @@ -1,5 +1,6 @@ #include #include +#include #include "asn1parser.h" @@ -15,7 +16,10 @@ asn1p_module_new() { TQ_INIT(&(mod->exports)); TQ_INIT(&(mod->imports)); TQ_INIT(&(mod->members)); - } + + mod->members_hash = genhash_new(cmpf_string, hashf_string, NULL, NULL); + assert(mod->members_hash); + } return mod; } @@ -42,6 +46,9 @@ asn1p_module_free(asn1p_module_t *mod) { while((expr = TQ_REMOVE(&(mod->members), next))) asn1p_expr_free(expr); + genhash_destroy(mod->members_hash); + mod->members_hash = NULL; + free(mod); } } @@ -66,3 +73,26 @@ asn1p_delete(asn1p_t *asn) { free(asn); } } + + +void +asn1p_module_move_members(asn1p_module_t *to, asn1p_module_t *from) { + if(from) { + while(TQ_FIRST(&(from->members))) { + asn1p_expr_t *expr = TQ_REMOVE(&from->members, next); + TQ_ADD(&to->members, expr, next); + genhash_add(to->members_hash, expr->Identifier, expr); + } + assert(TQ_FIRST(&from->members) == 0); + + genhash_empty(from->members_hash, 0, 0); + } +} + +void +asn1p_module_member_add(asn1p_module_t *mod, asn1p_expr_t *expr) { + if(expr) { + TQ_ADD(&mod->members, expr, next); + genhash_add(mod->members_hash, expr->Identifier, expr); + } +} diff --git a/libasn1parser/asn1p_module.h b/libasn1parser/asn1p_module.h index db1f1cf04..8315bf43c 100644 --- a/libasn1parser/asn1p_module.h +++ b/libasn1parser/asn1p_module.h @@ -16,6 +16,8 @@ typedef struct asn1p_s { asn1p_t *asn1p_new(void); void asn1p_delete(asn1p_t *asn); +struct genhash_s; /* Forward declaration */ + /* * Flags specific to a module. */ @@ -75,7 +77,8 @@ typedef struct asn1p_module_s { /* * List of everything that this module defines itself. */ - TQ_HEAD(struct asn1p_expr_s) members; + TQ_HEAD(struct asn1p_expr_s) members; /* Do not access directly */ + struct genhash_s *members_hash; /* * Next module in the list. @@ -100,4 +103,8 @@ typedef struct asn1p_module_s { asn1p_module_t *asn1p_module_new(void); void asn1p_module_free(asn1p_module_t *mod); +void asn1p_module_move_members(asn1p_module_t *to, asn1p_module_t *from); +void asn1p_module_member_add(asn1p_module_t *mod, struct asn1p_expr_s *expr); + + #endif /* ASN1_PARSER_MODULE_H */ diff --git a/libasn1parser/asn1p_xports.c b/libasn1parser/asn1p_xports.c index 8f46ac125..8ba511ad6 100644 --- a/libasn1parser/asn1p_xports.c +++ b/libasn1parser/asn1p_xports.c @@ -13,7 +13,7 @@ asn1p_xports_new() { xp = calloc(1, sizeof *xp); if(xp) { - TQ_INIT(&(xp->members)); + TQ_INIT(&(xp->xp_members)); } return xp; @@ -30,7 +30,7 @@ asn1p_xports_free(asn1p_xports_t *xp) { free(xp->fromModuleName); asn1p_oid_free(xp->identifier.oid); - while((expr = TQ_REMOVE(&(xp->members), next))) + while((expr = TQ_REMOVE(&(xp->xp_members), next))) asn1p_expr_free(expr); free(xp); diff --git a/libasn1parser/asn1p_xports.h b/libasn1parser/asn1p_xports.h index da90de558..0c65be092 100644 --- a/libasn1parser/asn1p_xports.h +++ b/libasn1parser/asn1p_xports.h @@ -26,7 +26,7 @@ typedef struct asn1p_xports_s { /* * Number of entities to import. */ - TQ_HEAD(struct asn1p_expr_s) members; + TQ_HEAD(struct asn1p_expr_s) xp_members; /* * Pointer to the next xports structure in whatever list. diff --git a/libasn1parser/asn1p_y.c b/libasn1parser/asn1p_y.c index 305532e20..2d4860d47 100644 --- a/libasn1parser/asn1p_y.c +++ b/libasn1parser/asn1p_y.c @@ -394,15 +394,14 @@ static asn1p_module_t *currentModule; #ifdef AL_IMPORT #error AL_IMPORT DEFINED ELSEWHERE! #endif -#define AL_IMPORT(to,where,from,field) do { \ - if(!(from)) break; \ - while(TQ_FIRST(&((from)->where))) { \ - TQ_ADD(&((to)->where), \ - TQ_REMOVE(&((from)->where), field), \ - field); \ - } \ - assert(TQ_FIRST(&((from)->where)) == 0); \ - } while(0) +#define AL_IMPORT(to, where, from, field) \ + do { \ + if(!(from)) break; \ + while(TQ_FIRST(&((from)->where))) { \ + TQ_ADD(&((to)->where), TQ_REMOVE(&((from)->where), field), field); \ + } \ + assert(TQ_FIRST(&((from)->where)) == 0); \ + } while(0) @@ -426,7 +425,7 @@ static asn1p_module_t *currentModule; #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -#line 116 "asn1p_y.y" +#line 115 "asn1p_y.y" { asn1p_t *a_grammar; asn1p_module_flags_e a_module_flags; @@ -462,7 +461,7 @@ typedef union YYSTYPE } tv_nametag; } /* Line 193 of yacc.c. */ -#line 466 "asn1p_y.c" +#line 465 "asn1p_y.c" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -475,7 +474,7 @@ typedef union YYSTYPE /* Line 216 of yacc.c. */ -#line 479 "asn1p_y.c" +#line 478 "asn1p_y.c" #ifdef short # undef short @@ -895,41 +894,41 @@ static const yytype_int16 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 415, 415, 418, 424, 429, 446, 446, 475, 476, - 480, 483, 489, 495, 504, 508, 512, 522, 523, 532, - 535, 544, 547, 550, 553, 557, 578, 579, 588, 601, - 604, 621, 628, 642, 650, 649, 663, 676, 677, 680, - 690, 696, 697, 700, 705, 712, 713, 717, 728, 733, - 740, 746, 752, 762, 763, 775, 778, 781, 789, 794, - 801, 807, 813, 822, 825, 845, 855, 875, 881, 897, - 903, 911, 920, 931, 935, 943, 951, 959, 970, 975, - 982, 983, 991, 999, 1022, 1023, 1026, 1031, 1035, 1043, - 1050, 1056, 1063, 1069, 1074, 1081, 1086, 1089, 1096, 1106, - 1107, 1111, 1118, 1128, 1138, 1149, 1159, 1170, 1180, 1191, - 1203, 1204, 1211, 1210, 1219, 1223, 1230, 1234, 1237, 1241, - 1247, 1255, 1264, 1275, 1278, 1285, 1308, 1331, 1355, 1362, - 1381, 1382, 1385, 1386, 1392, 1398, 1404, 1414, 1424, 1430, - 1442, 1457, 1465, 1473, 1484, 1495, 1517, 1525, 1534, 1538, - 1543, 1552, 1557, 1562, 1570, 1593, 1603, 1604, 1605, 1605, - 1613, 1618, 1623, 1628, 1629, 1630, 1631, 1635, 1636, 1654, - 1658, 1663, 1671, 1680, 1695, 1696, 1702, 1703, 1704, 1705, - 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1721, - 1722, 1723, 1727, 1733, 1738, 1743, 1748, 1753, 1762, 1763, - 1767, 1771, 1772, 1773, 1774, 1775, 1779, 1780, 1781, 1782, - 1786, 1787, 1794, 1794, 1795, 1795, 1799, 1800, 1804, 1805, - 1809, 1810, 1811, 1815, 1821, 1822, 1831, 1831, 1833, 1836, - 1840, 1841, 1847, 1858, 1859, 1865, 1866, 1872, 1873, 1880, - 1881, 1887, 1888, 1899, 1905, 1911, 1912, 1914, 1915, 1916, - 1921, 1926, 1931, 1936, 1948, 1957, 1958, 1964, 1965, 1970, - 1973, 1978, 1986, 1992, 2004, 2007, 2013, 2014, 2014, 2015, - 2017, 2030, 2035, 2041, 2055, 2056, 2060, 2063, 2066, 2074, - 2075, 2076, 2081, 2080, 2092, 2101, 2102, 2103, 2104, 2107, - 2110, 2119, 2135, 2141, 2147, 2161, 2172, 2188, 2191, 2211, - 2215, 2219, 2223, 2230, 2235, 2241, 2250, 2255, 2262, 2270, - 2280, 2285, 2292, 2300, 2310, 2325, 2330, 2337, 2344, 2352, - 2360, 2367, 2378, 2382, 2389, 2420, 2421, 2425, 2432, 2438, - 2439, 2440, 2441, 2445, 2446, 2447, 2451, 2455, 2463, 2464, - 2470, 2477, 2484 + 0, 414, 414, 417, 423, 428, 445, 445, 474, 475, + 479, 482, 488, 494, 503, 507, 511, 521, 522, 531, + 534, 543, 546, 549, 552, 556, 577, 578, 587, 600, + 603, 620, 627, 641, 649, 648, 662, 675, 676, 679, + 689, 695, 696, 699, 704, 711, 712, 716, 727, 732, + 739, 745, 751, 761, 762, 774, 777, 780, 788, 793, + 800, 806, 812, 821, 824, 844, 854, 874, 880, 896, + 902, 910, 919, 930, 934, 942, 950, 958, 969, 974, + 981, 982, 990, 998, 1021, 1022, 1025, 1030, 1034, 1042, + 1049, 1055, 1062, 1068, 1073, 1080, 1085, 1088, 1095, 1105, + 1106, 1110, 1117, 1127, 1137, 1148, 1158, 1169, 1179, 1190, + 1202, 1203, 1210, 1209, 1218, 1222, 1229, 1233, 1236, 1240, + 1246, 1254, 1263, 1274, 1277, 1284, 1307, 1330, 1354, 1361, + 1380, 1381, 1384, 1385, 1391, 1397, 1403, 1413, 1423, 1429, + 1441, 1456, 1464, 1472, 1483, 1494, 1516, 1524, 1533, 1537, + 1542, 1551, 1556, 1561, 1569, 1592, 1602, 1603, 1604, 1604, + 1612, 1617, 1622, 1627, 1628, 1629, 1630, 1634, 1635, 1653, + 1657, 1662, 1670, 1679, 1694, 1695, 1701, 1702, 1703, 1704, + 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1720, + 1721, 1722, 1726, 1732, 1737, 1742, 1747, 1752, 1761, 1762, + 1766, 1770, 1771, 1772, 1773, 1774, 1778, 1779, 1780, 1781, + 1785, 1786, 1793, 1793, 1794, 1794, 1798, 1799, 1803, 1804, + 1808, 1809, 1810, 1814, 1820, 1821, 1830, 1830, 1832, 1835, + 1839, 1840, 1846, 1857, 1858, 1864, 1865, 1871, 1872, 1879, + 1880, 1886, 1887, 1898, 1904, 1910, 1911, 1913, 1914, 1915, + 1920, 1925, 1930, 1935, 1947, 1956, 1957, 1963, 1964, 1969, + 1972, 1977, 1985, 1991, 2003, 2006, 2012, 2013, 2013, 2014, + 2016, 2029, 2034, 2040, 2054, 2055, 2059, 2062, 2065, 2073, + 2074, 2075, 2080, 2079, 2091, 2100, 2101, 2102, 2103, 2106, + 2109, 2118, 2134, 2140, 2146, 2160, 2171, 2187, 2190, 2210, + 2214, 2218, 2222, 2229, 2234, 2240, 2249, 2254, 2261, 2269, + 2279, 2284, 2291, 2299, 2309, 2324, 2329, 2336, 2343, 2351, + 2359, 2366, 2377, 2381, 2388, 2419, 2420, 2424, 2431, 2437, + 2438, 2439, 2440, 2444, 2445, 2446, 2450, 2454, 2462, 2463, + 2469, 2476, 2483 }; #endif @@ -2342,21 +2341,21 @@ yyparse () switch (yyn) { case 2: -#line 415 "asn1p_y.y" +#line 414 "asn1p_y.y" { *(void **)param = (yyvsp[(2) - (2)].a_grammar); } break; case 3: -#line 418 "asn1p_y.y" +#line 417 "asn1p_y.y" { *(void **)param = (yyvsp[(1) - (1)].a_grammar); } break; case 4: -#line 424 "asn1p_y.y" +#line 423 "asn1p_y.y" { (yyval.a_grammar) = asn1p_new(); checkmem((yyval.a_grammar)); @@ -2365,7 +2364,7 @@ yyparse () break; case 5: -#line 429 "asn1p_y.y" +#line 428 "asn1p_y.y" { (yyval.a_grammar) = (yyvsp[(1) - (2)].a_grammar); TQ_ADD(&((yyval.a_grammar)->modules), (yyvsp[(2) - (2)].a_module), mod_next); @@ -2373,12 +2372,12 @@ yyparse () break; case 6: -#line 446 "asn1p_y.y" +#line 445 "asn1p_y.y" { currentModule = asn1p_module_new(); } break; case 7: -#line 451 "asn1p_y.y" +#line 450 "asn1p_y.y" { (yyval.a_module) = currentModule; @@ -2399,31 +2398,31 @@ yyparse () break; case 8: -#line 475 "asn1p_y.y" +#line 474 "asn1p_y.y" { (yyval.a_oid) = 0; } break; case 9: -#line 476 "asn1p_y.y" +#line 475 "asn1p_y.y" { (yyval.a_oid) = (yyvsp[(1) - (1)].a_oid); } break; case 10: -#line 480 "asn1p_y.y" +#line 479 "asn1p_y.y" { (yyval.a_oid) = (yyvsp[(2) - (3)].a_oid); } break; case 11: -#line 483 "asn1p_y.y" +#line 482 "asn1p_y.y" { (yyval.a_oid) = 0; } break; case 12: -#line 489 "asn1p_y.y" +#line 488 "asn1p_y.y" { (yyval.a_oid) = asn1p_oid_new(); asn1p_oid_add_arc((yyval.a_oid), &(yyvsp[(1) - (1)].a_oid_arc)); @@ -2433,7 +2432,7 @@ yyparse () break; case 13: -#line 495 "asn1p_y.y" +#line 494 "asn1p_y.y" { (yyval.a_oid) = (yyvsp[(1) - (2)].a_oid); asn1p_oid_add_arc((yyval.a_oid), &(yyvsp[(2) - (2)].a_oid_arc)); @@ -2443,7 +2442,7 @@ yyparse () break; case 14: -#line 504 "asn1p_y.y" +#line 503 "asn1p_y.y" { /* iso */ (yyval.a_oid_arc).name = (yyvsp[(1) - (1)].tv_str); (yyval.a_oid_arc).number = -1; @@ -2451,7 +2450,7 @@ yyparse () break; case 15: -#line 508 "asn1p_y.y" +#line 507 "asn1p_y.y" { /* iso(1) */ (yyval.a_oid_arc).name = (yyvsp[(1) - (4)].tv_str); (yyval.a_oid_arc).number = (yyvsp[(3) - (4)].a_int); @@ -2459,7 +2458,7 @@ yyparse () break; case 16: -#line 512 "asn1p_y.y" +#line 511 "asn1p_y.y" { /* 1 */ (yyval.a_oid_arc).name = 0; (yyval.a_oid_arc).number = (yyvsp[(1) - (1)].a_int); @@ -2467,61 +2466,61 @@ yyparse () break; case 17: -#line 522 "asn1p_y.y" +#line 521 "asn1p_y.y" { (yyval.a_module_flags) = MSF_NOFLAGS; } break; case 18: -#line 523 "asn1p_y.y" +#line 522 "asn1p_y.y" { (yyval.a_module_flags) = (yyvsp[(1) - (1)].a_module_flags); } break; case 19: -#line 532 "asn1p_y.y" +#line 531 "asn1p_y.y" { (yyval.a_module_flags) = (yyvsp[(1) - (1)].a_module_flags); } break; case 20: -#line 535 "asn1p_y.y" +#line 534 "asn1p_y.y" { (yyval.a_module_flags) = (yyvsp[(1) - (2)].a_module_flags) | (yyvsp[(2) - (2)].a_module_flags); } break; case 21: -#line 544 "asn1p_y.y" +#line 543 "asn1p_y.y" { (yyval.a_module_flags) = MSF_EXPLICIT_TAGS; } break; case 22: -#line 547 "asn1p_y.y" +#line 546 "asn1p_y.y" { (yyval.a_module_flags) = MSF_IMPLICIT_TAGS; } break; case 23: -#line 550 "asn1p_y.y" +#line 549 "asn1p_y.y" { (yyval.a_module_flags) = MSF_AUTOMATIC_TAGS; } break; case 24: -#line 553 "asn1p_y.y" +#line 552 "asn1p_y.y" { (yyval.a_module_flags) = MSF_EXTENSIBILITY_IMPLIED; } break; case 25: -#line 557 "asn1p_y.y" +#line 556 "asn1p_y.y" { /* X.680Amd1 specifies TAG and XER */ if(strcmp((yyvsp[(1) - (2)].tv_str), "TAG") == 0) { @@ -2540,24 +2539,24 @@ yyparse () break; case 26: -#line 578 "asn1p_y.y" +#line 577 "asn1p_y.y" { (yyval.a_module) = 0; } break; case 27: -#line 579 "asn1p_y.y" +#line 578 "asn1p_y.y" { (yyval.a_module) = (yyvsp[(1) - (1)].a_module); } break; case 28: -#line 588 "asn1p_y.y" +#line 587 "asn1p_y.y" { (yyval.a_module) = asn1p_module_new(); AL_IMPORT((yyval.a_module), exports, (yyvsp[(1) - (3)].a_module), xp_next); AL_IMPORT((yyval.a_module), imports, (yyvsp[(2) - (3)].a_module), xp_next); - AL_IMPORT((yyval.a_module), members, (yyvsp[(3) - (3)].a_module), next); + asn1p_module_move_members((yyval.a_module), (yyvsp[(3) - (3)].a_module)); asn1p_module_free((yyvsp[(1) - (3)].a_module)); asn1p_module_free((yyvsp[(2) - (3)].a_module)); @@ -2566,14 +2565,14 @@ yyparse () break; case 29: -#line 601 "asn1p_y.y" +#line 600 "asn1p_y.y" { (yyval.a_module) = (yyvsp[(1) - (1)].a_module); } break; case 30: -#line 604 "asn1p_y.y" +#line 603 "asn1p_y.y" { if((yyvsp[(1) - (2)].a_module)) { (yyval.a_module) = (yyvsp[(1) - (2)].a_module); @@ -2581,51 +2580,51 @@ yyparse () (yyval.a_module) = (yyvsp[(2) - (2)].a_module); break; } - AL_IMPORT((yyval.a_module), members, (yyvsp[(2) - (2)].a_module), next); + asn1p_module_move_members((yyval.a_module), (yyvsp[(2) - (2)].a_module)); asn1p_module_free((yyvsp[(2) - (2)].a_module)); } break; case 31: -#line 621 "asn1p_y.y" +#line 620 "asn1p_y.y" { (yyval.a_module) = asn1p_module_new(); checkmem((yyval.a_module)); assert((yyvsp[(1) - (1)].a_expr)->expr_type != A1TC_INVALID); assert((yyvsp[(1) - (1)].a_expr)->meta_type != AMT_INVALID); - TQ_ADD(&((yyval.a_module)->members), (yyvsp[(1) - (1)].a_expr), next); + asn1p_module_member_add((yyval.a_module), (yyvsp[(1) - (1)].a_expr)); } break; case 32: -#line 628 "asn1p_y.y" +#line 627 "asn1p_y.y" { (yyval.a_module) = asn1p_module_new(); checkmem((yyval.a_module)); assert((yyvsp[(1) - (1)].a_expr)->expr_type != A1TC_INVALID); assert((yyvsp[(1) - (1)].a_expr)->meta_type != AMT_INVALID); - TQ_ADD(&((yyval.a_module)->members), (yyvsp[(1) - (1)].a_expr), next); + asn1p_module_member_add((yyval.a_module), (yyvsp[(1) - (1)].a_expr)); } break; case 33: -#line 642 "asn1p_y.y" +#line 641 "asn1p_y.y" { (yyval.a_module) = asn1p_module_new(); checkmem((yyval.a_module)); assert((yyvsp[(1) - (1)].a_expr)->expr_type != A1TC_INVALID); assert((yyvsp[(1) - (1)].a_expr)->meta_type != AMT_INVALID); - TQ_ADD(&((yyval.a_module)->members), (yyvsp[(1) - (1)].a_expr), next); + asn1p_module_member_add((yyval.a_module), (yyvsp[(1) - (1)].a_expr)); } break; case 34: -#line 650 "asn1p_y.y" +#line 649 "asn1p_y.y" { asn1p_lexer_hack_push_encoding_control(); } break; case 35: -#line 651 "asn1p_y.y" +#line 650 "asn1p_y.y" { fprintf(stderr, "WARNING: ENCODING-CONTROL %s " @@ -2637,7 +2636,7 @@ yyparse () break; case 36: -#line 663 "asn1p_y.y" +#line 662 "asn1p_y.y" { return yyerror( "Attempt to redefine a standard basic string type, " @@ -2646,12 +2645,12 @@ yyparse () break; case 37: -#line 676 "asn1p_y.y" +#line 675 "asn1p_y.y" { (yyval.a_module) = 0; } break; case 39: -#line 680 "asn1p_y.y" +#line 679 "asn1p_y.y" { if(!saved_aid && 0) return yyerror("Unterminated IMPORTS FROM, " @@ -2662,19 +2661,19 @@ yyparse () break; case 40: -#line 690 "asn1p_y.y" +#line 689 "asn1p_y.y" { return yyerror("Empty IMPORTS list"); } break; case 41: -#line 696 "asn1p_y.y" +#line 695 "asn1p_y.y" { (yyval.a_module) = asn1p_module_new(); } break; case 43: -#line 700 "asn1p_y.y" +#line 699 "asn1p_y.y" { (yyval.a_module) = asn1p_module_new(); checkmem((yyval.a_module)); @@ -2683,7 +2682,7 @@ yyparse () break; case 44: -#line 705 "asn1p_y.y" +#line 704 "asn1p_y.y" { (yyval.a_module) = (yyvsp[(1) - (2)].a_module); TQ_ADD(&((yyval.a_module)->imports), (yyvsp[(2) - (2)].a_xports), xp_next); @@ -2691,17 +2690,17 @@ yyparse () break; case 45: -#line 712 "asn1p_y.y" +#line 711 "asn1p_y.y" { memset(&(yyval.a_aid), 0, sizeof((yyval.a_aid))); } break; case 46: -#line 713 "asn1p_y.y" +#line 712 "asn1p_y.y" { (yyval.a_aid).oid = (yyvsp[(1) - (1)].a_oid); } break; case 47: -#line 717 "asn1p_y.y" +#line 716 "asn1p_y.y" { (yyval.a_xports) = (yyvsp[(1) - (4)].a_xports); (yyval.a_xports)->fromModuleName = (yyvsp[(3) - (4)].tv_str); @@ -2713,24 +2712,24 @@ yyparse () break; case 48: -#line 728 "asn1p_y.y" +#line 727 "asn1p_y.y" { (yyval.a_xports) = asn1p_xports_new(); checkmem((yyval.a_xports)); - TQ_ADD(&((yyval.a_xports)->members), (yyvsp[(1) - (1)].a_expr), next); + TQ_ADD(&((yyval.a_xports)->xp_members), (yyvsp[(1) - (1)].a_expr), next); } break; case 49: -#line 733 "asn1p_y.y" +#line 732 "asn1p_y.y" { (yyval.a_xports) = (yyvsp[(1) - (3)].a_xports); - TQ_ADD(&((yyval.a_xports)->members), (yyvsp[(3) - (3)].a_expr), next); + TQ_ADD(&((yyval.a_xports)->xp_members), (yyvsp[(3) - (3)].a_expr), next); } break; case 50: -#line 740 "asn1p_y.y" +#line 739 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -2740,7 +2739,7 @@ yyparse () break; case 51: -#line 746 "asn1p_y.y" +#line 745 "asn1p_y.y" { /* Completely equivalent to above */ (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -2750,7 +2749,7 @@ yyparse () break; case 52: -#line 752 "asn1p_y.y" +#line 751 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -2760,12 +2759,12 @@ yyparse () break; case 53: -#line 762 "asn1p_y.y" +#line 761 "asn1p_y.y" { (yyval.a_module) = 0; } break; case 54: -#line 763 "asn1p_y.y" +#line 762 "asn1p_y.y" { (yyval.a_module) = asn1p_module_new(); checkmem((yyval.a_module)); @@ -2778,21 +2777,21 @@ yyparse () break; case 55: -#line 775 "asn1p_y.y" +#line 774 "asn1p_y.y" { (yyval.a_xports) = (yyvsp[(2) - (3)].a_xports); } break; case 56: -#line 778 "asn1p_y.y" +#line 777 "asn1p_y.y" { (yyval.a_xports) = 0; } break; case 57: -#line 781 "asn1p_y.y" +#line 780 "asn1p_y.y" { /* Empty EXPORTS clause effectively prohibits export. */ (yyval.a_xports) = asn1p_xports_new(); @@ -2801,24 +2800,24 @@ yyparse () break; case 58: -#line 789 "asn1p_y.y" +#line 788 "asn1p_y.y" { (yyval.a_xports) = asn1p_xports_new(); assert((yyval.a_xports)); - TQ_ADD(&((yyval.a_xports)->members), (yyvsp[(1) - (1)].a_expr), next); + TQ_ADD(&((yyval.a_xports)->xp_members), (yyvsp[(1) - (1)].a_expr), next); } break; case 59: -#line 794 "asn1p_y.y" +#line 793 "asn1p_y.y" { (yyval.a_xports) = (yyvsp[(1) - (3)].a_xports); - TQ_ADD(&((yyval.a_xports)->members), (yyvsp[(3) - (3)].a_expr), next); + TQ_ADD(&((yyval.a_xports)->xp_members), (yyvsp[(3) - (3)].a_expr), next); } break; case 60: -#line 801 "asn1p_y.y" +#line 800 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -2828,7 +2827,7 @@ yyparse () break; case 61: -#line 807 "asn1p_y.y" +#line 806 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -2838,7 +2837,7 @@ yyparse () break; case 62: -#line 813 "asn1p_y.y" +#line 812 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -2848,12 +2847,12 @@ yyparse () break; case 63: -#line 822 "asn1p_y.y" +#line 821 "asn1p_y.y" { (yyval.a_constr) = (yyvsp[(2) - (3)].a_constr); } break; case 64: -#line 825 "asn1p_y.y" +#line 824 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(2) - (4)].a_expr); assert((yyval.a_expr)->Identifier == 0); @@ -2864,7 +2863,7 @@ yyparse () break; case 65: -#line 845 "asn1p_y.y" +#line 844 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -2875,7 +2874,7 @@ yyparse () break; case 66: -#line 855 "asn1p_y.y" +#line 854 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -2887,7 +2886,7 @@ yyparse () break; case 67: -#line 875 "asn1p_y.y" +#line 874 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(3) - (3)].a_expr); (yyval.a_expr)->Identifier = (yyvsp[(1) - (3)].tv_str); @@ -2897,7 +2896,7 @@ yyparse () break; case 68: -#line 881 "asn1p_y.y" +#line 880 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(3) - (3)].a_expr); (yyval.a_expr)->Identifier = (yyvsp[(1) - (3)].tv_str); @@ -2907,7 +2906,7 @@ yyparse () break; case 69: -#line 897 "asn1p_y.y" +#line 896 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(6) - (6)].a_expr); (yyval.a_expr)->Identifier = (yyvsp[(1) - (6)].tv_str); @@ -2916,7 +2915,7 @@ yyparse () break; case 70: -#line 903 "asn1p_y.y" +#line 902 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(6) - (6)].a_expr); (yyval.a_expr)->Identifier = (yyvsp[(1) - (6)].tv_str); @@ -2925,7 +2924,7 @@ yyparse () break; case 71: -#line 911 "asn1p_y.y" +#line 910 "asn1p_y.y" { int ret; (yyval.a_plist) = asn1p_paramlist_new(yylineno); @@ -2938,7 +2937,7 @@ yyparse () break; case 72: -#line 920 "asn1p_y.y" +#line 919 "asn1p_y.y" { int ret; (yyval.a_plist) = (yyvsp[(1) - (3)].a_plist); @@ -2950,7 +2949,7 @@ yyparse () break; case 73: -#line 931 "asn1p_y.y" +#line 930 "asn1p_y.y" { (yyval.a_parg).governor = NULL; (yyval.a_parg).argument = (yyvsp[(1) - (1)].tv_str); @@ -2958,7 +2957,7 @@ yyparse () break; case 74: -#line 935 "asn1p_y.y" +#line 934 "asn1p_y.y" { int ret; (yyval.a_parg).governor = asn1p_ref_new(yylineno, currentModule); @@ -2970,7 +2969,7 @@ yyparse () break; case 75: -#line 943 "asn1p_y.y" +#line 942 "asn1p_y.y" { int ret; (yyval.a_parg).governor = asn1p_ref_new(yylineno, currentModule); @@ -2982,7 +2981,7 @@ yyparse () break; case 76: -#line 951 "asn1p_y.y" +#line 950 "asn1p_y.y" { int ret; (yyval.a_parg).governor = asn1p_ref_new(yylineno, currentModule); @@ -2994,7 +2993,7 @@ yyparse () break; case 77: -#line 959 "asn1p_y.y" +#line 958 "asn1p_y.y" { int ret; (yyval.a_parg).governor = asn1p_ref_new(yylineno, currentModule); @@ -3006,7 +3005,7 @@ yyparse () break; case 78: -#line 970 "asn1p_y.y" +#line 969 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3015,7 +3014,7 @@ yyparse () break; case 79: -#line 975 "asn1p_y.y" +#line 974 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (3)].a_expr); asn1p_expr_add((yyval.a_expr), (yyvsp[(3) - (3)].a_expr)); @@ -3023,7 +3022,7 @@ yyparse () break; case 81: -#line 983 "asn1p_y.y" +#line 982 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3035,7 +3034,7 @@ yyparse () break; case 82: -#line 991 "asn1p_y.y" +#line 990 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3047,7 +3046,7 @@ yyparse () break; case 83: -#line 999 "asn1p_y.y" +#line 998 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); (yyval.a_expr)->expr_type = A1TC_VALUESET; @@ -3057,17 +3056,17 @@ yyparse () break; case 84: -#line 1022 "asn1p_y.y" +#line 1021 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); } break; case 85: -#line 1023 "asn1p_y.y" +#line 1022 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (1)].a_expr); } break; case 86: -#line 1026 "asn1p_y.y" +#line 1025 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3076,7 +3075,7 @@ yyparse () break; case 87: -#line 1031 "asn1p_y.y" +#line 1030 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (3)].a_expr); asn1p_expr_add((yyval.a_expr), (yyvsp[(3) - (3)].a_expr)); @@ -3084,7 +3083,7 @@ yyparse () break; case 88: -#line 1035 "asn1p_y.y" +#line 1034 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (5)].a_expr); asn1p_expr_add_many((yyval.a_expr), (yyvsp[(4) - (5)].a_expr)); @@ -3093,7 +3092,7 @@ yyparse () break; case 89: -#line 1043 "asn1p_y.y" +#line 1042 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(2) - (3)].a_expr); assert((yyval.a_expr)->Identifier == 0); @@ -3104,7 +3103,7 @@ yyparse () break; case 90: -#line 1050 "asn1p_y.y" +#line 1049 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (2)].a_expr); (yyvsp[(2) - (2)].a_marker).flags |= (yyval.a_expr)->marker.flags; @@ -3114,7 +3113,7 @@ yyparse () break; case 91: -#line 1056 "asn1p_y.y" +#line 1055 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3125,14 +3124,14 @@ yyparse () break; case 92: -#line 1063 "asn1p_y.y" +#line 1062 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (1)].a_expr); } break; case 93: -#line 1069 "asn1p_y.y" +#line 1068 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3141,7 +3140,7 @@ yyparse () break; case 94: -#line 1074 "asn1p_y.y" +#line 1073 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (3)].a_expr); asn1p_expr_add((yyval.a_expr), (yyvsp[(3) - (3)].a_expr)); @@ -3149,7 +3148,7 @@ yyparse () break; case 95: -#line 1081 "asn1p_y.y" +#line 1080 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(2) - (2)].a_expr); assert((yyval.a_expr)->Identifier == 0); @@ -3158,14 +3157,14 @@ yyparse () break; case 96: -#line 1086 "asn1p_y.y" +#line 1085 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (1)].a_expr); } break; case 97: -#line 1089 "asn1p_y.y" +#line 1088 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (1)].a_expr); _fixup_anonymous_identifier((yyval.a_expr)); @@ -3173,7 +3172,7 @@ yyparse () break; case 98: -#line 1096 "asn1p_y.y" +#line 1095 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(3) - (5)].a_expr); checkmem((yyval.a_expr)); @@ -3184,17 +3183,17 @@ yyparse () break; case 99: -#line 1106 "asn1p_y.y" +#line 1105 "asn1p_y.y" { (yyval.a_int) = 0; } break; case 100: -#line 1107 "asn1p_y.y" +#line 1106 "asn1p_y.y" { (yyval.a_int) = 1; } break; case 101: -#line 1111 "asn1p_y.y" +#line 1110 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3205,7 +3204,7 @@ yyparse () break; case 102: -#line 1118 "asn1p_y.y" +#line 1117 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (3)].a_expr); asn1p_expr_add((yyval.a_expr), (yyvsp[(3) - (3)].a_expr)); @@ -3213,7 +3212,7 @@ yyparse () break; case 103: -#line 1128 "asn1p_y.y" +#line 1127 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3225,7 +3224,7 @@ yyparse () break; case 104: -#line 1138 "asn1p_y.y" +#line 1137 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); (yyval.a_expr)->Identifier = (yyvsp[(1) - (4)].tv_str); @@ -3238,7 +3237,7 @@ yyparse () break; case 105: -#line 1149 "asn1p_y.y" +#line 1148 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); (yyval.a_expr)->Identifier = (yyvsp[(1) - (3)].tv_str); @@ -3250,7 +3249,7 @@ yyparse () break; case 106: -#line 1159 "asn1p_y.y" +#line 1158 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3263,7 +3262,7 @@ yyparse () break; case 107: -#line 1170 "asn1p_y.y" +#line 1169 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); (yyval.a_expr)->Identifier = (yyvsp[(1) - (3)].tv_str); @@ -3275,7 +3274,7 @@ yyparse () break; case 108: -#line 1180 "asn1p_y.y" +#line 1179 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3288,7 +3287,7 @@ yyparse () break; case 109: -#line 1191 "asn1p_y.y" +#line 1190 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3301,31 +3300,31 @@ yyparse () break; case 110: -#line 1203 "asn1p_y.y" +#line 1202 "asn1p_y.y" { (yyval.a_wsynt) = 0; } break; case 111: -#line 1204 "asn1p_y.y" +#line 1203 "asn1p_y.y" { (yyval.a_wsynt) = (yyvsp[(1) - (1)].a_wsynt); } break; case 112: -#line 1211 "asn1p_y.y" +#line 1210 "asn1p_y.y" { asn1p_lexer_hack_enable_with_syntax(); } break; case 113: -#line 1213 "asn1p_y.y" +#line 1212 "asn1p_y.y" { (yyval.a_wsynt) = (yyvsp[(5) - (6)].a_wsynt); } break; case 114: -#line 1219 "asn1p_y.y" +#line 1218 "asn1p_y.y" { (yyval.a_wsynt) = asn1p_wsyntx_new(); TQ_ADD(&((yyval.a_wsynt)->chunks), (yyvsp[(1) - (1)].a_wchunk), next); @@ -3333,7 +3332,7 @@ yyparse () break; case 115: -#line 1223 "asn1p_y.y" +#line 1222 "asn1p_y.y" { (yyval.a_wsynt) = (yyvsp[(1) - (2)].a_wsynt); TQ_ADD(&((yyval.a_wsynt)->chunks), (yyvsp[(2) - (2)].a_wchunk), next); @@ -3341,7 +3340,7 @@ yyparse () break; case 116: -#line 1230 "asn1p_y.y" +#line 1229 "asn1p_y.y" { (yyval.a_wchunk) = asn1p_wsyntx_chunk_fromstring((yyvsp[(1) - (1)].tv_opaque).buf, 0); (yyval.a_wchunk)->type = WC_WHITESPACE; @@ -3349,14 +3348,14 @@ yyparse () break; case 117: -#line 1234 "asn1p_y.y" +#line 1233 "asn1p_y.y" { (yyval.a_wchunk) = asn1p_wsyntx_chunk_fromstring((yyvsp[(1) - (1)].tv_str), 0); } break; case 118: -#line 1237 "asn1p_y.y" +#line 1236 "asn1p_y.y" { (yyval.a_wchunk) = asn1p_wsyntx_chunk_fromstring((yyvsp[(1) - (1)].a_refcomp).name, 0); (yyval.a_wchunk)->type = WC_FIELD; @@ -3364,14 +3363,14 @@ yyparse () break; case 119: -#line 1241 "asn1p_y.y" +#line 1240 "asn1p_y.y" { (yyval.a_wchunk) = asn1p_wsyntx_chunk_fromsyntax((yyvsp[(2) - (3)].a_wsynt)); } break; case 120: -#line 1247 "asn1p_y.y" +#line 1246 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3383,7 +3382,7 @@ yyparse () break; case 121: -#line 1255 "asn1p_y.y" +#line 1254 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3396,7 +3395,7 @@ yyparse () break; case 122: -#line 1264 "asn1p_y.y" +#line 1263 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3409,7 +3408,7 @@ yyparse () break; case 124: -#line 1278 "asn1p_y.y" +#line 1277 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(2) - (2)].a_expr); (yyval.a_expr)->tag = (yyvsp[(1) - (2)].a_tag); @@ -3417,7 +3416,7 @@ yyparse () break; case 125: -#line 1285 "asn1p_y.y" +#line 1284 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (2)].a_expr); /* @@ -3441,7 +3440,7 @@ yyparse () break; case 126: -#line 1308 "asn1p_y.y" +#line 1307 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (2)].a_expr); /* @@ -3465,7 +3464,7 @@ yyparse () break; case 127: -#line 1331 "asn1p_y.y" +#line 1330 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(2) - (3)].a_expr); (yyval.a_expr)->tag = (yyvsp[(1) - (3)].a_tag); @@ -3490,7 +3489,7 @@ yyparse () break; case 128: -#line 1355 "asn1p_y.y" +#line 1354 "asn1p_y.y" { (yyval.a_int) = asn1p_as_pointer ? EM_INDIRECT : 0; asn1p_as_pointer = 0; @@ -3498,7 +3497,7 @@ yyparse () break; case 129: -#line 1362 "asn1p_y.y" +#line 1361 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(2) - (2)].a_expr); (yyval.a_expr)->marker.flags |= (yyvsp[(1) - (2)].a_int); @@ -3518,7 +3517,7 @@ yyparse () break; case 133: -#line 1386 "asn1p_y.y" +#line 1385 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(3) - (4)].a_expr); assert((yyval.a_expr)->expr_type == A1TC_INVALID); @@ -3528,7 +3527,7 @@ yyparse () break; case 134: -#line 1392 "asn1p_y.y" +#line 1391 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(3) - (4)].a_expr); assert((yyval.a_expr)->expr_type == A1TC_INVALID); @@ -3538,7 +3537,7 @@ yyparse () break; case 135: -#line 1398 "asn1p_y.y" +#line 1397 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(3) - (4)].a_expr); assert((yyval.a_expr)->expr_type == A1TC_INVALID); @@ -3548,7 +3547,7 @@ yyparse () break; case 136: -#line 1404 "asn1p_y.y" +#line 1403 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3562,7 +3561,7 @@ yyparse () break; case 137: -#line 1414 "asn1p_y.y" +#line 1413 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3576,7 +3575,7 @@ yyparse () break; case 138: -#line 1424 "asn1p_y.y" +#line 1423 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3586,7 +3585,7 @@ yyparse () break; case 139: -#line 1430 "asn1p_y.y" +#line 1429 "asn1p_y.y" { int ret; (yyval.a_expr) = NEW_EXPR(); @@ -3602,7 +3601,7 @@ yyparse () break; case 140: -#line 1442 "asn1p_y.y" +#line 1441 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3613,7 +3612,7 @@ yyparse () break; case 141: -#line 1457 "asn1p_y.y" +#line 1456 "asn1p_y.y" { int ret; (yyval.a_ref) = asn1p_ref_new(yylineno, currentModule); @@ -3625,7 +3624,7 @@ yyparse () break; case 142: -#line 1465 "asn1p_y.y" +#line 1464 "asn1p_y.y" { int ret; (yyval.a_ref) = asn1p_ref_new(yylineno, currentModule); @@ -3637,7 +3636,7 @@ yyparse () break; case 143: -#line 1473 "asn1p_y.y" +#line 1472 "asn1p_y.y" { int ret; (yyval.a_ref) = asn1p_ref_new(yylineno, currentModule); @@ -3652,7 +3651,7 @@ yyparse () break; case 144: -#line 1484 "asn1p_y.y" +#line 1483 "asn1p_y.y" { int ret; (yyval.a_ref) = asn1p_ref_new(yylineno, currentModule); @@ -3667,7 +3666,7 @@ yyparse () break; case 145: -#line 1495 "asn1p_y.y" +#line 1494 "asn1p_y.y" { int ret; (yyval.a_ref) = (yyvsp[(3) - (3)].a_ref); @@ -3690,7 +3689,7 @@ yyparse () break; case 146: -#line 1517 "asn1p_y.y" +#line 1516 "asn1p_y.y" { int ret; (yyval.a_ref) = asn1p_ref_new(yylineno, currentModule); @@ -3702,7 +3701,7 @@ yyparse () break; case 147: -#line 1525 "asn1p_y.y" +#line 1524 "asn1p_y.y" { int ret; (yyval.a_ref) = (yyvsp[(1) - (3)].a_ref); @@ -3713,7 +3712,7 @@ yyparse () break; case 149: -#line 1538 "asn1p_y.y" +#line 1537 "asn1p_y.y" { (yyval.a_refcomp).lex_type = RLT_AmpUppercase; (yyval.a_refcomp).name = (yyvsp[(1) - (1)].tv_str); @@ -3721,7 +3720,7 @@ yyparse () break; case 150: -#line 1543 "asn1p_y.y" +#line 1542 "asn1p_y.y" { (yyval.a_refcomp).lex_type = RLT_Amplowercase; (yyval.a_refcomp).name = (yyvsp[(1) - (1)].tv_str); @@ -3729,7 +3728,7 @@ yyparse () break; case 151: -#line 1552 "asn1p_y.y" +#line 1551 "asn1p_y.y" { (yyval.a_ref) = asn1p_ref_new(yylineno, currentModule); asn1p_ref_add_component((yyval.a_ref), (yyvsp[(1) - (1)].tv_str), RLT_AmpUppercase); @@ -3738,7 +3737,7 @@ yyparse () break; case 152: -#line 1557 "asn1p_y.y" +#line 1556 "asn1p_y.y" { (yyval.a_ref) = (yyval.a_ref); asn1p_ref_add_component((yyval.a_ref), (yyvsp[(3) - (3)].tv_str), RLT_AmpUppercase); @@ -3747,7 +3746,7 @@ yyparse () break; case 153: -#line 1562 "asn1p_y.y" +#line 1561 "asn1p_y.y" { (yyval.a_ref) = (yyval.a_ref); asn1p_ref_add_component((yyval.a_ref), (yyvsp[(3) - (3)].tv_str), RLT_Amplowercase); @@ -3756,7 +3755,7 @@ yyparse () break; case 154: -#line 1570 "asn1p_y.y" +#line 1569 "asn1p_y.y" { (yyval.a_ref) = asn1p_ref_new(yylineno, currentModule); asn1p_ref_add_component((yyval.a_ref), (yyvsp[(1) - (1)].tv_str), RLT_CAPITALS); @@ -3765,7 +3764,7 @@ yyparse () break; case 155: -#line 1593 "asn1p_y.y" +#line 1592 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(2) - (4)].a_expr); assert((yyval.a_expr)->Identifier == NULL); @@ -3776,12 +3775,12 @@ yyparse () break; case 158: -#line 1605 "asn1p_y.y" +#line 1604 "asn1p_y.y" { asn1p_lexer_hack_push_opaque_state(); } break; case 159: -#line 1605 "asn1p_y.y" +#line 1604 "asn1p_y.y" { (yyval.a_value) = asn1p_value_frombuf((yyvsp[(3) - (3)].tv_opaque).buf, (yyvsp[(3) - (3)].tv_opaque).len, 0); checkmem((yyval.a_value)); @@ -3790,7 +3789,7 @@ yyparse () break; case 160: -#line 1613 "asn1p_y.y" +#line 1612 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromint(0); checkmem((yyval.a_value)); @@ -3799,7 +3798,7 @@ yyparse () break; case 161: -#line 1618 "asn1p_y.y" +#line 1617 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromint(0); checkmem((yyval.a_value)); @@ -3808,7 +3807,7 @@ yyparse () break; case 162: -#line 1623 "asn1p_y.y" +#line 1622 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromint(1); checkmem((yyval.a_value)); @@ -3817,7 +3816,7 @@ yyparse () break; case 168: -#line 1636 "asn1p_y.y" +#line 1635 "asn1p_y.y" { asn1p_ref_t *ref; int ret; @@ -3835,7 +3834,7 @@ yyparse () break; case 169: -#line 1654 "asn1p_y.y" +#line 1653 "asn1p_y.y" { (yyval.a_value) = asn1p_value_frombuf((yyvsp[(1) - (1)].tv_opaque).buf, (yyvsp[(1) - (1)].tv_opaque).len, 0); checkmem((yyval.a_value)); @@ -3843,7 +3842,7 @@ yyparse () break; case 170: -#line 1658 "asn1p_y.y" +#line 1657 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromint((yyvsp[(1) - (1)].a_int)); checkmem((yyval.a_value)); @@ -3852,7 +3851,7 @@ yyparse () break; case 171: -#line 1663 "asn1p_y.y" +#line 1662 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromint((yyvsp[(1) - (1)].a_int)); checkmem((yyval.a_value)); @@ -3861,7 +3860,7 @@ yyparse () break; case 172: -#line 1671 "asn1p_y.y" +#line 1670 "asn1p_y.y" { (yyval.tv_opaque).len = (yyvsp[(1) - (1)].tv_opaque).len + 1; (yyval.tv_opaque).buf = malloc(1 + (yyval.tv_opaque).len + 1); @@ -3874,7 +3873,7 @@ yyparse () break; case 173: -#line 1680 "asn1p_y.y" +#line 1679 "asn1p_y.y" { int newsize = (yyvsp[(1) - (2)].tv_opaque).len + (yyvsp[(2) - (2)].tv_opaque).len; char *p = malloc(newsize + 1); @@ -3890,7 +3889,7 @@ yyparse () break; case 175: -#line 1696 "asn1p_y.y" +#line 1695 "asn1p_y.y" { (yyval.tv_opaque).len = strlen((yyvsp[(1) - (1)].tv_str)); (yyval.tv_opaque).buf = (yyvsp[(1) - (1)].tv_str); @@ -3898,77 +3897,77 @@ yyparse () break; case 176: -#line 1702 "asn1p_y.y" +#line 1701 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_BOOLEAN; } break; case 177: -#line 1703 "asn1p_y.y" +#line 1702 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_NULL; } break; case 178: -#line 1704 "asn1p_y.y" +#line 1703 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_REAL; } break; case 179: -#line 1705 "asn1p_y.y" +#line 1704 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_OCTET_STRING; } break; case 180: -#line 1706 "asn1p_y.y" +#line 1705 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_OBJECT_IDENTIFIER; } break; case 181: -#line 1707 "asn1p_y.y" +#line 1706 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_RELATIVE_OID; } break; case 182: -#line 1708 "asn1p_y.y" +#line 1707 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_EXTERNAL; } break; case 183: -#line 1709 "asn1p_y.y" +#line 1708 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_EMBEDDED_PDV; } break; case 184: -#line 1710 "asn1p_y.y" +#line 1709 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_CHARACTER_STRING; } break; case 185: -#line 1711 "asn1p_y.y" +#line 1710 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_UTCTime; } break; case 186: -#line 1712 "asn1p_y.y" +#line 1711 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_GeneralizedTime; } break; case 189: -#line 1721 "asn1p_y.y" +#line 1720 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_INTEGER; } break; case 190: -#line 1722 "asn1p_y.y" +#line 1721 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_ENUMERATED; } break; case 191: -#line 1723 "asn1p_y.y" +#line 1722 "asn1p_y.y" { (yyval.a_type) = ASN_BASIC_BIT_STRING; } break; case 192: -#line 1727 "asn1p_y.y" +#line 1726 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -3978,7 +3977,7 @@ yyparse () break; case 193: -#line 1733 "asn1p_y.y" +#line 1732 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(3) - (4)].a_expr); (yyval.a_expr)->expr_type = ASN_BASIC_INTEGER; @@ -3987,7 +3986,7 @@ yyparse () break; case 194: -#line 1738 "asn1p_y.y" +#line 1737 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(3) - (4)].a_expr); (yyval.a_expr)->expr_type = ASN_BASIC_ENUMERATED; @@ -3996,7 +3995,7 @@ yyparse () break; case 195: -#line 1743 "asn1p_y.y" +#line 1742 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(4) - (5)].a_expr); (yyval.a_expr)->expr_type = ASN_BASIC_BIT_STRING; @@ -4005,7 +4004,7 @@ yyparse () break; case 196: -#line 1748 "asn1p_y.y" +#line 1747 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(3) - (4)].a_expr); (yyval.a_expr)->expr_type = ASN_BASIC_BIT_STRING; @@ -4014,7 +4013,7 @@ yyparse () break; case 197: -#line 1753 "asn1p_y.y" +#line 1752 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4024,12 +4023,12 @@ yyparse () break; case 198: -#line 1762 "asn1p_y.y" +#line 1761 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_BMPString; } break; case 199: -#line 1763 "asn1p_y.y" +#line 1762 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_GeneralString; fprintf(stderr, "WARNING: GeneralString is not fully supported\n"); @@ -4037,7 +4036,7 @@ yyparse () break; case 200: -#line 1767 "asn1p_y.y" +#line 1766 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_GraphicString; fprintf(stderr, "WARNING: GraphicString is not fully supported\n"); @@ -4045,27 +4044,27 @@ yyparse () break; case 201: -#line 1771 "asn1p_y.y" +#line 1770 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_IA5String; } break; case 202: -#line 1772 "asn1p_y.y" +#line 1771 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_ISO646String; } break; case 203: -#line 1773 "asn1p_y.y" +#line 1772 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_NumericString; } break; case 204: -#line 1774 "asn1p_y.y" +#line 1773 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_PrintableString; } break; case 205: -#line 1775 "asn1p_y.y" +#line 1774 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_T61String; fprintf(stderr, "WARNING: T61String is not fully supported\n"); @@ -4073,22 +4072,22 @@ yyparse () break; case 206: -#line 1779 "asn1p_y.y" +#line 1778 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_TeletexString; } break; case 207: -#line 1780 "asn1p_y.y" +#line 1779 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_UniversalString; } break; case 208: -#line 1781 "asn1p_y.y" +#line 1780 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_UTF8String; } break; case 209: -#line 1782 "asn1p_y.y" +#line 1781 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_VideotexString; fprintf(stderr, "WARNING: VideotexString is not fully supported\n"); @@ -4096,39 +4095,39 @@ yyparse () break; case 210: -#line 1786 "asn1p_y.y" +#line 1785 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_VisibleString; } break; case 211: -#line 1787 "asn1p_y.y" +#line 1786 "asn1p_y.y" { (yyval.a_type) = ASN_STRING_ObjectDescriptor; } break; case 216: -#line 1799 "asn1p_y.y" +#line 1798 "asn1p_y.y" { (yyval.a_constr) = 0; } break; case 218: -#line 1804 "asn1p_y.y" +#line 1803 "asn1p_y.y" { (yyval.a_constr) = 0; } break; case 220: -#line 1809 "asn1p_y.y" +#line 1808 "asn1p_y.y" { (yyval.a_constr) = 0; } break; case 223: -#line 1815 "asn1p_y.y" +#line 1814 "asn1p_y.y" { CONSTRAINT_INSERT((yyval.a_constr), ACT_CA_SET, (yyvsp[(2) - (3)].a_constr), 0); } break; case 225: -#line 1822 "asn1p_y.y" +#line 1821 "asn1p_y.y" { if((yyvsp[(2) - (2)].a_constr)->type == ACT_CA_SET && (yyvsp[(2) - (2)].a_constr)->el_count == 1) { CONSTRAINT_INSERT((yyval.a_constr), ACT_CA_SET, (yyvsp[(1) - (2)].a_constr), (yyvsp[(2) - (2)].a_constr)->elements[0]); @@ -4139,7 +4138,7 @@ yyparse () break; case 229: -#line 1836 "asn1p_y.y" +#line 1835 "asn1p_y.y" { (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); (yyval.a_constr)->type = ACT_EL_EXT; @@ -4147,7 +4146,7 @@ yyparse () break; case 231: -#line 1841 "asn1p_y.y" +#line 1840 "asn1p_y.y" { asn1p_constraint_t *ct; ct = asn1p_constraint_new(yylineno, currentModule); @@ -4157,7 +4156,7 @@ yyparse () break; case 232: -#line 1847 "asn1p_y.y" +#line 1846 "asn1p_y.y" { asn1p_constraint_t *ct; ct = asn1p_constraint_new(yylineno, currentModule); @@ -4169,35 +4168,35 @@ yyparse () break; case 234: -#line 1859 "asn1p_y.y" +#line 1858 "asn1p_y.y" { CONSTRAINT_INSERT((yyval.a_constr), ACT_CA_AEX, (yyvsp[(3) - (3)].a_constr), 0); } break; case 236: -#line 1866 "asn1p_y.y" +#line 1865 "asn1p_y.y" { CONSTRAINT_INSERT((yyval.a_constr), ACT_CA_UNI, (yyvsp[(1) - (3)].a_constr), (yyvsp[(3) - (3)].a_constr)); } break; case 238: -#line 1873 "asn1p_y.y" +#line 1872 "asn1p_y.y" { CONSTRAINT_INSERT((yyval.a_constr), ACT_CA_INT, (yyvsp[(1) - (3)].a_constr), (yyvsp[(3) - (3)].a_constr)); } break; case 240: -#line 1881 "asn1p_y.y" +#line 1880 "asn1p_y.y" { CONSTRAINT_INSERT((yyval.a_constr), ACT_CA_EXC, (yyvsp[(1) - (3)].a_constr), (yyvsp[(3) - (3)].a_constr)); } break; case 242: -#line 1888 "asn1p_y.y" +#line 1887 "asn1p_y.y" { int ret; (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); @@ -4209,7 +4208,7 @@ yyparse () break; case 243: -#line 1899 "asn1p_y.y" +#line 1898 "asn1p_y.y" { (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); checkmem((yyval.a_constr)); @@ -4219,7 +4218,7 @@ yyparse () break; case 244: -#line 1905 "asn1p_y.y" +#line 1904 "asn1p_y.y" { (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); checkmem((yyval.a_constr)); @@ -4229,21 +4228,21 @@ yyparse () break; case 250: -#line 1921 "asn1p_y.y" +#line 1920 "asn1p_y.y" { CONSTRAINT_INSERT((yyval.a_constr), ACT_CT_FROM, (yyvsp[(2) - (2)].a_constr), 0); } break; case 251: -#line 1926 "asn1p_y.y" +#line 1925 "asn1p_y.y" { CONSTRAINT_INSERT((yyval.a_constr), ACT_CT_SIZE, (yyvsp[(2) - (2)].a_constr), 0); } break; case 252: -#line 1931 "asn1p_y.y" +#line 1930 "asn1p_y.y" { (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); (yyval.a_constr)->type = ACT_CT_PATTERN; @@ -4252,7 +4251,7 @@ yyparse () break; case 253: -#line 1936 "asn1p_y.y" +#line 1935 "asn1p_y.y" { asn1p_ref_t *ref; (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); @@ -4265,7 +4264,7 @@ yyparse () break; case 254: -#line 1948 "asn1p_y.y" +#line 1947 "asn1p_y.y" { (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); checkmem((yyval.a_constr)); @@ -4276,7 +4275,7 @@ yyparse () break; case 256: -#line 1958 "asn1p_y.y" +#line 1957 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromint(-123); (yyval.a_value)->type = ATV_MIN; @@ -4284,7 +4283,7 @@ yyparse () break; case 258: -#line 1965 "asn1p_y.y" +#line 1964 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromint(321); (yyval.a_value)->type = ATV_MAX; @@ -4292,7 +4291,7 @@ yyparse () break; case 260: -#line 1973 "asn1p_y.y" +#line 1972 "asn1p_y.y" { (yyval.a_value) = _convert_bitstring2binary((yyvsp[(1) - (1)].tv_str), 'B'); checkmem((yyval.a_value)); @@ -4301,7 +4300,7 @@ yyparse () break; case 261: -#line 1978 "asn1p_y.y" +#line 1977 "asn1p_y.y" { (yyval.a_value) = _convert_bitstring2binary((yyvsp[(1) - (1)].tv_str), 'H'); checkmem((yyval.a_value)); @@ -4310,7 +4309,7 @@ yyparse () break; case 262: -#line 1986 "asn1p_y.y" +#line 1985 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromtype((yyvsp[(2) - (2)].a_expr)); checkmem((yyval.a_value)); @@ -4319,7 +4318,7 @@ yyparse () break; case 263: -#line 1992 "asn1p_y.y" +#line 1991 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromtype((yyvsp[(1) - (1)].a_expr)); checkmem((yyval.a_value)); @@ -4328,14 +4327,14 @@ yyparse () break; case 264: -#line 2004 "asn1p_y.y" +#line 2003 "asn1p_y.y" { CONSTRAINT_INSERT((yyval.a_constr), ACT_CT_WCOMP, (yyvsp[(3) - (3)].a_constr), 0); } break; case 265: -#line 2007 "asn1p_y.y" +#line 2006 "asn1p_y.y" { assert((yyvsp[(3) - (3)].a_constr)->type == ACT_CA_CSV); (yyvsp[(3) - (3)].a_constr)->type = ACT_CT_WCOMPS; @@ -4344,12 +4343,12 @@ yyparse () break; case 269: -#line 2015 "asn1p_y.y" +#line 2014 "asn1p_y.y" { (yyval.a_constr) = (yyvsp[(2) - (3)].a_constr); } break; case 270: -#line 2017 "asn1p_y.y" +#line 2016 "asn1p_y.y" { assert((yyvsp[(4) - (5)].a_constr)->type == ACT_CA_CSV); (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); @@ -4365,7 +4364,7 @@ yyparse () break; case 271: -#line 2030 "asn1p_y.y" +#line 2029 "asn1p_y.y" { (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); (yyval.a_constr)->type = ACT_CA_CSV; @@ -4374,7 +4373,7 @@ yyparse () break; case 272: -#line 2035 "asn1p_y.y" +#line 2034 "asn1p_y.y" { (yyval.a_constr) = (yyvsp[(1) - (3)].a_constr); asn1p_constraint_insert((yyval.a_constr), (yyvsp[(3) - (3)].a_constr)); @@ -4382,7 +4381,7 @@ yyparse () break; case 273: -#line 2041 "asn1p_y.y" +#line 2040 "asn1p_y.y" { (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); checkmem((yyval.a_constr)); @@ -4394,43 +4393,43 @@ yyparse () break; case 274: -#line 2055 "asn1p_y.y" +#line 2054 "asn1p_y.y" { (yyval.a_pres) = ACPRES_DEFAULT; } break; case 275: -#line 2056 "asn1p_y.y" +#line 2055 "asn1p_y.y" { (yyval.a_pres) = (yyvsp[(1) - (1)].a_pres); } break; case 276: -#line 2060 "asn1p_y.y" +#line 2059 "asn1p_y.y" { (yyval.a_pres) = ACPRES_PRESENT; } break; case 277: -#line 2063 "asn1p_y.y" +#line 2062 "asn1p_y.y" { (yyval.a_pres) = ACPRES_ABSENT; } break; case 278: -#line 2066 "asn1p_y.y" +#line 2065 "asn1p_y.y" { (yyval.a_pres) = ACPRES_OPTIONAL; } break; case 282: -#line 2081 "asn1p_y.y" +#line 2080 "asn1p_y.y" { asn1p_lexer_hack_push_opaque_state(); } break; case 283: -#line 2081 "asn1p_y.y" +#line 2080 "asn1p_y.y" { (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); checkmem((yyval.a_constr)); @@ -4442,7 +4441,7 @@ yyparse () break; case 284: -#line 2092 "asn1p_y.y" +#line 2091 "asn1p_y.y" { (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); (yyval.a_constr)->type = ACT_CT_CTNG; @@ -4452,41 +4451,41 @@ yyparse () break; case 285: -#line 2101 "asn1p_y.y" +#line 2100 "asn1p_y.y" { (yyval.a_ctype) = ACT_EL_RANGE; } break; case 286: -#line 2102 "asn1p_y.y" +#line 2101 "asn1p_y.y" { (yyval.a_ctype) = ACT_EL_RLRANGE; } break; case 287: -#line 2103 "asn1p_y.y" +#line 2102 "asn1p_y.y" { (yyval.a_ctype) = ACT_EL_LLRANGE; } break; case 288: -#line 2104 "asn1p_y.y" +#line 2103 "asn1p_y.y" { (yyval.a_ctype) = ACT_EL_ULRANGE; } break; case 289: -#line 2107 "asn1p_y.y" +#line 2106 "asn1p_y.y" { (yyval.a_constr) = (yyvsp[(1) - (1)].a_constr); } break; case 290: -#line 2110 "asn1p_y.y" +#line 2109 "asn1p_y.y" { (yyval.a_constr) = (yyvsp[(1) - (1)].a_constr); } break; case 291: -#line 2119 "asn1p_y.y" +#line 2118 "asn1p_y.y" { asn1p_ref_t *ref = asn1p_ref_new(yylineno, currentModule); asn1p_constraint_t *ct; @@ -4503,14 +4502,14 @@ yyparse () break; case 292: -#line 2135 "asn1p_y.y" +#line 2134 "asn1p_y.y" { CONSTRAINT_INSERT((yyval.a_constr), ACT_CA_CRC, (yyvsp[(1) - (4)].a_constr), (yyvsp[(3) - (4)].a_constr)); } break; case 293: -#line 2141 "asn1p_y.y" +#line 2140 "asn1p_y.y" { (yyval.a_constr) = asn1p_constraint_new(yylineno, currentModule); checkmem((yyval.a_constr)); @@ -4520,7 +4519,7 @@ yyparse () break; case 294: -#line 2147 "asn1p_y.y" +#line 2146 "asn1p_y.y" { asn1p_constraint_t *ct; ct = asn1p_constraint_new(yylineno, currentModule); @@ -4532,7 +4531,7 @@ yyparse () break; case 295: -#line 2161 "asn1p_y.y" +#line 2160 "asn1p_y.y" { char *p = malloc(strlen((yyvsp[(2) - (2)].tv_str)) + 2); int ret; @@ -4547,7 +4546,7 @@ yyparse () break; case 296: -#line 2172 "asn1p_y.y" +#line 2171 "asn1p_y.y" { char *p = malloc(strlen((yyvsp[(3) - (3)].tv_str)) + 3); int ret; @@ -4563,14 +4562,14 @@ yyparse () break; case 297: -#line 2188 "asn1p_y.y" +#line 2187 "asn1p_y.y" { (yyval.tv_str) = (yyvsp[(1) - (1)].tv_str); } break; case 298: -#line 2191 "asn1p_y.y" +#line 2190 "asn1p_y.y" { int l1 = strlen((yyvsp[(1) - (3)].tv_str)); int l3 = strlen((yyvsp[(3) - (3)].tv_str)); @@ -4585,7 +4584,7 @@ yyparse () break; case 299: -#line 2211 "asn1p_y.y" +#line 2210 "asn1p_y.y" { (yyval.a_marker).flags = EM_NOMARK; (yyval.a_marker).default_value = 0; @@ -4593,12 +4592,12 @@ yyparse () break; case 300: -#line 2215 "asn1p_y.y" +#line 2214 "asn1p_y.y" { (yyval.a_marker) = (yyvsp[(1) - (1)].a_marker); } break; case 301: -#line 2219 "asn1p_y.y" +#line 2218 "asn1p_y.y" { (yyval.a_marker).flags = EM_OPTIONAL | EM_INDIRECT; (yyval.a_marker).default_value = 0; @@ -4606,7 +4605,7 @@ yyparse () break; case 302: -#line 2223 "asn1p_y.y" +#line 2222 "asn1p_y.y" { (yyval.a_marker).flags = EM_DEFAULT; (yyval.a_marker).default_value = (yyvsp[(2) - (2)].a_value); @@ -4614,7 +4613,7 @@ yyparse () break; case 303: -#line 2230 "asn1p_y.y" +#line 2229 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4623,7 +4622,7 @@ yyparse () break; case 304: -#line 2235 "asn1p_y.y" +#line 2234 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (3)].a_expr); asn1p_expr_add((yyval.a_expr), (yyvsp[(3) - (3)].a_expr)); @@ -4631,7 +4630,7 @@ yyparse () break; case 305: -#line 2241 "asn1p_y.y" +#line 2240 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4642,7 +4641,7 @@ yyparse () break; case 306: -#line 2250 "asn1p_y.y" +#line 2249 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4651,7 +4650,7 @@ yyparse () break; case 307: -#line 2255 "asn1p_y.y" +#line 2254 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (3)].a_expr); asn1p_expr_add((yyval.a_expr), (yyvsp[(3) - (3)].a_expr)); @@ -4659,7 +4658,7 @@ yyparse () break; case 308: -#line 2262 "asn1p_y.y" +#line 2261 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4671,7 +4670,7 @@ yyparse () break; case 309: -#line 2270 "asn1p_y.y" +#line 2269 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4683,7 +4682,7 @@ yyparse () break; case 310: -#line 2280 "asn1p_y.y" +#line 2279 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4692,7 +4691,7 @@ yyparse () break; case 311: -#line 2285 "asn1p_y.y" +#line 2284 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (3)].a_expr); asn1p_expr_add((yyval.a_expr), (yyvsp[(3) - (3)].a_expr)); @@ -4700,7 +4699,7 @@ yyparse () break; case 312: -#line 2292 "asn1p_y.y" +#line 2291 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4712,7 +4711,7 @@ yyparse () break; case 313: -#line 2300 "asn1p_y.y" +#line 2299 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4724,7 +4723,7 @@ yyparse () break; case 314: -#line 2310 "asn1p_y.y" +#line 2309 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (1)].a_expr); asn1p_expr_t *first_memb = TQ_FIRST(&((yyval.a_expr)->members)); @@ -4741,7 +4740,7 @@ yyparse () break; case 315: -#line 2325 "asn1p_y.y" +#line 2324 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4750,7 +4749,7 @@ yyparse () break; case 316: -#line 2330 "asn1p_y.y" +#line 2329 "asn1p_y.y" { (yyval.a_expr) = (yyvsp[(1) - (3)].a_expr); asn1p_expr_add((yyval.a_expr), (yyvsp[(3) - (3)].a_expr)); @@ -4758,7 +4757,7 @@ yyparse () break; case 317: -#line 2337 "asn1p_y.y" +#line 2336 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4769,7 +4768,7 @@ yyparse () break; case 318: -#line 2344 "asn1p_y.y" +#line 2343 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4781,7 +4780,7 @@ yyparse () break; case 319: -#line 2352 "asn1p_y.y" +#line 2351 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4793,7 +4792,7 @@ yyparse () break; case 320: -#line 2360 "asn1p_y.y" +#line 2359 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4804,7 +4803,7 @@ yyparse () break; case 321: -#line 2367 "asn1p_y.y" +#line 2366 "asn1p_y.y" { (yyval.a_expr) = NEW_EXPR(); checkmem((yyval.a_expr)); @@ -4816,7 +4815,7 @@ yyparse () break; case 322: -#line 2378 "asn1p_y.y" +#line 2377 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromint((yyvsp[(1) - (1)].a_int)); checkmem((yyval.a_value)); @@ -4824,7 +4823,7 @@ yyparse () break; case 323: -#line 2382 "asn1p_y.y" +#line 2381 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromint((yyvsp[(1) - (1)].a_int)); checkmem((yyval.a_value)); @@ -4832,7 +4831,7 @@ yyparse () break; case 324: -#line 2389 "asn1p_y.y" +#line 2388 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromdouble((yyvsp[(1) - (1)].a_dbl)); checkmem((yyval.a_value)); @@ -4840,17 +4839,17 @@ yyparse () break; case 325: -#line 2420 "asn1p_y.y" +#line 2419 "asn1p_y.y" { memset(&(yyval.a_tag), 0, sizeof((yyval.a_tag))); } break; case 326: -#line 2421 "asn1p_y.y" +#line 2420 "asn1p_y.y" { (yyval.a_tag) = (yyvsp[(1) - (1)].a_tag); } break; case 327: -#line 2425 "asn1p_y.y" +#line 2424 "asn1p_y.y" { (yyval.a_tag) = (yyvsp[(1) - (2)].a_tag); (yyval.a_tag).tag_mode = (yyvsp[(2) - (2)].a_tag).tag_mode; @@ -4858,7 +4857,7 @@ yyparse () break; case 328: -#line 2432 "asn1p_y.y" +#line 2431 "asn1p_y.y" { (yyval.a_tag) = (yyvsp[(2) - (4)].a_tag); (yyval.a_tag).tag_value = (yyvsp[(3) - (4)].a_int); @@ -4866,42 +4865,42 @@ yyparse () break; case 329: -#line 2438 "asn1p_y.y" +#line 2437 "asn1p_y.y" { (yyval.a_tag).tag_class = TC_CONTEXT_SPECIFIC; } break; case 330: -#line 2439 "asn1p_y.y" +#line 2438 "asn1p_y.y" { (yyval.a_tag).tag_class = TC_UNIVERSAL; } break; case 331: -#line 2440 "asn1p_y.y" +#line 2439 "asn1p_y.y" { (yyval.a_tag).tag_class = TC_APPLICATION; } break; case 332: -#line 2441 "asn1p_y.y" +#line 2440 "asn1p_y.y" { (yyval.a_tag).tag_class = TC_PRIVATE; } break; case 333: -#line 2445 "asn1p_y.y" +#line 2444 "asn1p_y.y" { (yyval.a_tag).tag_mode = TM_DEFAULT; } break; case 334: -#line 2446 "asn1p_y.y" +#line 2445 "asn1p_y.y" { (yyval.a_tag).tag_mode = TM_IMPLICIT; } break; case 335: -#line 2447 "asn1p_y.y" +#line 2446 "asn1p_y.y" { (yyval.a_tag).tag_mode = TM_EXPLICIT; } break; case 336: -#line 2451 "asn1p_y.y" +#line 2450 "asn1p_y.y" { checkmem((yyvsp[(1) - (1)].tv_str)); (yyval.tv_str) = (yyvsp[(1) - (1)].tv_str); @@ -4909,7 +4908,7 @@ yyparse () break; case 337: -#line 2455 "asn1p_y.y" +#line 2454 "asn1p_y.y" { checkmem((yyvsp[(1) - (1)].tv_str)); (yyval.tv_str) = (yyvsp[(1) - (1)].tv_str); @@ -4917,19 +4916,19 @@ yyparse () break; case 338: -#line 2463 "asn1p_y.y" +#line 2462 "asn1p_y.y" { (yyval.tv_str) = 0; } break; case 339: -#line 2464 "asn1p_y.y" +#line 2463 "asn1p_y.y" { (yyval.tv_str) = (yyvsp[(1) - (1)].tv_str); } break; case 340: -#line 2470 "asn1p_y.y" +#line 2469 "asn1p_y.y" { checkmem((yyvsp[(1) - (1)].tv_str)); (yyval.tv_str) = (yyvsp[(1) - (1)].tv_str); @@ -4937,7 +4936,7 @@ yyparse () break; case 341: -#line 2477 "asn1p_y.y" +#line 2476 "asn1p_y.y" { (yyval.a_ref) = asn1p_ref_new(yylineno, currentModule); asn1p_ref_add_component((yyval.a_ref), (yyvsp[(1) - (1)].tv_str), RLT_lowercase); @@ -4946,7 +4945,7 @@ yyparse () break; case 342: -#line 2484 "asn1p_y.y" +#line 2483 "asn1p_y.y" { (yyval.a_value) = asn1p_value_fromref((yyvsp[(1) - (1)].a_ref), 0); } @@ -4954,7 +4953,7 @@ yyparse () /* Line 1267 of yacc.c. */ -#line 4958 "asn1p_y.c" +#line 4957 "asn1p_y.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -5168,7 +5167,7 @@ yyparse () } -#line 2488 "asn1p_y.y" +#line 2487 "asn1p_y.y" diff --git a/libasn1parser/asn1p_y.h b/libasn1parser/asn1p_y.h index 9e5f2ce8a..8581bc80b 100644 --- a/libasn1parser/asn1p_y.h +++ b/libasn1parser/asn1p_y.h @@ -262,7 +262,7 @@ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -#line 116 "asn1p_y.y" +#line 115 "asn1p_y.y" { asn1p_t *a_grammar; asn1p_module_flags_e a_module_flags; diff --git a/libasn1parser/asn1p_y.y b/libasn1parser/asn1p_y.y index 4d209c352..0b1c9e407 100644 --- a/libasn1parser/asn1p_y.y +++ b/libasn1parser/asn1p_y.y @@ -95,15 +95,14 @@ static asn1p_module_t *currentModule; #ifdef AL_IMPORT #error AL_IMPORT DEFINED ELSEWHERE! #endif -#define AL_IMPORT(to,where,from,field) do { \ - if(!(from)) break; \ - while(TQ_FIRST(&((from)->where))) { \ - TQ_ADD(&((to)->where), \ - TQ_REMOVE(&((from)->where), field), \ - field); \ - } \ - assert(TQ_FIRST(&((from)->where)) == 0); \ - } while(0) +#define AL_IMPORT(to, where, from, field) \ + do { \ + if(!(from)) break; \ + while(TQ_FIRST(&((from)->where))) { \ + TQ_ADD(&((to)->where), TQ_REMOVE(&((from)->where), field), field); \ + } \ + assert(TQ_FIRST(&((from)->where)) == 0); \ + } while(0) %} @@ -589,7 +588,7 @@ ModuleBody: $$ = asn1p_module_new(); AL_IMPORT($$, exports, $1, xp_next); AL_IMPORT($$, imports, $2, xp_next); - AL_IMPORT($$, members, $3, next); + asn1p_module_move_members($$, $3); asn1p_module_free($1); asn1p_module_free($2); @@ -608,7 +607,7 @@ AssignmentList: $$ = $2; break; } - AL_IMPORT($$, members, $2, next); + asn1p_module_move_members($$, $2); asn1p_module_free($2); } ; @@ -623,14 +622,14 @@ Assignment: checkmem($$); assert($1->expr_type != A1TC_INVALID); assert($1->meta_type != AMT_INVALID); - TQ_ADD(&($$->members), $1, next); + asn1p_module_member_add($$, $1); } | ValueAssignment { $$ = asn1p_module_new(); checkmem($$); assert($1->expr_type != A1TC_INVALID); assert($1->meta_type != AMT_INVALID); - TQ_ADD(&($$->members), $1, next); + asn1p_module_member_add($$, $1); } /* * Value set definition @@ -644,7 +643,7 @@ Assignment: checkmem($$); assert($1->expr_type != A1TC_INVALID); assert($1->meta_type != AMT_INVALID); - TQ_ADD(&($$->members), $1, next); + asn1p_module_member_add($$, $1); } | TOK_ENCODING_CONTROL TOK_capitalreference { asn1p_lexer_hack_push_encoding_control(); } @@ -728,11 +727,11 @@ ImportsList: ImportsElement { $$ = asn1p_xports_new(); checkmem($$); - TQ_ADD(&($$->members), $1, next); + TQ_ADD(&($$->xp_members), $1, next); } | ImportsList ',' ImportsElement { $$ = $1; - TQ_ADD(&($$->members), $3, next); + TQ_ADD(&($$->xp_members), $3, next); } ; @@ -789,11 +788,11 @@ ExportsBody: ExportsElement { $$ = asn1p_xports_new(); assert($$); - TQ_ADD(&($$->members), $1, next); + TQ_ADD(&($$->xp_members), $1, next); } | ExportsBody ',' ExportsElement { $$ = $1; - TQ_ADD(&($$->members), $3, next); + TQ_ADD(&($$->xp_members), $3, next); } ; From cd8f1e03776898729cbc32a02c70c7836f748579 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Mon, 6 Nov 2017 00:13:32 -0800 Subject: [PATCH 12/41] uper_encode() with NULL callback to ignore output and return the number of bits --- skeletons/per_encoder.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/skeletons/per_encoder.c b/skeletons/per_encoder.c index 17e5fce5e..86aec4ea5 100644 --- a/skeletons/per_encoder.c +++ b/skeletons/per_encoder.c @@ -4,6 +4,14 @@ static int _uper_encode_flush_outp(asn_per_outp_t *po); +static int +ignore_output(const void *data, size_t size, void *app_key) { + (void)data; + (void)size; + (void)app_key; + return 0; +} + asn_enc_rval_t uper_encode(const asn_TYPE_descriptor_t *td, const asn_per_constraints_t *constraints, const void *sptr, @@ -20,7 +28,7 @@ uper_encode(const asn_TYPE_descriptor_t *td, po.buffer = po.tmpspace; po.nboff = 0; po.nbits = 8 * sizeof(po.tmpspace); - po.output = cb; + po.output = cb ? cb : ignore_output; po.op_key = app_key; po.flushed_bytes = 0; From 1fc5edb22d1bc5dea70e389422c5cf3e46b1d1ab Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Mon, 6 Nov 2017 01:58:49 -0800 Subject: [PATCH 13/41] asn_encode_to_new_buffer() --- skeletons/asn_application.c | 80 ++++++++++++++++++++++++++++++++++++- skeletons/asn_application.h | 22 ++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/skeletons/asn_application.c b/skeletons/asn_application.c index ee74e32fc..b8852ea65 100644 --- a/skeletons/asn_application.c +++ b/skeletons/asn_application.c @@ -42,6 +42,12 @@ struct overrun_encoder_key { size_t computed_size; }; +struct dynamic_encoder_key { + void *buffer; + size_t buffer_size; + size_t computed_size; +}; + struct callback_failure_catch_key { asn_app_consume_bytes_f *callback; void *callback_key; @@ -70,6 +76,43 @@ overrun_encoder_cb(const void *data, size_t size, void *keyp) { return 0; } +/* + * Encoder which dynamically allocates output, and continues + * to count even if allocation failed. + */ +static int +dynamic_encoder_cb(const void *data, size_t size, void *keyp) { + struct dynamic_encoder_key *key = keyp; + + if(key->buffer) { + if(key->computed_size + size >= key->buffer_size) { + void *p; + size_t new_size = key->buffer_size; + + do { + new_size *= 2; + } while(new_size <= key->computed_size + size); + + p = REALLOC(key->buffer, new_size); + if(p) { + key->buffer = p; + key->buffer_size = new_size; + } else { + FREEMEM(key->buffer); + key->buffer = 0; + key->buffer_size = 0; + key->computed_size += size; + return 0; + } + } + memcpy((char *)key->buffer + key->computed_size, data, size); + } + + key->computed_size += size; + + return 0; +} + /* * Encoder which help convert the application level encoder failure into EIO. */ @@ -134,7 +177,8 @@ asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_ctx, overrun_encoder_cb, &buf_key); if(er.encoded >= 0 && (size_t)er.encoded != buf_key.computed_size) { - ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE " yet produced %" ASN_PRI_SIZE " bytes", + ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE + " yet produced %" ASN_PRI_SIZE " bytes", er.encoded, buf_key.computed_size); assert(er.encoded < 0 || (size_t)er.encoded == buf_key.computed_size); } @@ -142,6 +186,40 @@ asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_ctx, return er; } +asn_encode_to_new_buffer_result_t +asn_encode_to_new_buffer(const asn_codec_ctx_t *opt_codec_ctx, + enum asn_transfer_syntax syntax, + const asn_TYPE_descriptor_t *td, const void *sptr) { + struct dynamic_encoder_key buf_key; + asn_encode_to_new_buffer_result_t res; + + buf_key.buffer_size = 16; + buf_key.buffer = MALLOC(buf_key.buffer_size); + buf_key.computed_size = 0; + + res.result = asn_encode_internal(opt_codec_ctx, syntax, td, sptr, + dynamic_encoder_cb, &buf_key); + + if(res.result.encoded >= 0 + && (size_t)res.result.encoded != buf_key.computed_size) { + ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE + " yet produced %" ASN_PRI_SIZE " bytes", + er.encoded, buf_key.computed_size); + assert(res.result.encoded < 0 + || (size_t)res.result.encoded == buf_key.computed_size); + } + + res.buffer = buf_key.buffer; + + /* 0-terminate just in case. */ + if(res.buffer) { + assert(buf_key.computed_size < buf_key.buffer_size); + ((char *)res.buffer)[buf_key.computed_size] = '\0'; + } + + return res; +} + static asn_enc_rval_t asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx, enum asn_transfer_syntax syntax, diff --git a/skeletons/asn_application.h b/skeletons/asn_application.h index a125562c3..acc91ab7f 100644 --- a/skeletons/asn_application.h +++ b/skeletons/asn_application.h @@ -81,6 +81,28 @@ asn_enc_rval_t asn_encode_to_buffer( const struct asn_TYPE_descriptor_s *type_to_encode, const void *structure_to_encode, void *buffer, size_t buffer_size); +/* + * A variant of asn_encode_to_buffer() with automatically allocated buffer. + * RETURN VALUES: + * On success, returns a newly allocated (.buffer) containing the whole message. + * The message size is returned in (.result.encoded). + * On failure: + * (.buffer) is NULL, + * (.result.encoded) as in asn_encode_to_buffer(), + * The errno codes as in asn_encode_to_buffer(), plus the following: + * ENOMEM: Memory allocation failed due to system or internal limits. + * The user is responsible for freeing the (.buffer). + */ +typedef struct asn_encode_to_new_buffer_result_s { + void *buffer; /* NULL if failed to encode. */ + asn_enc_rval_t result; +} asn_encode_to_new_buffer_result_t; +asn_encode_to_new_buffer_result_t asn_encode_to_new_buffer( + const asn_codec_ctx_t *opt_codec_parameters, /* See asn_codecs.h */ + enum asn_transfer_syntax, + const struct asn_TYPE_descriptor_s *type_to_encode, + const void *structure_to_encode); + /* * Generic type of an application-defined callback to return various From 08661a6508d87d775167d24058d4b6faa957f410 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Mon, 6 Nov 2017 02:08:47 -0800 Subject: [PATCH 14/41] use ptrdiff_t --- libasn1common/genhash.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libasn1common/genhash.c b/libasn1common/genhash.c index 275e23e23..5a6d3e41b 100644 --- a/libasn1common/genhash.c +++ b/libasn1common/genhash.c @@ -58,6 +58,7 @@ #include #include #include +#include #include #include "genhash.h" @@ -767,7 +768,7 @@ genhash_empty(genhash_t *h, int freekeys, int freevalues) { unsigned int hashf_int (const void *key) { - return (*(const int *)key ^ (*(const int *)key >> 16)); + return (*(const ptrdiff_t *)key ^ (*(const ptrdiff_t *)key >> 16)); } int @@ -777,7 +778,7 @@ cmpf_int (const void *key1, const void *key2) { unsigned int hashf_void (const void *key) { - return ((int)key ^ ((int)key >> 16)); + return ((ptrdiff_t)key ^ ((ptrdiff_t)key >> 16)); } int From f3334585a7d9d932c3c1ea8e2217ff4e348fd85b Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Tue, 7 Nov 2017 00:02:24 -0800 Subject: [PATCH 15/41] update doc --- doc/docsrc/asn1c-usage.tex | 195 +++++++++++++++++++++++-------------- 1 file changed, 120 insertions(+), 75 deletions(-) diff --git a/doc/docsrc/asn1c-usage.tex b/doc/docsrc/asn1c-usage.tex index c1d5b7324..846d5da66 100644 --- a/doc/docsrc/asn1c-usage.tex +++ b/doc/docsrc/asn1c-usage.tex @@ -72,7 +72,9 @@ \lstnewenvironment{codesample}[1][]{\lstset{style=listingStyle,language=C,#1}}{} \lstnewenvironment{bash}[1][]{\lstset{style=listingStyle,language=bash,#1}}{} \lstnewenvironment{asn}[1][]{\lstset{style=listingStyle,language=asn1,#1}}{} -\def\code{lstinline} + +\newcommand{\code}[1]{\lstinline{#1}} +\newcommand{\cmd}[1]{\texttt{#1}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands. \usepackage{extramarks} @@ -124,13 +126,13 @@ \chapter{Introduction to the ASN.1 Compiler} language structures (C structs, unions, enums) describing the corresponding ASN.1 types. The compiler also creates the code which allows automatic serialization and deserialization of these structures using several -standardized encoding rules (BER, DER, XER, PER). +standardized encoding rules (BER, DER, OER, PER, XER). -For example, suppose the following ASN.1 module is given% +Let's take the following ASN.1 example% \footnote{Part \ref{par:ASN.1-Basics} provides a quick reference on the ASN.1 notation.}: \begin{asn} -RectangleTest DEFINITIONS ::= BEGIN +RectangleModule DEFINITIONS ::= BEGIN Rectangle ::= SEQUENCE { height INTEGER, -- Height of the rectangle @@ -139,7 +141,7 @@ \chapter{Introduction to the ASN.1 Compiler} END \end{asn} -The compiler would read this ASN.1 definition and produce the following +The asn1c compiler reads this ASN.1 definition and produce the following C type: \begin{codesample} typedef struct Rectangle_s { @@ -147,26 +149,26 @@ \chapter{Introduction to the ASN.1 Compiler} long width; } Rectangle_t; \end{codesample} -It would also create the code for converting this structure into platform-independent -wire representation (a serializer API) and the decoder of such wire -representation back into local, machine-specific type (a deserializer -API). - +The asn1c compiler also creates the code for converting this structure into +platform-independent wire representation and the decoder +of such wire representation back into local, machine-specific type. +These encoders and decoders are also called serializers and deserializers, +marshallers and unmarshallers, or codecs. \section{Quick start with asn1c} -After building and installing the compiler, the \emph{asn1c} -command may be used to compile the ASN.1 modules% +After building and installing the compiler, the \cmd{asn1c} +may be used to compile the ASN.1 modules% \footnote{This is probably \textbf{not} what you want to try out right now. Read through the rest of this chapter and check the Section~\ref{sec:Command-line-options} to find out about \textbf{-P} and \textbf{-R} options.% }: \begin{bash} -asn1c %\emph{}% +asn1c %\emph{}% \end{bash} If several ASN.1 modules contain interdependencies, all of the files must be specified altogether: \begin{bash} -asn1c %\emph{ ...}% +asn1c %\emph{ ...}% \end{bash} The compiler \textbf{-E} and \textbf{-EF} options are used for testing the parser and the semantic fixer, respectively. These options will @@ -175,7 +177,7 @@ \section{Quick start with asn1c} by the compiler. It might be useful to check whether a particular syntactic construct is properly supported by the compiler. \begin{bash} -asn1c %\textbf{-EF} \emph{}% +asn1c %\textbf{-EF} \emph{}% \end{bash} The \textbf{-P} option is used to dump the compiled output on the screen instead of creating a bunch of .c and .h files on disk in the @@ -187,36 +189,40 @@ \section{Quick start with asn1c} Print the compiled output instead of creating multiple source files: \begin{bash} -asn1c %\textbf{-P} \emph{}% +asn1c %\textbf{-P} \emph{}% \end{bash} \clearpage{} -\section{Recognizing compiler output} +\section{Understanding compiler output} -The asn1c compiler produces a number of files: +The \cmd{asn1c} compiler produces a number of files: \begin{itemize} \item A set of .c and .h files for each type defined in the ASN.1 specification. These files will be named similarly to -the ASN.1 types (\emph{Rectangle.c} and \emph{Rectangle.h} for the -RectangleTest ASN.1 module defined in the beginning of this document). +the ASN.1 types (\textbf{Rectangle.c} and \textbf{Rectangle.h} for the +RectangleModule ASN.1 module defined in the beginning of this document). \item A set of helper .c and .h files which contain the generic encoders, -decoders and other useful routines. There will be quite a few of them, some +decoders and other useful routines. +Sometimes they are referred to by the term \emph{skeletons}. +There will be quite a few of them, some of them are not even always necessary, but the overall amount of code after compilation will be rather small anyway. -\item A \emph{converter-example.c} file containing the \emph{int main()} function with a fully functioning decoder. It can convert a given PDU between BER, XER and possibly OER and PER (if -gen-OER or -gen-PER options to asn1c were in effect). At some point you will want to replace this file with your own file containing the \emph{int main()} function. -\item A \emph{Makefile.am.libasncodecs} file mentioning all the files created -at the earlier steps. The accompanying \emph{Makefile.am.example} file is -suitable for either automake suite or the plain `make` utility. -Just rename it into \emph{Makefile}. +\item A \textbf{Makefile.am.libasncodecs} file which explicitly lists all the +generated files. +This makefile can be used on its own to build the just the codec library. +\item A \textbf{converter-example.c} file containing the \emph{int main()} function with a fully functioning encoder and data format converter. It can convert a given PDU between BER, XER and possibly OER and PER (if \cmd{-gen-OER} or \cmd{-gen-PER} options to \cmd{asn1c} were in effect). At some point you will want to replace this file with your own file containing the \emph{int main()} function. +\item A \textbf{Makefile.am.example} file which binds together +\textbf{Makefile.am.libasncodecs} and \textbf{converter-example.c} +to build a versatile converter and debugger for your data formats. \end{itemize} It is possible to compile everything with just a couple of instructions: \begin{bash} -asn1c -pdu=%\emph{Rectangle}% *.asn1 -make -f Makefile.am.example # If you use `make` +asn1c -pdu=%\emph{Rectangle}% *.asn +make -f Makefile.am.example # If you use `make` \end{bash} or \begin{bash} -asn1c *.asn1 +asn1c *.asn cc -I. -DPDU=%\emph{Rectangle}% -o rectangle.exe *.c # ... or like this \end{bash} Refer to the Chapter \ref{cha:Step-by-step-examples} for a sample @@ -226,7 +232,7 @@ \section{Recognizing compiler output} \clearpage{} \section{\label{sec:Command-line-options}Command line options} -The following table summarizes the asn1c command line options. +The following table summarizes the \cmd{asn1c} command line options. \renewcommand{\arraystretch}{1.33} \begin{longtable}{lp{4in}} @@ -278,7 +284,8 @@ \section{\label{sec:Command-line-options}Command line options} In case of \texttt{-pdu=\textbf{all}}, all ASN.1 types defined in all modules wil form a PDU table. In case of \texttt{-pdu=\textbf{auto}}, all types not referenced by any other type will form a PDU table. If \texttt{\emph{Type}} is an ASN.1 type identifier, it is added to a PDU table. The last form may be specified multiple times.}\\ \\ \textbf{Output Options} & \textbf{Description}\\ \midrule -{\ttfamily -print-constraints} & {\small When \texttt{-EF} are also specified, this option forces the compiler +{\ttfamily -print-class-matrix} & {\small When \texttt{-EF} options are given, this option instructs the compiler to print out the collected Information Object Class matrix.}\\ +{\ttfamily -print-constraints} & {\small With \texttt{-EF}, this option instructs the compiler to explain its internal understanding of subtype constraints.}\\ {\ttfamily -print-lines} & {\small Generate \texttt{``-{}- \#line''} comments in \texttt{-E} output.}\\ @@ -289,28 +296,27 @@ \section{\label{sec:Command-line-options}Command line options} \chapter{Using the ASN.1 Compiler} -\section[Invoking the helper code]{Invoking the ASN.1 helper code} +\section[Invoking the codec API]{Invoking the generated ASN.1 codec API} -First of all, you should include one or more header files into your -application. Typically, it is enough to include the header file of -the main PDU type. For our Rectangle module, including the Rectangle.h -file is sufficient: +Let's start with including the necessary header files into your +application. Normally it is enough to include the header file of +the main PDU type. For our \emph{Rectangle} module, including the \emph{Rectangle.h} file is sufficient: \begin{codesample} #include \end{codesample} -The header files defines the C structure corresponding to the ASN.1 -definition of a rectangle and the declaration of the ASN.1 type descriptor, -which is used as an argument to most of the functions provided by -the ASN.1 module. For example, here is the code which frees the Rectangle\_t -structure: +The header files defines a C structure corresponding to the ASN.1 +definition of a rectangle and the declaration of the ASN.1 +\emph{type descriptor}. A type descriptor is a special globally accessible +object which is used as an argument to most of the API functions provided by +the ASN.1 codec. A type descriptor starts with \emph{asn\_DEF\_\ldots{}}. For example, here is the code which frees the Rectangle\_t structure: \begin{codesample} Rectangle_t *rect = ...; -ASN_STRUCT_FREE(asn_DEF_Rectangle, rect); +ASN_STRUCT_FREE(%\textbf{asn\_DEF\_}%Rectangle, rect); \end{codesample} This code defines a \emph{rect} pointer which points to the Rectangle\_t -structure which needs to be freed. The second line uses the generic -ASN\_STRUCT\_FREE() macro which invokes the memory deallocation routine +structure which needs to be freed. The second line uses a generic +\code{ASN\_STRUCT\_FREE()} macro which invokes the memory deallocation routine created specifically for this Rectangle\_t structure. The \emph{asn\_DEF\_Rectangle} is the type descriptor which holds a collection of routines and operations defined for the Rectangle\_t structure. @@ -354,14 +360,14 @@ \chapter{Using the ASN.1 Compiler} structure. See Section~\ref{sub:Freeing-the-target}. \end{description} Each of the above function takes the type descriptor (\emph{asn\_DEF\_\ldots{}}) -and the target structure (\emph{rect}, in the above example). +and the target structure (\emph{rect}, as in the example above). \subsection{\label{sub:Generic-Encoding}Generic encoders and decoders} Before we start describing specific encoders and decoders, let's step back a little and check out a simple high level way. -The asn1c runtime supplies (see asn\_application.h) two sets of high level functions, \emph{asn\_encode*} and \emph{asn\_decode*}, which take a transfer syntax selector as the argument. The transfer syntax selector is defined as this: +The asn1c runtime supplies (see \emph{asn\_application.h}) two sets of high level functions, \emph{asn\_encode*} and \emph{asn\_decode*}, which take a transfer syntax selector as the argument. The transfer syntax selector is defined as this: \begin{codesample}[basicstyle=\scriptsize\listingfont] /* @@ -391,12 +397,11 @@ \subsection{\label{sub:Generic-Encoding}Generic encoders and decoders} size_t buf_size = sizeof(buffer); asn_enc_rval_t er; -er = %\textbf{asn\_encode\emph{\_to\_buffer}}%(0, %\textbf{ATS\_BER}%, &asn_DEF_Rectangle, buffer, buf_size); +er = %\textbf{asn\_encode\emph{\_to\_buffer}}%(0, %\textbf{ATS\_DER}%, &asn_DEF_Rectangle, buffer, buf_size); if(er.encoded > buf_size) { fprintf(stderr, "Buffer of size %\%%zu is too small for %\%%s, need %\%%zu\n", buf_size, asn_DEF_Rectangle.name, er.encoded); - ASN_STRUCT_FREE(asn_DEF_Rectangle, rect); } \end{codesample} @@ -542,8 +547,8 @@ \subsection{\label{sub:Encoding-DER}Encoding DER} } } \end{codesample} -As you see, the DER encoder does not write into some sort of buffer -or something. It just invokes the custom function (possible, multiple +As you see, the DER encoder does not write into some sort of buffer. +It just invokes the custom function (possible, multiple times) which would save the data into appropriate storage. The optional argument \emph{app\_key} is opaque for the DER encoder code and just used by \emph{\_write\_stream()} as the pointer to the appropriate @@ -675,8 +680,12 @@ \subsection{\label{sub:Freeing-the-target}Freeing the target structure} Freeing the structure is slightly more complex than it may seem to. When the ASN.1 structure is freed, all the members of the structure -and their submembers are recursively freed as well. But it might not -be feasible to free the structure itself. Consider the following case: +and their submembers are recursively freed as well. +The ASN\_STRUCT\_FREE() macro helps with that. + +But it might not always be feasible to free the whole structure. +In the following example, the application programmer defines a custom +structure with one ASN.1-derived member (rect). \begin{codesample} struct my_figure { /* The custom structure */ int flags; /* */ @@ -685,17 +694,16 @@ \subsection{\label{sub:Freeing-the-target}Freeing the target structure} /* other members of the structure */ }; \end{codesample} -In this example, the application programmer defines a custom structure -with one ASN.1-derived member (rect). This member is not a reference -to the Rectangle\_t, but an in-place inclusion of the Rectangle\_t -structure. If the freeing is necessary, the usual procedure of freeing -everything must not be applied to the \&rect pointer itself, because -it does not point to the memory block directly allocated by the memory -allocation routine, but instead lies within a block allocated for +This member is not a reference to the Rectangle\_t, but an in-place inclusion +of the Rectangle\_t structure. +If there's a need to free the \code{rect} member, the usual procedure of +freeing everything must not be applied to the \code{\&rect} pointer itself, +because it does not point to the beginning of memory block allocated by +the memory allocation routine, but instead lies within a block allocated for the my\_figure structure. -To solve this problem, in addition to ASN\_STRUCT\_FREE macro, the asn1c -skeletons define the ASN\_STRUCT\_RESET macro which doesn't free the passed +To solve this problem, in addition to ASN\_STRUCT\_FREE() macro, the asn1c +skeletons define the ASN\_STRUCT\_RESET() macro which doesn't free the passed pointer and instead resets the structure into the clean and safe state. \begin{codesample} /* %\textbf{1. Rectangle\_t is defined within my\_figure}% */ @@ -721,16 +729,53 @@ \subsection{\label{sub:Freeing-the-target}Freeing the target structure} \chapter{\label{cha:Step-by-step-examples}Step by step examples} +\section{A “Rectangle” converter and debugger} + +One of the most common need is to create some sort of analysis tool +for the existing ASN.1 data files. Let's build a converter for existing +Rectangle binary files between BER, OER, PER, and XER (XML). + +\begin{enumerate} +\item Create a file named \textbf{rectangle.asn} with the following contents: +\begin{asn} +RectangleModule DEFINITIONS ::= BEGIN + +Rectangle ::= SEQUENCE { + height INTEGER, + width INTEGER +} + +END +\end{asn} + +\item Compile it into the set of .c and .h files using \cmd{asn1c} compiler: + +\begin{bash} +asn1c -pdu=%\textbf{Rectangle}% -gen-OER -gen-PER %\textbf{rectangle.asn}% +\end{bash} + +\item Create the converter and dumper: + +\begin{bash} +make -f Makefile.am.example +\end{bash} + +\item Done. The binary file converter is ready: + +\begin{bash} +./converter-example -h +\end{bash} +\end{enumerate} -\section{A ``Rectangle'' Encoder} +\section{A “Rectangle” Encoder} This example will help you create a simple BER and XER encoder of a ``Rectangle'' type used throughout this document. \begin{enumerate} -\item Create a file named \textbf{rectangle.asn1} with the following contents: +\item Create a file named \textbf{rectangle.asn} with the following contents: \begin{asn} -RectangleModule1 DEFINITIONS ::= BEGIN +RectangleModule DEFINITIONS ::= BEGIN Rectangle ::= SEQUENCE { height INTEGER, @@ -742,10 +787,10 @@ \section{A ``Rectangle'' Encoder} \item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}: \begin{bash} -asn1c %\textbf{rectangle.asn1}% +asn1c %\textbf{rectangle.asn}% \end{bash} \item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading -the \textbf{rectangle.asn1} file into the Web form and unpacking the +the \textbf{rectangle.asn} file into the Web form and unpacking the produced archive on your computer. \item By this time, you should have gotten multiple files in the current directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}. @@ -815,19 +860,19 @@ \section{A ``Rectangle'' Encoder} \begin{bash} cc -I. -o %\textbf{\emph{rencode}} \emph{*.c}% \end{bash} -\item Voila! You have just created the BER and XER encoder of a Rectangle +\item Done. You have just created the BER and XER encoder of a Rectangle type, named \textbf{rencode}! \end{enumerate} -\section{\label{sec:A-Rectangle-Decoder}A ``Rectangle'' Decoder} +\section{\label{sec:A-Rectangle-Decoder}A “Rectangle” Decoder} This example will help you to create a simple BER decoder of a simple ``Rectangle'' type used throughout this document. \begin{enumerate} -\item Create a file named \textbf{rectangle.asn1} with the following contents: +\item Create a file named \textbf{rectangle.asn} with the following contents: \begin{asn} -RectangleModule1 DEFINITIONS ::= BEGIN +RectangleModule DEFINITIONS ::= BEGIN Rectangle ::= SEQUENCE { height INTEGER, @@ -839,10 +884,10 @@ \section{\label{sec:A-Rectangle-Decoder}A ``Rectangle'' Decoder} \item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}: \begin{bash} -asn1c %\textbf{rectangle.asn1}% +asn1c %\textbf{rectangle.asn}% \end{bash} \item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading -the \textbf{rectangle.asn1} file into the Web form and unpacking the +the \textbf{rectangle.asn} file into the Web form and unpacking the produced archive on your computer. \item By this time, you should have gotten multiple files in the current directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}. @@ -904,7 +949,7 @@ \section{\label{sec:A-Rectangle-Decoder}A ``Rectangle'' Decoder} \begin{bash} cc -I. -o %\textbf{\emph{rdecode}} \emph{*.c}% \end{bash} -\item Voila! You have just created the BER decoder of a Rectangle type, +\item Done. You have just created the BER decoder of a Rectangle type, named \textbf{rdecode}! \end{enumerate} @@ -919,7 +964,7 @@ \section{Adding constraints into ``Rectangle'' type} This example shows how to add basic constraints to the ASN.1 specification and how to invoke the constraints validation code in your application. \begin{enumerate} -\item Create a file named \textbf{rectangle.asn1} with the following contents: +\item Create a file named \textbf{rectangle.asn} with the following contents: \begin{asn} RectangleModuleWithConstraints DEFINITIONS ::= BEGIN @@ -954,7 +999,7 @@ \section{Adding constraints into ``Rectangle'' type} /* assert(errlen < sizeof(errbuf)); // you may rely on that */ if(ret) { fprintf(stderr, "Constraint validation failed: %\%%s\n", - errbuf /* errbuf is properly nul-terminated */ + errbuf /* errbuf is properly null-terminated */ ); /* exit(...); // Replace with appropriate action */ } From d5627a1f11dfe0a391f462ab2d5f8fd65b8c76ef Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Tue, 7 Nov 2017 01:04:40 -0800 Subject: [PATCH 16/41] more logical structure --- doc/docsrc/asn1c-usage.tex | 1484 ++++++++++++++++++------------------ 1 file changed, 722 insertions(+), 762 deletions(-) diff --git a/doc/docsrc/asn1c-usage.tex b/doc/docsrc/asn1c-usage.tex index 846d5da66..ed93bce5d 100644 --- a/doc/docsrc/asn1c-usage.tex +++ b/doc/docsrc/asn1c-usage.tex @@ -13,9 +13,9 @@ \setmonofont{Consolas} \usepackage{fancyhdr} +\usepackage{fancyref} \usepackage{longtable} \usepackage{booktabs} -\usepackage{varioref} \usepackage{url} \usepackage{xcolor} \usepackage{listings} @@ -64,7 +64,7 @@ flexiblecolumns=false } \lstdefinelanguage{asn1}{ - morekeywords={DEFINITIONS,BEGIN,END,SEQUENCE,SET,OF,CHOICE,OPTIONAL}, + morekeywords={DEFINITIONS,BEGIN,END,AUTOMATIC,TAGS,SEQUENCE,SET,OF,CHOICE,OPTIONAL,INTEGER,MAX}, morecomment=[l]{--}, morecomment=[n]{/*}{*/} } @@ -112,913 +112,873 @@ \tableofcontents{} -\part{Using the ASN.1 Compiler} +\chapter{\label{chap:Quick-start-examples}Quick start examples} +\section{A “Rectangle” converter and debugger} -\chapter{Introduction to the ASN.1 Compiler} - -The purpose of the ASN.1 compiler is to convert the specifications -in ASN.1 notation into some other language. At this moment, only C -and C++ target languages are supported, the latter is in upward compatibility -mode. - -The compiler reads the specification and emits a series of target -language structures (C structs, unions, enums) describing the corresponding -ASN.1 types. The compiler also creates the code which allows automatic -serialization and deserialization of these structures using several -standardized encoding rules (BER, DER, OER, PER, XER). +One of the most common need is to create some sort of analysis tool +for the existing ASN.1 data files. Let's build a converter for existing +Rectangle binary files between BER, OER, PER, and XER (XML). -Let's take the following ASN.1 example% -\footnote{Part \ref{par:ASN.1-Basics} provides a quick reference -on the ASN.1 notation.}: +\begin{enumerate} +\item Create a file named \textbf{rectangle.asn} with the following contents: \begin{asn} RectangleModule DEFINITIONS ::= BEGIN Rectangle ::= SEQUENCE { - height INTEGER, -- Height of the rectangle - width INTEGER -- Width of the rectangle + height INTEGER, + width INTEGER } END \end{asn} -The asn1c compiler reads this ASN.1 definition and produce the following -C type: -\begin{codesample} -typedef struct Rectangle_s { - long height; - long width; -} Rectangle_t; -\end{codesample} -The asn1c compiler also creates the code for converting this structure into -platform-independent wire representation and the decoder -of such wire representation back into local, machine-specific type. -These encoders and decoders are also called serializers and deserializers, -marshallers and unmarshallers, or codecs. -\section{Quick start with asn1c} +\item Compile it into the set of .c and .h files using \cmd{asn1c} compiler: -After building and installing the compiler, the \cmd{asn1c} -may be used to compile the ASN.1 modules% -\footnote{This is probably \textbf{not} what you want to try out right now. Read through the rest of this chapter and check the Section~\ref{sec:Command-line-options} -to find out about \textbf{-P} and \textbf{-R} options.% -}: -\begin{bash} -asn1c %\emph{}% -\end{bash} -If several ASN.1 modules contain interdependencies, all of the files -must be specified altogether: -\begin{bash} -asn1c %\emph{ ...}% -\end{bash} -The compiler \textbf{-E} and \textbf{-EF} options are used for testing -the parser and the semantic fixer, respectively. These options will -instruct the compiler to dump out the parsed (and fixed, if \textbf{-F} -is involved) ASN.1 specification as it was understood -by the compiler. It might be useful to check whether a particular -syntactic construct is properly supported by the compiler. \begin{bash} -asn1c %\textbf{-EF} \emph{}% +asn1c -pdu=%\textbf{Rectangle}% -gen-OER -gen-PER %\textbf{rectangle.asn}% \end{bash} -The \textbf{-P} option is used to dump the compiled output on the -screen instead of creating a bunch of .c and .h files on disk in the -current directory. You would probably want to start with \textbf{-P} -option instead of creating a mess in your current directory. Another -option, \textbf{-R}, asks compiler to only generate the files which -need to be generated, and supress linking in the numerous support -files. -Print the compiled output instead of creating multiple source files: +\item Create the converter and dumper: + \begin{bash} -asn1c %\textbf{-P} \emph{}% +make -f Makefile.am.example \end{bash} -\clearpage{} -\section{Understanding compiler output} +\item Done. The binary file converter is ready: -The \cmd{asn1c} compiler produces a number of files: -\begin{itemize} -\item A set of .c and .h files for each type defined -in the ASN.1 specification. These files will be named similarly to -the ASN.1 types (\textbf{Rectangle.c} and \textbf{Rectangle.h} for the -RectangleModule ASN.1 module defined in the beginning of this document). -\item A set of helper .c and .h files which contain the generic encoders, -decoders and other useful routines. -Sometimes they are referred to by the term \emph{skeletons}. -There will be quite a few of them, some -of them are not even always necessary, but the overall amount of code -after compilation will be rather small anyway. -\item A \textbf{Makefile.am.libasncodecs} file which explicitly lists all the -generated files. -This makefile can be used on its own to build the just the codec library. -\item A \textbf{converter-example.c} file containing the \emph{int main()} function with a fully functioning encoder and data format converter. It can convert a given PDU between BER, XER and possibly OER and PER (if \cmd{-gen-OER} or \cmd{-gen-PER} options to \cmd{asn1c} were in effect). At some point you will want to replace this file with your own file containing the \emph{int main()} function. -\item A \textbf{Makefile.am.example} file which binds together -\textbf{Makefile.am.libasncodecs} and \textbf{converter-example.c} -to build a versatile converter and debugger for your data formats. -\end{itemize} -It is possible to compile everything with just a couple of instructions: -\begin{bash} -asn1c -pdu=%\emph{Rectangle}% *.asn -make -f Makefile.am.example # If you use `make` -\end{bash} -or \begin{bash} -asn1c *.asn -cc -I. -DPDU=%\emph{Rectangle}% -o rectangle.exe *.c # ... or like this +./converter-example -h \end{bash} -Refer to the Chapter \ref{cha:Step-by-step-examples} for a sample -\emph{int main()} function if you want some custom logic and not satisfied -with the supplied \emph{converter-example.c}. +\end{enumerate} -\clearpage{} -\section{\label{sec:Command-line-options}Command line options} +\section{A “Rectangle” Encoder} -The following table summarizes the \cmd{asn1c} command line options. +This example will help you create a simple BER and XER encoder of +a ``Rectangle'' type used throughout this document. +\begin{enumerate} +\item Create a file named \textbf{rectangle.asn} with the following contents: -\renewcommand{\arraystretch}{1.33} -\begin{longtable}{lp{4in}} -\textbf{Stage Selection Options} & \textbf{Description}\\ -\midrule -{\ttfamily -E} & {\small Stop after the parsing stage and print the reconstructed ASN.1 -specification code to the standard output.}\\ -{\ttfamily -F} & {\small Used together with \texttt{-E}, instructs the compiler to stop after -the ASN.1 syntax tree fixing stage and dump the reconstructed ASN.1 -specification to the standard output.}\\ -{\ttfamily -P} & {\small Dump the compiled output to the standard output instead of -creating the target language files on disk.}\\ -{\ttfamily -R} & {\small Restrict the compiler to generate only the ASN.1 tables, omitting the usual support code.}\\ -{\ttfamily -S~\emph{}} & {\small Use the specified directory with ASN.1 skeleton files.}\\ -{\ttfamily -X} & {\small Generate the XML DTD for the specified ASN.1 modules.}\\\\ -\textbf{Warning Options} & \textbf{Description}\\ -\midrule -{\ttfamily -Werror} & {\small Treat warnings as errors; abort if any warning is produced.}\\ -{\ttfamily -Wdebug-parser} & {\small Enable the parser debugging during the ASN.1 parsing stage.}\\ -{\ttfamily -Wdebug-lexer} & {\small Enable the lexer debugging during the ASN.1 parsing stage.}\\ -{\ttfamily -Wdebug-fixer} & {\small Enable the ASN.1 syntax tree fixer debugging during the fixing stage.}\\ -{\ttfamily -Wdebug-compiler} & {\small Enable debugging during the actual compile time.}\\ \\ -\textbf{Language Options} & \textbf{Description}\\ -\midrule -{\ttfamily -fbless-SIZE} & {\small Allow SIZE() constraint for INTEGER, ENUMERATED, and other types for which this constraint is normally prohibited by the standard. -This is a violation of an ASN.1 standard and compiler may fail to produce the meaningful code.}\\ -{\ttfamily -fcompound-names} & {\small Use complex names for C structures. Using complex names prevents -name clashes in case the module reuses the same identifiers in multiple -contexts.}\\ -{\ttfamily -findirect-choice} & {\small When generating code for a CHOICE type, compile the CHOICE -members as indirect pointers instead of declaring them inline. Consider -using this option together with \texttt{-fno-include-deps} -to prevent circular references.}\\ -{\ttfamily -fincludes-quoted} & {\small Generate \#include lines in "double" instead of quotes.}\\ -{\ttfamily -fknown-extern-type=\emph{}} & {\small Pretend the specified type is known. The compiler will assume -the target language source files for the given type have been provided -manually. }\\ -{\ttfamily -fline-refs} & {\small Include ASN.1 module's line numbers in generated code comments.}\\ -{\ttfamily -fno-constraints} & {\small Do not generate ASN.1 subtype constraint checking code. This -may produce a shorter executable.}\\ -{\ttfamily -fno-include-deps} & {\small Do not generate courtesy \#include lines for non-critical dependencies.}\\ -{\ttfamily -funnamed-unions} & {\small Enable unnamed unions in the definitions of target language's structures.}\\ -{\ttfamily -fwide-types} & {\small Use the wide integer types (INTEGER\_t, REAL\_t) instead of machine's native data types (long, double). }\\\\ -\textbf{Codecs Generation Options} & \textbf{Description}\\ -\midrule -{\ttfamily -gen-OER} & {\small Generate the Octet Encoding Rules (OER) support code.}\\ -{\ttfamily -gen-PER} & {\small Generate the Packed Encoding Rules (PER) support code.}\\ -{\ttfamily -pdu=\{\textbf{all}|\textbf{auto}|\emph{Type}\}} & {\small Create a PDU table for specified types, or discover the Protocol Data Units automatically. -In case of \texttt{-pdu=\textbf{all}}, all ASN.1 types defined in all modules wil form a PDU table. In case of \texttt{-pdu=\textbf{auto}}, all types not referenced by any other type will form a PDU table. If \texttt{\emph{Type}} is an ASN.1 type identifier, it is added to a PDU table. The last form may be specified multiple times.}\\ \\ -\textbf{Output Options} & \textbf{Description}\\ -\midrule -{\ttfamily -print-class-matrix} & {\small When \texttt{-EF} options are given, this option instructs the compiler to print out the collected Information Object Class matrix.}\\ -{\ttfamily -print-constraints} & {\small With \texttt{-EF}, this option instructs the compiler -to explain its internal understanding of subtype constraints.}\\ -{\ttfamily -print-lines} & {\small Generate \texttt{``-{}- \#line''} comments -in \texttt{-E} output.}\\ -\end{longtable} -\renewcommand{\arraystretch}{1} +\begin{asn} +RectangleModule DEFINITIONS ::= BEGIN +Rectangle ::= SEQUENCE { + height INTEGER, + width INTEGER +} -\chapter{Using the ASN.1 Compiler} +END +\end{asn} +\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}: +\begin{bash} +asn1c %\textbf{rectangle.asn}% +\end{bash} +\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading +the \textbf{rectangle.asn} file into the Web form and unpacking the +produced archive on your computer. +\item By this time, you should have gotten multiple files in the current +directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}. +\item Create a main() routine which creates the Rectangle\_t structure in +memory and encodes it using BER and XER encoding rules. Let's name +the file \textbf{main.c}: -\section[Invoking the codec API]{Invoking the generated ASN.1 codec API} +\begin{codesample}[basicstyle=\scriptsize\listingfont] +#include +#include +#include /* Rectangle ASN.1 type */ -Let's start with including the necessary header files into your -application. Normally it is enough to include the header file of -the main PDU type. For our \emph{Rectangle} module, including the \emph{Rectangle.h} file is sufficient: -\begin{codesample} -#include -\end{codesample} -The header files defines a C structure corresponding to the ASN.1 -definition of a rectangle and the declaration of the ASN.1 -\emph{type descriptor}. A type descriptor is a special globally accessible -object which is used as an argument to most of the API functions provided by -the ASN.1 codec. A type descriptor starts with \emph{asn\_DEF\_\ldots{}}. For example, here is the code which frees the Rectangle\_t structure: -\begin{codesample} -Rectangle_t *rect = ...; +/* Write the encoded output into some FILE stream. */ +static int write_out(const void *buffer, size_t size, void *app_key) { + FILE *out_fp = app_key; + size_t wrote = fwrite(buffer, 1, size, out_fp); + return (wrote == size) ? 0 : -1; +} + +int main(int ac, char **av) { + Rectangle_t *rectangle; /* Type to encode */ + asn_enc_rval_t ec; /* Encoder return value */ -ASN_STRUCT_FREE(%\textbf{asn\_DEF\_}%Rectangle, rect); -\end{codesample} -This code defines a \emph{rect} pointer which points to the Rectangle\_t -structure which needs to be freed. The second line uses a generic -\code{ASN\_STRUCT\_FREE()} macro which invokes the memory deallocation routine -created specifically for this Rectangle\_t structure. -The \emph{asn\_DEF\_Rectangle} is the type descriptor which holds -a collection of routines and operations defined for the Rectangle\_t structure. + /* Allocate the Rectangle_t */ + rectangle = calloc(1, sizeof(Rectangle_t)); /* not malloc! */ + if(!rectangle) { + perror("calloc() failed"); + exit(1); + } -The following member functions of the asn\_DEF\_Rectangle type descriptor -are of interest: -\begin{description} -\item [{ber\_decoder}] This is the generic \emph{restartable}% -\footnote{Restartability mean that if the decoder encounters the end of the buffer it may be invoked again with the rest of the -buffer to continue decoding.} -BER decoder (Basic Encoding Rules). This decoder would create and/or -fill the target structure for you. See Section~\ref{sub:Decoding-BER}. -\item [{der\_encoder}] This is the generic DER encoder (Distinguished Encoding -Rules). This encoder will take the target structure and encode it -into a series of bytes. See Section~\ref{sub:Encoding-DER}. NOTE: -DER encoding is a subset of BER. Any BER decoder should be able to -handle any DER input. -\item [{oer\_decoder}] This is the OER (Octet Encoding Rules) decoder. -\item [{oer\_encoder}] This is the Canonical OER encoder. This encoder -will take the target structure and encode it into a series of bytes compatible -with all BASIC-OER and CANONICAL-OER decoders. -\item [{uper\_decoder}] This is the Unaligned PER decoder. -\item [{uper\_encoder}] This is the Unaligned Basic PER encoder. This encoder -will take the target structure and encode it into a series of bytes. -\item [{xer\_decoder}] This is the generic XER decoder. It takes both BASIC-XER -or CANONICAL-XER encodings and deserializes the data into a local, -machine-dependent representation. See Section~\ref{sub:Decoding-XER}. -\item [{xer\_encoder}] This is the XER encoder (XML Encoding Rules). This -encoder will take the target structure and represent it as an XML -(text) document using either BASIC-XER or CANONICAL-XER encoding rules. -See Section~\ref{sub:Encoding-XER}. - -\item [{check\_constraints}] Check that the contents of the target structure -are semantically valid and constrained to appropriate implicit or -explicit subtype constraints. See Section~\ref{sub:Validating-the-target}. -\item [{print\_struct}] This function convert the contents of the passed -target structure into human readable form. This form is not formal -and cannot be converted back into the structure, but it may turn out -to be useful for debugging or quick-n-dirty printing. See Section~\ref{sub:Printing-the-target}. -\item [{free\_struct}] This is a generic disposal which frees the target -structure. See Section~\ref{sub:Freeing-the-target}. -\end{description} -Each of the above function takes the type descriptor (\emph{asn\_DEF\_\ldots{}}) -and the target structure (\emph{rect}, as in the example above). - -\subsection{\label{sub:Generic-Encoding}Generic encoders and decoders} + /* Initialize the Rectangle members */ + rectangle->height = 42; /* any random value */ + rectangle->width = 23; /* any random value */ -Before we start describing specific encoders and decoders, let's step back -a little and check out a simple high level way. + /* BER encode the data if filename is given */ + if(ac < 2) { + fprintf(stderr, "Specify filename for BER output\n"); + } else { + const char *filename = av[1]; + FILE *fp = fopen(filename, "wb"); /* for BER output */ + + if(!fp) { + perror(filename); + exit(1); + } -The asn1c runtime supplies (see \emph{asn\_application.h}) two sets of high level functions, \emph{asn\_encode*} and \emph{asn\_decode*}, which take a transfer syntax selector as the argument. The transfer syntax selector is defined as this: + /* Encode the Rectangle type as BER (DER) */ + ec = der_encode(&asn_DEF_Rectangle, rectangle, write_out, fp); + fclose(fp); + if(ec.encoded == -1) { + fprintf(stderr, "Could not encode Rectangle (at %\%%s)\n", + ec.failed_type ? ec.failed_type->name : "unknown"); + exit(1); + } else { + fprintf(stderr, "Created %\%%s with BER encoded Rectangle\n", filename); + } + } -\begin{codesample}[basicstyle=\scriptsize\listingfont] -/* - * A selection of ASN.1 Transfer Syntaxes to use with generalized encoders and decoders. - */ -enum asn_transfer_syntax { - ATS_INVALID, - ATS_NONSTANDARD_PLAINTEXT, - ATS_BER, - ATS_DER, - ATS_CER, - ATS_BASIC_OER, - ATS_CANONICAL_OER, - ATS_UNALIGNED_BASIC_PER, - ATS_UNALIGNED_CANONICAL_PER, - ATS_BASIC_XER, - ATS_CANONICAL_XER, -}; + /* Also print the constructed Rectangle XER encoded (XML) */ + xer_fprint(stdout, &asn_DEF_Rectangle, rectangle); + + return 0; /* Encoding finished successfully */ + } \end{codesample} +\item Compile all files together using C compiler (varies by platform): -Using this encoding selector, encoding and decoding becomes very generic: +\begin{bash} +cc -I. -o %\textbf{\emph{rencode}} \emph{*.c}% +\end{bash} +\item Done. You have just created the BER and XER encoder of a Rectangle +type, named \textbf{rencode}! +\end{enumerate} -\noindent{}Encoding: +\section{\label{sec:A-Rectangle-Decoder}A “Rectangle” Decoder} -\begin{codesample}[basicstyle=\scriptsize\listingfont] -uint8_t buffer[128]; -size_t buf_size = sizeof(buffer); -asn_enc_rval_t er; +This example will help you to create a simple BER decoder of a simple +``Rectangle'' type used throughout this document. +\begin{enumerate} +\item Create a file named \textbf{rectangle.asn} with the following contents: -er = %\textbf{asn\_encode\emph{\_to\_buffer}}%(0, %\textbf{ATS\_DER}%, &asn_DEF_Rectangle, buffer, buf_size); +\begin{asn} +RectangleModule DEFINITIONS ::= BEGIN -if(er.encoded > buf_size) { - fprintf(stderr, "Buffer of size %\%%zu is too small for %\%%s, need %\%%zu\n", - buf_size, asn_DEF_Rectangle.name, er.encoded); +Rectangle ::= SEQUENCE { + height INTEGER, + width INTEGER } -\end{codesample} -\noindent{}Decoding: +END +\end{asn} +\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}: + +\begin{bash} +asn1c %\textbf{rectangle.asn}% +\end{bash} +\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading +the \textbf{rectangle.asn} file into the Web form and unpacking the +produced archive on your computer. +\item By this time, you should have gotten multiple files in the current +directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}. +\item Create a main() routine which takes the binary input file, decodes +it as it were a BER-encoded Rectangle type, and prints out the text +(XML) representation of the Rectangle type. Let's name the file \textbf{main.c}: \begin{codesample}[basicstyle=\scriptsize\listingfont] -Rectangle_t *%$\underbracket{\textrm{\listingfont rect = 0}}$%; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */ +#include +#include +#include /* Rectangle ASN.1 type */ -... = %\textbf{asn\_decode}%(0, %\textbf{ATS\_BER}%, &asn_DEF_Rectangle, (void **)%$\underbracket{\textrm{\listingfont \&rect}}$%, buffer, buf_size); -\end{codesample} +int main(int ac, char **av) { + char buf[1024]; /* Temporary buffer */ + asn_dec_rval_t rval; /* Decoder return value */ + Rectangle_t *%$\underbracket{\textrm{\listingfont rectangle = 0}}$%; /* Type to decode. %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */ + FILE *fp; /* Input file handler */ + size_t size; /* Number of bytes read */ + char *filename; /* Input file name */ -\subsection{\label{sub:Decoding-BER}Decoding BER} + /* Require a single filename argument */ + if(ac != 2) { + fprintf(stderr, "Usage: %\%%s \n", av[0]); + exit(1); + } else { + filename = av[1]; + } -The Basic Encoding Rules describe the most widely used (by the ASN.1 -community) way to encode and decode a given structure in a machine-independent -way. Several other encoding rules (CER, DER) define a more restrictive -versions of BER, so the generic BER parser is also capable of decoding -the data encoded by the CER and DER encoders. The opposite is not true. + /* Open input file as read-only binary */ + fp = fopen(filename, "rb"); + if(!fp) { + perror(filename); + exit(1); + } -\emph{The ASN.1 compiler provides the generic BER decoder which is -capable of decoding BER, CER and DER encoded data.} + /* Read up to the buffer size */ + size = fread(buf, 1, sizeof(buf), fp); + fclose(fp); + if(!size) { + fprintf(stderr, "%\%%s: Empty or broken\n", filename); + exit(1); + } -The decoder is restartable (stream-oriented), which means that in -case the buffer has less data than it is expected, the decoder will -process whatever there is available and ask for more data to be provided. -Please note that the decoder may actually process less data than it -was given in the buffer, which means that you must be able to make -the next buffer contain the unprocessed part of the previous buffer. + /* Decode the input buffer as Rectangle type */ + rval = ber_decode(0, &asn_DEF_Rectangle, (void **)&rectangle, buf, size); + if(rval.code != RC_OK) { + fprintf(stderr, "%\%%s: Broken Rectangle encoding at byte %\%%ld\n", filename, (long)rval.consumed); + exit(1); + } -Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes. -\begin{itemize} -\item You can concatenate these buffers and feed the BER decoder with 300 -bytes of data, or -\item You can feed it the first buffer of 100 bytes of data, realize that -the ber\_decoder consumed only 95 bytes from it and later feed the -decoder with 205 bytes buffer which consists of 5 unprocessed bytes -from the first buffer and the additional 200 bytes from the second -buffer. -\end{itemize} -This is not as convenient as it could be (the BER encoder could -consume the whole 100 bytes and keep these 5 bytes in some temporary -storage), but in case of existing stream based processing it might -actually fit well into existing algorithm. Suggestions are welcome. + /* Print the decoded Rectangle type as XML */ + xer_fprint(stdout, &asn_DEF_Rectangle, rectangle); -Here is the example of BER decoding of a simple structure: + return 0; /* Decoding finished successfully */ +} +\end{codesample} +\item Compile all files together using C compiler (varies by platform): -\begin{codesample} -Rectangle_t * -simple_deserializer(const void *buffer, size_t buf_size) { - asn_dec_rval_t rval; - Rectangle_t *%$\underbracket{\textrm{\listingfont rect = 0}}$%; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */ +\begin{bash} +cc -I. -o %\textbf{\emph{rdecode}} \emph{*.c}% +\end{bash} +\item Done. You have just created the BER decoder of a Rectangle type, +named \textbf{rdecode}! +\end{enumerate} - rval = %\textbf{asn\_DEF\_Rectangle.op->ber\_decoder}%(0, - &asn_DEF_Rectangle, - (void **)%$\underbracket{\textrm{\listingfont \&rect}}$%, /* Decoder %\emph{changes}% the pointer */ - buffer, buf_size, 0); +\section{Adding constraints to a “Rectangle”} - if(rval%\textbf{.code}% == RC_OK) { - return rect; /* Decoding succeeded */ - } else { - /* Free the partially decoded rectangle */ - ASN_STRUCT_FREE(asn_DEF_Rectangle, rect); - return 0; - } +This example shows how to add basic constraints to the ASN.1 specification +and how to invoke the constraints validation code in your application. +\begin{enumerate} + +\item Create a file named \textbf{rectangle.asn} with the following contents: + +\begin{asn} +RectangleModuleWithConstraints DEFINITIONS ::= BEGIN + +Rectangle ::= SEQUENCE { + height INTEGER (0..100), -- Value range constraint + width INTEGER (0..MAX) -- Makes width non-negative } -\end{codesample} -The code above defines a function, \emph{simple\_deserializer}, which -takes a buffer and its length and is expected to return a pointer -to the Rectangle\_t structure. Inside, it tries to convert the bytes -passed into the target structure (rect) using the BER decoder and -returns the rect pointer afterwards. If the structure cannot be deserialized, -it frees the memory which might be left allocated by the unfinished -\emph{ber\_decoder} routine and returns 0 (no data). (This \textbf{freeing -is necessary} because the ber\_decoder is a restartable procedure, -and may fail just because there is more data needs to be provided -before decoding could be finalized). The code above obviously does -not take into account the way the \emph{ber\_decoder()} failed, so -the freeing is necessary because the part of the buffer may already -be decoded into the structure by the time something goes wrong. +END +\end{asn} -A little less wordy would be to invoke a globally available \emph{ber\_decode()} -function instead of dereferencing the asn\_DEF\_Rectangle type descriptor: -\begin{codesample} -rval = ber_decode(0, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size); +\item Compile the file according to procedures shown in \fref{sec:A-Rectangle-Decoder}. +\item Modify the Rectangle type processing routine (you can start with the +main() routine shown in the \fref{sec:A-Rectangle-Decoder}) +by placing the following snippet of code \emph{before} encoding and/or +\emph{after} decoding the Rectangle type: + +\begin{codesample}[basicstyle=\scriptsize\listingfont] +int ret; /* Return value */ +char errbuf[128]; /* Buffer for error message */ +size_t errlen = sizeof(errbuf); /* Size of the buffer */ + +/* ... here goes the Rectangle %\emph{decoding}% code ... */ + +ret = asn_check_constraints(&asn_DEF_Rectangle, rectangle, errbuf, &errlen); +/* assert(errlen < sizeof(errbuf)); // you may rely on that */ +if(ret) { + fprintf(stderr, "Constraint validation failed: %\%%s\n", errbuf); + /* exit(...); // Replace with appropriate action */ + } + +/* ... here goes the Rectangle %\emph{encoding}% code ... */ \end{codesample} -Note that the initial (asn\_DEF\_Rectangle.op->ber\_decoder) reference -is gone, and also the last argument (0) is no longer necessary. +\item Compile the resulting C code as shown in the previous chapters. +\item Test the constraints checking code by assigning integer value +101 to the \textbf{.height} member of the Rectangle structure, or +a negative value to the \textbf{.width} member. +The program will fail with ``Constraint validation failed'' message. +\item Done. +\end{enumerate} -These two ways of BER decoder invocations are fully equivalent. +\chapter{ASN.1 Compiler} -The BER de\emph{coder} may fail because of (\emph{the following RC\_\ldots{} -codes are defined in ber\_decoder.h}): -\begin{itemize} -\item RC\_WMORE: There is more data expected than it is provided (stream -mode continuation feature); -\item RC\_FAIL: General failure to decode the buffer; -\item \ldots{} other codes may be defined as well. -\end{itemize} -Together with the return code (.code) the asn\_dec\_rval\_t type contains -the number of bytes which is consumed from the buffer. In the previous -hypothetical example of two buffers (of 100 and 200 bytes), the first -call to ber\_decode() would return with .code = RC\_WMORE and .consumed -= 95. The .consumed field of the BER decoder return value is \textbf{always} -valid, even if the decoder succeeds or fails with any other return -code. +\section{The asn1c compiler tool} -Look into ber\_decoder.h for the precise definition of ber\_decode() -and related types. +The purpose of the ASN.1 compiler is to convert the specifications +in ASN.1 notation into some other language, such as C. +The compiler reads the specification and emits a series of target +language structures (C structs, unions, enums) describing the corresponding +ASN.1 types. The compiler also creates the code which allows automatic +serialization and deserialization of these structures using several +standardized encoding rules (BER, DER, OER, PER, XER). -\subsection{\label{sub:Encoding-DER}Encoding DER} +Let's take the following ASN.1 example% +\footnote{\Fref{chap:Abstract-Syntax-Notation} provides a quick reference +on the ASN.1 notation.}: +\begin{asn} +RectangleModule DEFINITIONS ::= BEGIN -The Distinguished Encoding Rules is the \emph{canonical} variant of -BER encoding rules. The DER is best suited to encode the structures -where all the lengths are known beforehand. This is probably exactly -how you want to encode: either after a BER decoding or after a manual -fill-up, the target structure contains the data which size is implicitly -known before encoding. Among other uses, the DER encoding is used -to encode X.509 certificates. +Rectangle ::= SEQUENCE { + height INTEGER, -- Height of the rectangle + width INTEGER -- Width of the rectangle +} -As with BER decoder, the DER encoder may be invoked either directly -from the ASN.1 type descriptor (asn\_DEF\_Rectangle) or from the stand-alone -function, which is somewhat simpler: +END +\end{asn} +The asn1c compiler reads this ASN.1 definition and produce the following +C type: \begin{codesample} -/* - * This is the serializer itself. - * It supplies the DER encoder with the - * pointer to the custom output function. - */ -ssize_t -simple_serializer(FILE *ostream, Rectangle_t *rect) { - asn_enc_rval_t er; /* Encoder return value */ - - er = der_encode(&asn_DEF_Rect, rect, write_stream, ostream); - if(er%\textbf{.encoded}% == -1) { - fprintf(stderr, "Cannot encode %\%%s: %\%%s\n", - er%\textbf{.failed\_type}%->name, strerror(errno)); - return -1; - } else { - /* Return the number of bytes */ - return er.encoded; - } -} -\end{codesample} -As you see, the DER encoder does not write into some sort of buffer. -It just invokes the custom function (possible, multiple -times) which would save the data into appropriate storage. The optional -argument \emph{app\_key} is opaque for the DER encoder code and just -used by \emph{\_write\_stream()} as the pointer to the appropriate -output stream to be used. - -If the custom write function is not given (passed as 0), then the -DER encoder will essentially do the same thing (i.~e., encode the data) -but no callbacks will be invoked (so the data goes nowhere). It may -prove useful to determine the size of the structure's encoding before -actually doing the encoding% -\footnote{It is actually faster too: the encoder might skip over some computations -which aren't important for the size determination.% -}. - -Look into der\_encoder.h for the precise definition of der\_encode() -and related types. - - -\subsection{\label{sub:Encoding-XER}Encoding XER} - -The XER stands for XML Encoding Rules, where XML, in turn, is eXtensible -Markup Language, a text-based format for information exchange. The -encoder routine API comes in two flavors: stdio-based and callback-based. -With the callback-based encoder, the encoding process is very similar -to the DER one, described in Section~\ref{sub:Encoding-DER}. The -following example uses the definition of write\_stream() from up there. -\begin{codesample} -/* - * This procedure generates an XML document - * by invoking the XER encoder. - * NOTE: Do not copy this code verbatim! - * If the stdio output is necessary, - * use the xer_fprint() procedure instead. - * See Section %\ref{sub:Printing-the-target}%. - */ -int -print_as_XML(FILE *ostream, Rectangle_t *rect) { - asn_enc_rval_t er; /* Encoder return value */ - - er = xer_encode(&asn_DEF_Rectangle, rect, - XER_F_BASIC, /* BASIC-XER or CANONICAL-XER */ - write_stream, ostream); - - return (er.encoded == -1) ? -1 : 0; -} -\end{codesample} -Look into xer\_encoder.h for the precise definition of xer\_encode() -and related types. - -See Section~\ref{sub:Printing-the-target} for the example of stdio-based -XML encoder and other pretty-printing suggestions. - - -\subsection{\label{sub:Decoding-XER}Decoding XER} - -The data encoded using the XER rules can be subsequently decoded using -the xer\_decode() API call: -\begin{codesample} -Rectangle_t * -XML_to_Rectangle(const void *buffer, size_t buf_size) { - asn_dec_rval_t rval; - Rectangle_t *%$\underbracket{\textrm{\listingfont rect = 0}}$%; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */ - - rval = xer_decode(0, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size); - - if(rval%\textbf{.code}% == RC_OK) { - return rect; /* Decoding succeeded */ - } else { - /* Free partially decoded rect */ - ASN_STRUCT_FREE(asn_DEF_Rectangle, rect); - return 0; - } -} +typedef struct Rectangle_s { + long height; + long width; +} Rectangle_t; \end{codesample} -The decoder takes both BASIC-XER and CANONICAL-XER encodings. - -The decoder shares its data consumption properties with BER decoder; -please read the Section~\ref{sub:Decoding-BER} to know more. - -Look into xer\_decoder.h for the precise definition of xer\_decode() -and related types. - - -\subsection{\label{sub:Validating-the-target}Validating the target structure} +The asn1c compiler also creates the code for converting this structure into +platform-independent wire representation and the decoder +of such wire representation back into local, machine-specific type. +These encoders and decoders are also called serializers and deserializers, +marshallers and unmarshallers, or codecs. -Sometimes the target structure needs to be validated. For example, -if the structure was created by the application (as opposed to being -decoded from some external source), some important information required -by the ASN.1 specification might be missing. On the other hand, the -successful decoding of the data from some external source does not -necessarily mean that the data is fully valid either. It might well -be the case that the specification describes some subtype constraints -that were not taken into account during decoding, and it would actually -be useful to perform the last check when the data is ready to be encoded -or when the data has just been decoded to ensure its validity according -to some stricter rules. +Compiling ASN.1 modules into C codecs can be as simple as invoking \cmd{asn1c}: +may be used to compile the ASN.1 modules: +\begin{bash} +asn1c %\emph{}% +\end{bash} -The asn\_check\_constraints() function checks the type for various -implicit and explicit constraints. It is recommended to use asn\_check\_constraints() -function after each decoding and before each encoding. +If several ASN.1 modules contain interdependencies, all of the files +must be specified altogether: +\begin{bash} +asn1c %\emph{ ...}% +\end{bash} +The compiler \textbf{-E} and \textbf{-EF} options are used for testing +the parser and the semantic fixer, respectively. These options will +instruct the compiler to dump out the parsed (and fixed, if \textbf{-F} +is involved) ASN.1 specification as it was understood +by the compiler. It might be useful to check whether a particular +syntactic construct is properly supported by the compiler. +\begin{bash} +asn1c %\textbf{-EF} \emph{}% +\end{bash} +The \textbf{-P} option is used to dump the compiled output on the +screen instead of creating a bunch of .c and .h files on disk in the +current directory. You would probably want to start with \textbf{-P} +option instead of creating a mess in your current directory. Another +option, \textbf{-R}, asks compiler to only generate the files which +need to be generated, and supress linking in the numerous support +files. -Look into constraints.h for the precise definition of asn\_check\_constraints() -and related types. +Print the compiled output instead of creating multiple source files: +\begin{bash} +asn1c %\textbf{-P} \emph{}% +\end{bash} +\clearpage{} +\section{Compiler output} -\subsection{\label{sub:Printing-the-target}Printing the target structure} +The \cmd{asn1c} compiler produces a number of files: +\begin{itemize} +\item A set of .c and .h files for each type defined +in the ASN.1 specification. These files will be named similarly to +the ASN.1 types (\textbf{Rectangle.c} and \textbf{Rectangle.h} for the +RectangleModule ASN.1 module defined in the beginning of this document). +\item A set of helper .c and .h files which contain the generic encoders, +decoders and other useful routines. +Sometimes they are referred to by the term \emph{skeletons}. +There will be quite a few of them, some +of them are not even always necessary, but the overall amount of code +after compilation will be rather small anyway. +\item A \textbf{Makefile.am.libasncodecs} file which explicitly lists all the +generated files. +This makefile can be used on its own to build the just the codec library. +\item A \textbf{converter-example.c} file containing the \emph{int main()} function with a fully functioning encoder and data format converter. It can convert a given PDU between BER, XER and possibly OER and PER (if \cmd{-gen-OER} or \cmd{-gen-PER} options to \cmd{asn1c} were in effect). At some point you will want to replace this file with your own file containing the \emph{int main()} function. +\item A \textbf{Makefile.am.example} file which binds together +\textbf{Makefile.am.libasncodecs} and \textbf{converter-example.c} +to build a versatile converter and debugger for your data formats. +\end{itemize} +It is possible to compile everything with just a couple of instructions: +\begin{bash} +asn1c -pdu=%\emph{Rectangle}% *.asn +make -f Makefile.am.example # If you use `make` +\end{bash} +or +\begin{bash} +asn1c *.asn +cc -I. -DPDU=%\emph{Rectangle}% -o rectangle.exe *.c # ... or like this +\end{bash} +Refer to the \fref{chap:Quick-start-examples} for a sample +\emph{int main()} function if you want some custom logic and not satisfied +with the supplied \emph{converter-example.c}. -There are two ways to print the target structure: either invoke the -print\_struct member of the ASN.1 type descriptor, or using the asn\_fprint() -function, which is a simpler wrapper of the former: -\begin{codesample} -asn_fprint(stdout, &asn_DEF_Rectangle, rect); -\end{codesample} -Look into constr\_TYPE.h for the precise definition of asn\_fprint() -and related types. +\clearpage{} +\section{\label{sec:Command-line-options}Command line options} -Another practical alternative to this custom format printing would -be to invoke XER encoder. The default BASIC-XER encoder performs reasonable -formatting for the output to be useful and human readable. To invoke -the XER decoder in a manner similar to asn\_fprint(), use the xer\_fprint() -call: -\begin{codesample} -xer_fprint(stdout, &asn_DEF_Rectangle, rect); -\end{codesample} -See Section~\ref{sub:Encoding-XER} for XML-related details. +The following table summarizes the \cmd{asn1c} command line options. +\renewcommand{\arraystretch}{1.33} +\begin{longtable}{lp{4in}} +\textbf{Stage Selection Options} & \textbf{Description}\\ +\midrule +{\ttfamily -E} & {\small Stop after the parsing stage and print the reconstructed ASN.1 +specification code to the standard output.}\\ +{\ttfamily -F} & {\small Used together with \texttt{-E}, instructs the compiler to stop after +the ASN.1 syntax tree fixing stage and dump the reconstructed ASN.1 +specification to the standard output.}\\ +{\ttfamily -P} & {\small Dump the compiled output to the standard output instead of +creating the target language files on disk.}\\ +{\ttfamily -R} & {\small Restrict the compiler to generate only the ASN.1 tables, omitting the usual support code.}\\ +{\ttfamily -S~\emph{}} & {\small Use the specified directory with ASN.1 skeleton files.}\\ +{\ttfamily -X} & {\small Generate the XML DTD for the specified ASN.1 modules.}\\\\ +\textbf{Warning Options} & \textbf{Description}\\ +\midrule +{\ttfamily -Werror} & {\small Treat warnings as errors; abort if any warning is produced.}\\ +{\ttfamily -Wdebug-parser} & {\small Enable the parser debugging during the ASN.1 parsing stage.}\\ +{\ttfamily -Wdebug-lexer} & {\small Enable the lexer debugging during the ASN.1 parsing stage.}\\ +{\ttfamily -Wdebug-fixer} & {\small Enable the ASN.1 syntax tree fixer debugging during the fixing stage.}\\ +{\ttfamily -Wdebug-compiler} & {\small Enable debugging during the actual compile time.}\\ \\ +\textbf{Language Options} & \textbf{Description}\\ +\midrule +{\ttfamily -fbless-SIZE} & {\small Allow SIZE() constraint for INTEGER, ENUMERATED, and other types for which this constraint is normally prohibited by the standard. +This is a violation of an ASN.1 standard and compiler may fail to produce the meaningful code.}\\ +{\ttfamily -fcompound-names} & {\small Use complex names for C structures. Using complex names prevents +name clashes in case the module reuses the same identifiers in multiple +contexts.}\\ +{\ttfamily -findirect-choice} & {\small When generating code for a CHOICE type, compile the CHOICE +members as indirect pointers instead of declaring them inline. Consider +using this option together with \texttt{-fno-include-deps} +to prevent circular references.}\\ +{\ttfamily -fincludes-quoted} & {\small Generate \#include lines in "double" instead of quotes.}\\ +{\ttfamily -fknown-extern-type=\emph{}} & {\small Pretend the specified type is known. The compiler will assume +the target language source files for the given type have been provided +manually. }\\ +{\ttfamily -fline-refs} & {\small Include ASN.1 module's line numbers in generated code comments.}\\ +{\ttfamily -fno-constraints} & {\small Do not generate ASN.1 subtype constraint checking code. This +may produce a shorter executable.}\\ +{\ttfamily -fno-include-deps} & {\small Do not generate courtesy \#include lines for non-critical dependencies.}\\ +{\ttfamily -funnamed-unions} & {\small Enable unnamed unions in the definitions of target language's structures.}\\ +{\ttfamily -fwide-types} & {\small Use the wide integer types (INTEGER\_t, REAL\_t) instead of machine's native data types (long, double). }\\\\ +\textbf{Codecs Generation Options} & \textbf{Description}\\ +\midrule +{\ttfamily -gen-OER} & {\small Generate the Octet Encoding Rules (OER) support code.}\\ +{\ttfamily -gen-PER} & {\small Generate the Packed Encoding Rules (PER) support code.}\\ +{\ttfamily -pdu=\{\textbf{all}|\textbf{auto}|\emph{Type}\}} & {\small Create a PDU table for specified types, or discover the Protocol Data Units automatically. +In case of \texttt{-pdu=\textbf{all}}, all ASN.1 types defined in all modules wil form a PDU table. In case of \texttt{-pdu=\textbf{auto}}, all types not referenced by any other type will form a PDU table. If \texttt{\emph{Type}} is an ASN.1 type identifier, it is added to a PDU table. The last form may be specified multiple times.}\\ \\ +\textbf{Output Options} & \textbf{Description}\\ +\midrule +{\ttfamily -print-class-matrix} & {\small When \texttt{-EF} options are given, this option instructs the compiler to print out the collected Information Object Class matrix.}\\ +{\ttfamily -print-constraints} & {\small With \texttt{-EF}, this option instructs the compiler +to explain its internal understanding of subtype constraints.}\\ +{\ttfamily -print-lines} & {\small Generate \texttt{``-{}- \#line''} comments +in \texttt{-E} output.}\\ +\end{longtable} +\renewcommand{\arraystretch}{1} -\subsection{\label{sub:Freeing-the-target}Freeing the target structure} -Freeing the structure is slightly more complex than it may seem to. -When the ASN.1 structure is freed, all the members of the structure -and their submembers are recursively freed as well. -The ASN\_STRUCT\_FREE() macro helps with that. +\chapter{API reference} + +\section{ASN\_STRUCT\_FREE} +\section{ASN\_STRUCT\_FREE\_CONTENTS\_ONLY} +\section{ASN\_STRUCT\_RESET} +\section{asn\_check\_constraints} +\section{asn\_decode} +\section{asn\_encode} +\section{asn\_encode\_to\_buffer} +\section{asn\_encode\_to\_new\_buffer} +\section{asn\_fprint} +\section{ber\_decode} +\section{der\_encode} +\section{der\_encode\_to\_buffer} +\section{oer\_decode} +\section{oer\_encode} +\section{oer\_encode\_to\_buffer} +\section{uper\_decode} +\section{uper\_decode\_complete} +\section{uper\_encode} +\section{uper\_encode\_to\_buffer} +\section{uper\_encode\_to\_new\_buffer} +\section{xer\_decode} +\section{xer\_encode} +\section{xer\_equivalent} +\section{xer\_fprint} + +\chapter{API usage examples} -But it might not always be feasible to free the whole structure. -In the following example, the application programmer defines a custom -structure with one ASN.1-derived member (rect). +Let's start with including the necessary header files into your +application. Normally it is enough to include the header file of +the main PDU type. For our \emph{Rectangle} module, including the \emph{Rectangle.h} file is sufficient: \begin{codesample} -struct my_figure { /* The custom structure */ - int flags; /* */ - /* The type is generated by the ASN.1 compiler */ - Rectangle_t rect; - /* other members of the structure */ -}; +#include \end{codesample} -This member is not a reference to the Rectangle\_t, but an in-place inclusion -of the Rectangle\_t structure. -If there's a need to free the \code{rect} member, the usual procedure of -freeing everything must not be applied to the \code{\&rect} pointer itself, -because it does not point to the beginning of memory block allocated by -the memory allocation routine, but instead lies within a block allocated for -the my\_figure structure. - -To solve this problem, in addition to ASN\_STRUCT\_FREE() macro, the asn1c -skeletons define the ASN\_STRUCT\_RESET() macro which doesn't free the passed -pointer and instead resets the structure into the clean and safe state. +The header files defines a C structure corresponding to the ASN.1 +definition of a rectangle and the declaration of the ASN.1 +\emph{type descriptor}. A type descriptor is a special globally accessible +object which is used as an argument to most of the API functions provided by +the ASN.1 codec. A type descriptor starts with \emph{asn\_DEF\_\ldots{}}. For example, here is the code which frees the Rectangle\_t structure: \begin{codesample} -/* %\textbf{1. Rectangle\_t is defined within my\_figure}% */ -struct my_figure { - Rectangle_t rect; -} *mf = ...; -/* - * Freeing the Rectangle_t - * without freeing the mf->rect area. - */ -ASN_STRUCT_RESET(asn_DEF_Rectangle, &mf->rect); - -/* %\textbf{2. Rectangle\_t is a stand-alone pointer}% */ Rectangle_t *rect = ...; + +ASN_STRUCT_FREE(%\textbf{asn\_DEF\_}%Rectangle, rect); +\end{codesample} +This code defines a \emph{rect} pointer which points to the Rectangle\_t +structure which needs to be freed. The second line uses a generic +\code{ASN\_STRUCT\_FREE()} macro which invokes the memory deallocation routine +created specifically for this Rectangle\_t structure. +The \emph{asn\_DEF\_Rectangle} is the type descriptor which holds +a collection of routines and operations defined for the Rectangle\_t structure. + +\section{\label{sec:Generic-Encoding}Generic encoders and decoders} + +Before we start describing specific encoders and decoders, let's step back +a little and check out a simple high level way. + +The asn1c runtime supplies (see \emph{asn\_application.h}) two sets of high level functions, \emph{asn\_encode*} and \emph{asn\_decode*}, which take a transfer syntax selector as the argument. The transfer syntax selector is defined as this: + +\begin{codesample}[basicstyle=\scriptsize\listingfont] /* - * Freeing the Rectangle_t - * and freeing the rect pointer. + * A selection of ASN.1 Transfer Syntaxes to use with generalized encoders and decoders. */ -ASN_STRUCT_FREE(asn_DEF_Rectangle, rect); +enum asn_transfer_syntax { + ATS_INVALID, + ATS_NONSTANDARD_PLAINTEXT, + ATS_BER, + ATS_DER, + ATS_CER, + ATS_BASIC_OER, + ATS_CANONICAL_OER, + ATS_UNALIGNED_BASIC_PER, + ATS_UNALIGNED_CANONICAL_PER, + ATS_BASIC_XER, + ATS_CANONICAL_XER, +}; \end{codesample} -It is safe to invoke both macros with the target structure pointer -set to 0 (NULL). In this case, the function will do nothing. -\chapter{\label{cha:Step-by-step-examples}Step by step examples} +Using this encoding selector, encoding and decoding becomes very generic: -\section{A “Rectangle” converter and debugger} +\noindent{}Encoding: -One of the most common need is to create some sort of analysis tool -for the existing ASN.1 data files. Let's build a converter for existing -Rectangle binary files between BER, OER, PER, and XER (XML). +\begin{codesample}[basicstyle=\scriptsize\listingfont] +uint8_t buffer[128]; +size_t buf_size = sizeof(buffer); +asn_enc_rval_t er; -\begin{enumerate} -\item Create a file named \textbf{rectangle.asn} with the following contents: -\begin{asn} -RectangleModule DEFINITIONS ::= BEGIN +er = %\textbf{asn\_encode\emph{\_to\_buffer}}%(0, %\textbf{ATS\_DER}%, &asn_DEF_Rectangle, buffer, buf_size); -Rectangle ::= SEQUENCE { - height INTEGER, - width INTEGER +if(er.encoded > buf_size) { + fprintf(stderr, "Buffer of size %\%%zu is too small for %\%%s, need %\%%zu\n", + buf_size, asn_DEF_Rectangle.name, er.encoded); } +\end{codesample} -END -\end{asn} +\noindent{}Decoding: -\item Compile it into the set of .c and .h files using \cmd{asn1c} compiler: +\begin{codesample}[basicstyle=\scriptsize\listingfont] +Rectangle_t *%$\underbracket{\textrm{\listingfont rect = 0}}$%; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */ -\begin{bash} -asn1c -pdu=%\textbf{Rectangle}% -gen-OER -gen-PER %\textbf{rectangle.asn}% -\end{bash} +... = %\textbf{asn\_decode}%(0, %\textbf{ATS\_BER}%, &asn_DEF_Rectangle, (void **)%$\underbracket{\textrm{\listingfont \&rect}}$%, buffer, buf_size); +\end{codesample} -\item Create the converter and dumper: +\section{\label{sec:Decoding-BER}Decoding BER} -\begin{bash} -make -f Makefile.am.example -\end{bash} +The Basic Encoding Rules describe the most widely used (by the ASN.1 +community) way to encode and decode a given structure in a machine-independent +way. Several other encoding rules (CER, DER) define a more restrictive +versions of BER, so the generic BER parser is also capable of decoding +the data encoded by the CER and DER encoders. The opposite is not true. -\item Done. The binary file converter is ready: +\emph{The ASN.1 compiler provides the generic BER decoder which is +capable of decoding BER, CER and DER encoded data.} -\begin{bash} -./converter-example -h -\end{bash} -\end{enumerate} +The decoder is restartable (stream-oriented), which means that in +case the buffer has less data than it is expected, the decoder will +process whatever there is available and ask for more data to be provided. +Please note that the decoder may actually process less data than it +was given in the buffer, which means that you must be able to make +the next buffer contain the unprocessed part of the previous buffer. -\section{A “Rectangle” Encoder} +Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes. +\begin{itemize} +\item You can concatenate these buffers and feed the BER decoder with 300 +bytes of data, or +\item You can feed it the first buffer of 100 bytes of data, realize that +the ber\_decoder consumed only 95 bytes from it and later feed the +decoder with 205 bytes buffer which consists of 5 unprocessed bytes +from the first buffer and the additional 200 bytes from the second +buffer. +\end{itemize} +This is not as convenient as it could be (the BER encoder could +consume the whole 100 bytes and keep these 5 bytes in some temporary +storage), but in case of existing stream based processing it might +actually fit well into existing algorithm. Suggestions are welcome. -This example will help you create a simple BER and XER encoder of -a ``Rectangle'' type used throughout this document. -\begin{enumerate} -\item Create a file named \textbf{rectangle.asn} with the following contents: +Here is the example of BER decoding of a simple structure: -\begin{asn} -RectangleModule DEFINITIONS ::= BEGIN +\begin{codesample} +Rectangle_t * +simple_deserializer(const void *buffer, size_t buf_size) { + asn_dec_rval_t rval; + Rectangle_t *%$\underbracket{\textrm{\listingfont rect = 0}}$%; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */ -Rectangle ::= SEQUENCE { - height INTEGER, - width INTEGER + rval = %\textbf{asn\_DEF\_Rectangle.op->ber\_decoder}%(0, + &asn_DEF_Rectangle, + (void **)%$\underbracket{\textrm{\listingfont \&rect}}$%, /* Decoder %\emph{changes}% the pointer */ + buffer, buf_size, 0); + + if(rval%\textbf{.code}% == RC_OK) { + return rect; /* Decoding succeeded */ + } else { + /* Free the partially decoded rectangle */ + ASN_STRUCT_FREE(asn_DEF_Rectangle, rect); + return 0; + } } +\end{codesample} -END -\end{asn} -\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}: +The code above defines a function, \emph{simple\_deserializer}, which +takes a buffer and its length and is expected to return a pointer +to the Rectangle\_t structure. Inside, it tries to convert the bytes +passed into the target structure (rect) using the BER decoder and +returns the rect pointer afterwards. If the structure cannot be deserialized, +it frees the memory which might be left allocated by the unfinished +\emph{ber\_decoder} routine and returns 0 (no data). (This \textbf{freeing +is necessary} because the ber\_decoder is a restartable procedure, +and may fail just because there is more data needs to be provided +before decoding could be finalized). The code above obviously does +not take into account the way the \emph{ber\_decoder()} failed, so +the freeing is necessary because the part of the buffer may already +be decoded into the structure by the time something goes wrong. -\begin{bash} -asn1c %\textbf{rectangle.asn}% -\end{bash} -\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading -the \textbf{rectangle.asn} file into the Web form and unpacking the -produced archive on your computer. -\item By this time, you should have gotten multiple files in the current -directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}. -\item Create a main() routine which creates the Rectangle\_t structure in -memory and encodes it using BER and XER encoding rules. Let's name -the file \textbf{main.c}: +A little less wordy would be to invoke a globally available \emph{ber\_decode()} +function instead of dereferencing the asn\_DEF\_Rectangle type descriptor: +\begin{codesample} +rval = ber_decode(0, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size); +\end{codesample} +Note that the initial (asn\_DEF\_Rectangle.op->ber\_decoder) reference +is gone, and also the last argument (0) is no longer necessary. -\begin{codesample}[basicstyle=\scriptsize\listingfont] -#include -#include -#include /* Rectangle ASN.1 type */ +These two ways of BER decoder invocations are fully equivalent. -/* Write the encoded output into some FILE stream. */ -static int write_out(const void *buffer, size_t size, void *app_key) { - FILE *out_fp = app_key; - size_t wrote = fwrite(buffer, 1, size, out_fp); - return (wrote == size) ? 0 : -1; -} - -int main(int ac, char **av) { - Rectangle_t *rectangle; /* Type to encode */ - asn_enc_rval_t ec; /* Encoder return value */ +The BER de\emph{coder} may fail because of (\emph{the following RC\_\ldots{} +codes are defined in ber\_decoder.h}): +\begin{itemize} +\item RC\_WMORE: There is more data expected than it is provided (stream +mode continuation feature); +\item RC\_FAIL: General failure to decode the buffer; +\item \ldots{} other codes may be defined as well. +\end{itemize} +Together with the return code (.code) the asn\_dec\_rval\_t type contains +the number of bytes which is consumed from the buffer. In the previous +hypothetical example of two buffers (of 100 and 200 bytes), the first +call to ber\_decode() would return with .code = RC\_WMORE and .consumed += 95. The .consumed field of the BER decoder return value is \textbf{always} +valid, even if the decoder succeeds or fails with any other return +code. - /* Allocate the Rectangle_t */ - rectangle = calloc(1, sizeof(Rectangle_t)); /* not malloc! */ - if(!rectangle) { - perror("calloc() failed"); - exit(1); - } +Look into ber\_decoder.h for the precise definition of ber\_decode() +and related types. - /* Initialize the Rectangle members */ - rectangle->height = 42; /* any random value */ - rectangle->width = 23; /* any random value */ - /* BER encode the data if filename is given */ - if(ac < 2) { - fprintf(stderr, "Specify filename for BER output\n"); - } else { - const char *filename = av[1]; - FILE *fp = fopen(filename, "wb"); /* for BER output */ - - if(!fp) { - perror(filename); - exit(1); - } +\section{\label{sec:Encoding-DER}Encoding DER} - /* Encode the Rectangle type as BER (DER) */ - ec = der_encode(&asn_DEF_Rectangle, rectangle, write_out, fp); - fclose(fp); - if(ec.encoded == -1) { - fprintf(stderr, "Could not encode Rectangle (at %\%%s)\n", - ec.failed_type ? ec.failed_type->name : "unknown"); - exit(1); - } else { - fprintf(stderr, "Created %\%%s with BER encoded Rectangle\n", filename); - } +The Distinguished Encoding Rules is the \emph{canonical} variant of +BER encoding rules. The DER is best suited to encode the structures +where all the lengths are known beforehand. This is probably exactly +how you want to encode: either after a BER decoding or after a manual +fill-up, the target structure contains the data which size is implicitly +known before encoding. Among other uses, the DER encoding is used +to encode X.509 certificates. + +As with BER decoder, the DER encoder may be invoked either directly +from the ASN.1 type descriptor (asn\_DEF\_Rectangle) or from the stand-alone +function, which is somewhat simpler: +\begin{codesample} +/* + * This is the serializer itself. + * It supplies the DER encoder with the + * pointer to the custom output function. + */ +ssize_t +simple_serializer(FILE *ostream, Rectangle_t *rect) { + asn_enc_rval_t er; /* Encoder return value */ + + er = der_encode(&asn_DEF_Rect, rect, write_stream, ostream); + if(er%\textbf{.encoded}% == -1) { + fprintf(stderr, "Cannot encode %\%%s: %\%%s\n", + er%\textbf{.failed\_type}%->name, strerror(errno)); + return -1; + } else { + /* Return the number of bytes */ + return er.encoded; } - - /* Also print the constructed Rectangle XER encoded (XML) */ - xer_fprint(stdout, &asn_DEF_Rectangle, rectangle); - - return 0; /* Encoding finished successfully */ - } +} \end{codesample} -\item Compile all files together using C compiler (varies by platform): +As you see, the DER encoder does not write into some sort of buffer. +It just invokes the custom function (possible, multiple +times) which would save the data into appropriate storage. The optional +argument \emph{app\_key} is opaque for the DER encoder code and just +used by \emph{\_write\_stream()} as the pointer to the appropriate +output stream to be used. -\begin{bash} -cc -I. -o %\textbf{\emph{rencode}} \emph{*.c}% -\end{bash} -\item Done. You have just created the BER and XER encoder of a Rectangle -type, named \textbf{rencode}! -\end{enumerate} +If the custom write function is not given (passed as 0), then the +DER encoder will essentially do the same thing (i.~e., encode the data) +but no callbacks will be invoked (so the data goes nowhere). It may +prove useful to determine the size of the structure's encoding before +actually doing the encoding% +\footnote{It is actually faster too: the encoder might skip over some computations +which aren't important for the size determination.% +}. -\section{\label{sec:A-Rectangle-Decoder}A “Rectangle” Decoder} +Look into der\_encoder.h for the precise definition of der\_encode() +and related types. -This example will help you to create a simple BER decoder of a simple -``Rectangle'' type used throughout this document. -\begin{enumerate} -\item Create a file named \textbf{rectangle.asn} with the following contents: -\begin{asn} -RectangleModule DEFINITIONS ::= BEGIN +\section{\label{sec:Encoding-XER}Encoding XER} -Rectangle ::= SEQUENCE { - height INTEGER, - width INTEGER -} +The XER stands for XML Encoding Rules, where XML, in turn, is eXtensible +Markup Language, a text-based format for information exchange. The +encoder routine API comes in two flavors: stdio-based and callback-based. +With the callback-based encoder, the encoding process is very similar +to the DER one, described in \fref{sec:Encoding-DER}. The +following example uses the definition of write\_stream() from up there. +\begin{codesample} +/* + * This procedure generates an XML document + * by invoking the XER encoder. + * NOTE: Do not copy this code verbatim! + * If the stdio output is necessary, + * use the xer_fprint() procedure instead. + * See %\fref{sec:Printing-the-target}%. + */ +int +print_as_XML(FILE *ostream, Rectangle_t *rect) { + asn_enc_rval_t er; /* Encoder return value */ -END -\end{asn} -\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}: + er = xer_encode(&asn_DEF_Rectangle, rect, + XER_F_BASIC, /* BASIC-XER or CANONICAL-XER */ + write_stream, ostream); -\begin{bash} -asn1c %\textbf{rectangle.asn}% -\end{bash} -\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading -the \textbf{rectangle.asn} file into the Web form and unpacking the -produced archive on your computer. -\item By this time, you should have gotten multiple files in the current -directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}. -\item Create a main() routine which takes the binary input file, decodes -it as it were a BER-encoded Rectangle type, and prints out the text -(XML) representation of the Rectangle type. Let's name the file \textbf{main.c}: + return (er.encoded == -1) ? -1 : 0; +} +\end{codesample} +Look into xer\_encoder.h for the precise definition of xer\_encode() +and related types. -\begin{codesample}[basicstyle=\scriptsize\listingfont] -#include -#include -#include /* Rectangle ASN.1 type */ +See \fref{sec:Printing-the-target} for the example of stdio-based +XML encoder and other pretty-printing suggestions. -int main(int ac, char **av) { - char buf[1024]; /* Temporary buffer */ - asn_dec_rval_t rval; /* Decoder return value */ - Rectangle_t *%$\underbracket{\textrm{\listingfont rectangle = 0}}$%; /* Type to decode. %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */ - FILE *fp; /* Input file handler */ - size_t size; /* Number of bytes read */ - char *filename; /* Input file name */ - /* Require a single filename argument */ - if(ac != 2) { - fprintf(stderr, "Usage: %\%%s \n", av[0]); - exit(1); - } else { - filename = av[1]; - } +\section{\label{sec:Decoding-XER}Decoding XER} - /* Open input file as read-only binary */ - fp = fopen(filename, "rb"); - if(!fp) { - perror(filename); - exit(1); - } +The data encoded using the XER rules can be subsequently decoded using +the xer\_decode() API call: +\begin{codesample} +Rectangle_t * +XML_to_Rectangle(const void *buffer, size_t buf_size) { + asn_dec_rval_t rval; + Rectangle_t *%$\underbracket{\textrm{\listingfont rect = 0}}$%; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */ - /* Read up to the buffer size */ - size = fread(buf, 1, sizeof(buf), fp); - fclose(fp); - if(!size) { - fprintf(stderr, "%\%%s: Empty or broken\n", filename); - exit(1); - } + rval = xer_decode(0, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size); - /* Decode the input buffer as Rectangle type */ - rval = ber_decode(0, &asn_DEF_Rectangle, (void **)&rectangle, buf, size); - if(rval.code != RC_OK) { - fprintf(stderr, "%\%%s: Broken Rectangle encoding at byte %\%%ld\n", filename, (long)rval.consumed); - exit(1); + if(rval%\textbf{.code}% == RC_OK) { + return rect; /* Decoding succeeded */ + } else { + /* Free partially decoded rect */ + ASN_STRUCT_FREE(asn_DEF_Rectangle, rect); + return 0; } - - /* Print the decoded Rectangle type as XML */ - xer_fprint(stdout, &asn_DEF_Rectangle, rectangle); - - return 0; /* Decoding finished successfully */ } \end{codesample} -\item Compile all files together using C compiler (varies by platform): +The decoder takes both BASIC-XER and CANONICAL-XER encodings. -\begin{bash} -cc -I. -o %\textbf{\emph{rdecode}} \emph{*.c}% -\end{bash} -\item Done. You have just created the BER decoder of a Rectangle type, -named \textbf{rdecode}! -\end{enumerate} +The decoder shares its data consumption properties with BER decoder; +please read the \fref{sec:Decoding-BER} to know more. -\chapter{Constraint validation examples} +Look into xer\_decoder.h for the precise definition of xer\_decode() +and related types. -This chapter shows how to define ASN.1 constraints and use the generated -validation code. +\section{\label{sec:Validating-the-target}Validating the target structure} -\section{Adding constraints into ``Rectangle'' type} +Sometimes the target structure needs to be validated. For example, +if the structure was created by the application (as opposed to being +decoded from some external source), some important information required +by the ASN.1 specification might be missing. On the other hand, the +successful decoding of the data from some external source does not +necessarily mean that the data is fully valid either. It might well +be the case that the specification describes some subtype constraints +that were not taken into account during decoding, and it would actually +be useful to perform the last check when the data is ready to be encoded +or when the data has just been decoded to ensure its validity according +to some stricter rules. -This example shows how to add basic constraints to the ASN.1 specification -and how to invoke the constraints validation code in your application. -\begin{enumerate} -\item Create a file named \textbf{rectangle.asn} with the following contents: +The asn\_check\_constraints() function checks the type for various +implicit and explicit constraints. It is recommended to use asn\_check\_constraints() +function after each decoding and before each encoding. -\begin{asn} -RectangleModuleWithConstraints DEFINITIONS ::= BEGIN +Look into constraints.h for the precise definition of asn\_check\_constraints() +and related types. -Rectangle ::= SEQUENCE { - height INTEGER (0..100), -- Value range constraint - width INTEGER (0..MAX) -- Makes width non-negative -} -END -\end{asn} -\item Compile the file according to procedures shown in the previous chapter. -\item Modify the Rectangle type processing routine (you can start with the -main() routine shown in the Section~\ref{sec:A-Rectangle-Decoder}) -by placing the following snippet of code \emph{before} encoding and/or -\emph{after} decoding the Rectangle type% -\footnote{Placing the constraint checking code \emph{before encoding} helps -to make sure the data is correct and within constraints before -sharing the data with anyone else. -Placing the constraint checking code \emph{after decoding} helps to make sure -the application got the valid contents before making use of it.% -}: +\section{\label{sec:Printing-the-target}Printing the target structure} +There are two ways to print the target structure: either invoke the +print\_struct member of the ASN.1 type descriptor, or using the asn\_fprint() +function, which is a simpler wrapper of the former: \begin{codesample} -int ret; /* Return value */ -char errbuf[128]; /* Buffer for error message */ -size_t errlen = sizeof(errbuf); /* Size of the buffer */ +asn_fprint(stdout, &asn_DEF_Rectangle, rect); +\end{codesample} +Look into constr\_TYPE.h for the precise definition of asn\_fprint() +and related types. -/* ... here goes the Rectangle %\emph{decoding}% code ... */ +Another practical alternative to this custom format printing would +be to invoke XER encoder. The default BASIC-XER encoder performs reasonable +formatting for the output to be useful and human readable. To invoke +the XER decoder in a manner similar to asn\_fprint(), use the xer\_fprint() +call: +\begin{codesample} +xer_fprint(stdout, &asn_DEF_Rectangle, rect); +\end{codesample} +See \fref{sec:Encoding-XER} for XML-related details. -ret = asn_check_constraints(&asn_DEF_Rectangle, rectangle, errbuf, &errlen); -/* assert(errlen < sizeof(errbuf)); // you may rely on that */ -if(ret) { - fprintf(stderr, "Constraint validation failed: %\%%s\n", - errbuf /* errbuf is properly null-terminated */ - ); - /* exit(...); // Replace with appropriate action */ - } -/* ... here goes the Rectangle %\emph{encoding}% code ... */ -\end{codesample} -\item Compile the resulting C code as shown in the previous chapters. -\item Try to test the constraints checking code by assigning integer value -101 to the \textbf{.height} member of the Rectangle structure, or -a negative value to the \textbf{.width} member. In either case, the -program should print ``Constraint validation failed'' message, followed -by a short explanation why validation did not succeed. -\item Done. -\end{enumerate} +\section{\label{sec:Freeing-the-target}Freeing the target structure} + +Freeing the structure is slightly more complex than it may seem to. +When the ASN.1 structure is freed, all the members of the structure +and their submembers are recursively freed as well. +The ASN\_STRUCT\_FREE() macro helps with that. -\part{\label{par:ASN.1-Basics}ASN.1 Basics} +But it might not always be feasible to free the whole structure. +In the following example, the application programmer defines a custom +structure with one ASN.1-derived member (rect). +\begin{codesample} +struct my_figure { /* The custom structure */ + int flags; /* */ + /* The type is generated by the ASN.1 compiler */ + Rectangle_t rect; + /* other members of the structure */ +}; +\end{codesample} +This member is not a reference to the Rectangle\_t, but an in-place inclusion +of the Rectangle\_t structure. +If there's a need to free the \code{rect} member, the usual procedure of +freeing everything must not be applied to the \code{\&rect} pointer itself, +because it does not point to the beginning of memory block allocated by +the memory allocation routine, but instead lies within a block allocated for +the my\_figure structure. +To solve this problem, in addition to ASN\_STRUCT\_FREE() macro, the asn1c +skeletons define the ASN\_STRUCT\_RESET() macro which doesn't free the passed +pointer and instead resets the structure into the clean and safe state. +\begin{codesample} +/* %\textbf{1. Rectangle\_t is defined within my\_figure}% */ +struct my_figure { + Rectangle_t rect; +} *mf = ...; +/* + * Freeing the Rectangle_t + * without freeing the mf->rect area. + */ +ASN_STRUCT_RESET(asn_DEF_Rectangle, &mf->rect); + +/* %\textbf{2. Rectangle\_t is a stand-alone pointer}% */ +Rectangle_t *rect = ...; +/* + * Freeing the Rectangle_t + * and freeing the rect pointer. + */ +ASN_STRUCT_FREE(asn_DEF_Rectangle, rect); +\end{codesample} +It is safe to invoke both macros with the target structure pointer +set to 0 (NULL). In this case, the function will do nothing. -\chapter{\label{cha:Abstract-Syntax-Notation:}Abstract Syntax Notation: ASN.1} +\chapter{\label{chap:Abstract-Syntax-Notation}Abstract Syntax Notation: ASN.1} \emph{This chapter defines some basic ASN.1 concepts and describes several most widely used types. It is by no means an authoritative From ec4b7af9efe59c2c6111929ace31850dbcd69a23 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Tue, 7 Nov 2017 04:20:36 -0800 Subject: [PATCH 17/41] doc --- skeletons/per_decoder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skeletons/per_decoder.h b/skeletons/per_decoder.h index 24dfe9366..710f4ee09 100644 --- a/skeletons/per_decoder.h +++ b/skeletons/per_decoder.h @@ -35,7 +35,7 @@ asn_dec_rval_t uper_decode( const struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ void **struct_ptr, /* Pointer to a target structure's pointer */ const void *buffer, /* Data to be decoded */ - size_t size, /* Size of data buffer */ + size_t size, /* Size of the input data buffer, in bytes */ int skip_bits, /* Number of unused leading bits, 0..7 */ int unused_bits /* Number of unused tailing bits, 0..7 */ ); From cf573ec13c1476099e8f952fe2efcfcd8ec9de8d Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Tue, 7 Nov 2017 04:20:52 -0800 Subject: [PATCH 18/41] constness --- doc/docsrc/asn_dec_rval.inc | 23 +++++++++++++++++++++++ skeletons/constr_TYPE.c | 25 ++++++++++++++----------- skeletons/constr_TYPE.h | 11 +++++------ 3 files changed, 42 insertions(+), 17 deletions(-) create mode 100644 doc/docsrc/asn_dec_rval.inc diff --git a/doc/docsrc/asn_dec_rval.inc b/doc/docsrc/asn_dec_rval.inc new file mode 100644 index 000000000..82b855135 --- /dev/null +++ b/doc/docsrc/asn_dec_rval.inc @@ -0,0 +1,23 @@ +The return value is returned in a compound structure: +\begin{codesample} +typedef struct { + enum { + RC_OK, /* Decoded successfully */ + RC_WMORE, /* More data expected, call again */ + RC_FAIL /* Failure to decode data */ + } code; /* Result code */ + size_t consumed; /* Number of bytes consumed */ +} asn_dec_rval_t; +\end{codesample} + +The \code{.code} member specifies the decoding outcome. + +\begin{description}[labelindent=\parindent] +\item[RC\_OK] Decoded successfully and completely +\item[RC\_WMORE] More data expected, call again +\item[RC\_FAIL] Failed for good +\end{description} + +The \code{.consumed} member specifies the amount of \code{buffer} data +that was used during parsing, irrespectively of the \code{.code}. + diff --git a/skeletons/constr_TYPE.c b/skeletons/constr_TYPE.c index 7a135ce23..aefaefdb7 100644 --- a/skeletons/constr_TYPE.c +++ b/skeletons/constr_TYPE.c @@ -33,22 +33,25 @@ asn_TYPE_outmost_tag(const asn_TYPE_descriptor_t *type_descriptor, * Print the target language's structure in human readable form. */ int -asn_fprint(FILE *stream, asn_TYPE_descriptor_t *td, const void *struct_ptr) { - if(!stream) stream = stdout; - if(!td || !struct_ptr) { - errno = EINVAL; - return -1; +asn_fprint(FILE *stream, const asn_TYPE_descriptor_t *td, + const void *struct_ptr) { + if(!stream) stream = stdout; + if(!td || !struct_ptr) { + errno = EINVAL; + return -1; } /* Invoke type-specific printer */ - if(td->op->print_struct(td, struct_ptr, 1, _print2fp, stream)) - return -1; + if(td->op->print_struct(td, struct_ptr, 1, _print2fp, stream)) { + return -1; + } - /* Terminate the output */ - if(_print2fp("\n", 1, stream)) - return -1; + /* Terminate the output */ + if(_print2fp("\n", 1, stream)) { + return -1; + } - return fflush(stream); + return fflush(stream); } /* Dump the data into the specified stdio stream */ diff --git a/skeletons/constr_TYPE.h b/skeletons/constr_TYPE.h index d9d55c206..31102f55f 100644 --- a/skeletons/constr_TYPE.h +++ b/skeletons/constr_TYPE.h @@ -242,17 +242,16 @@ typedef struct asn_TYPE_tag2member_s { } asn_TYPE_tag2member_t; /* - * This function is a wrapper around (td)->print_struct, which prints out - * the contents of the target language's structure (struct_ptr) into the - * file pointer (stream) in human readable form. + * This function prints out the contents of the target language's structure + * (struct_ptr) into the file pointer (stream) in human readable form. * RETURN VALUES: * 0: The structure is printed. * -1: Problem dumping the structure. * (See also xer_fprint() in xer_encoder.h) */ -int asn_fprint(FILE *stream, /* Destination stream descriptor */ - asn_TYPE_descriptor_t *td, /* ASN.1 type descriptor */ - const void *struct_ptr); /* Structure to be printed */ +int asn_fprint(FILE *stream, /* Destination stream descriptor */ + const asn_TYPE_descriptor_t *td, /* ASN.1 type descriptor */ + const void *struct_ptr); /* Structure to be printed */ #ifdef __cplusplus } From 933b950a80f0eed416fbc1fca095e11594ccc4b7 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Tue, 7 Nov 2017 05:55:29 -0800 Subject: [PATCH 19/41] moved decl around to maintain comments continuity --- skeletons/xer_encoder.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/skeletons/xer_encoder.h b/skeletons/xer_encoder.h index 564eea71c..9d75922c5 100644 --- a/skeletons/xer_encoder.h +++ b/skeletons/xer_encoder.h @@ -31,6 +31,17 @@ asn_enc_rval_t xer_encode(const struct asn_TYPE_descriptor_s *type_descriptor, void *app_key /* Arbitrary callback argument */ ); +/* + * The variant of the above function which dumps the BASIC-XER (XER_F_BASIC) + * output into the chosen file pointer. + * RETURN VALUES: + * 0: The structure is printed. + * -1: Problem printing the structure. + * WARNING: No sensible errno value is returned. + */ +int xer_fprint(FILE *stream, const struct asn_TYPE_descriptor_s *td, + const void *struct_ptr); + /* * A helper function that uses XER encoding/decoding to verify that: * - Both structures encode into the same BASIC XER. @@ -53,17 +64,6 @@ enum xer_equivalence_e xer_equivalent( const struct asn_TYPE_descriptor_s *type_descriptor, const void *struct1, const void *struct2, FILE *opt_debug_stream); -/* - * The variant of the above function which dumps the BASIC-XER (XER_F_BASIC) - * output into the chosen file pointer. - * RETURN VALUES: - * 0: The structure is printed. - * -1: Problem printing the structure. - * WARNING: No sensible errno value is returned. - */ -int xer_fprint(FILE *stream, const struct asn_TYPE_descriptor_s *td, - const void *sptr); - /* * Type of the generic XER encoder. */ From 9ce64c13c750ff7ce79e7d697372b1299cff8411 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Tue, 7 Nov 2017 06:22:14 -0800 Subject: [PATCH 20/41] API reference --- doc/asn1c-usage.pdf | Bin 205031 -> 244068 bytes doc/docsrc/Makefile.am | 2 +- doc/docsrc/asn1c-usage.tex | 582 +++++++++++++++++++++++++++++++++--- doc/docsrc/asn_dec_rval.inc | 17 +- 4 files changed, 561 insertions(+), 40 deletions(-) diff --git a/doc/asn1c-usage.pdf b/doc/asn1c-usage.pdf index a4d825102724094484f4dd64161dca532da20728..972ea178c5331a424099d3ce8720a3a9cf4bacca 100644 GIT binary patch delta 216647 zcmZs>QEr^L5W$^uK!U@;Y;6?ATAl=>Y7} z1AII?fSsQo+S$d))X)~%W5ZUtM}C+QcE>ZaTQKN)O^QYhD;_8UZV8SF7t++o|COL# zg@OXHQ~hQ=qK|;b2OKtE05;?)z~Kj$L%Y3qND$Fk-f&Z7l+uuRMRD-ur5mIeOOP2T zkF9W2C5O_yMsgld_c4=7<(A5tMQdy>p>7`qP@|>MnohB}eyv8icciuiG^c&)PO#ly zybg5HpzPp@T}-~rsTxEC8&Ok^i5f~HYwCcf6hWGw0_T)m8pN584bH@*Mb2T3k3Z~3 zvbM@4v7igg*1CDTR?(1ac)d`*_|6Y9IkM9w9`J@qkxneMT&blF^_>(Ed#$=u!p_tJ zxSn=S*&SX(9lKg|=Q_g5KJVYZ=Q$1n6*wiBSx`ozX9QD=`Z^^4HH3<<>Rkjk;y;W& zz_Ku~!u}HM1x&YAyb!IGn^wzk92Cn=iLFUU`_OMq z$lu*xKvt;M+CrP!nf!kj{@)4Q-pC4?CCSmB48X+1#r%Ih#&za&?IkOs|0}PUUj8Wl z?3)Dl1PE08T0o}=?S`;sL;LGD#v4b>c5gmyN17Gg@6_x_C57u!1wg8ib z!|%JphxMDCfX^o=tiLP{-_>lb7X_(#Wa#&8pPvJ~Rq~M^N;|R6e9MPLe0<3_TsRddC)}cn3 zPad8thgclKOF

KX@h#j8d8U!h-!x*H7JSgFPTT(q2BGtNe(_%2~&z@ExGa(2=OaFUZi5zwSfU6Gdv+A`ZcVs=1o`LqB6f((Im- z1!h*CX){J?$f_}Me{X;oZORRqJunhtFjqv9b6(sYtiZHE6S#nTo?|wTza97T2g``B zbxfm`4)k9{1(i)PfcqdRx6jysz9}xk9SKsrrJXvp%)JG9;lxX?p+d{7_UQWaIMj4c zv9WXI3_V$pF_BF=ZEkix?()tb^IzDt%E{$txFiRX+T?v7Bbpy~IW&&JUOpUk1(q;e zN+%RrU0nFUY_7SU&&EGtoD82U%bV%d5RVcIzF}`_feC*#faFVxZFZlV#2JbmaiQgwVJ0uncYmhsak2TnbQy(M0XpGgJH-H2r8BjOA=K;+hR^8pU0iFLb9qmZh7$|> zSLdxJ4>&FfkYJ_6LxF&-Vqp);MCq?t9g(4P&3pGM8Z7$im`isbajWD0FMCUXP=U0@ zsjDR2x6G4Vro_(ixWglYjPa*ky`k8?(S_o&H5Eaivqs{!^tVkO-~FEY>foN6?I2{F zb;%>YL;U2>>Hq<4AQ9)lytWL35Y_fAbKdTptG5E@Vc%(D$bn|ElG`JCwI>gv!)weO{epfj1S_aWc0y7uXF{kZ+FThiAl4X)<=K)}8$j#CGe&(@|I(TIK=MVjRt_1%|uOoRPsfMJs36_NXQd$F3 zrxXx-)ELu}o}B=2#{RB_Z0uqu&C5=b4L`}L4Cn4)Mk#d}`wa0_*CV#{(WvS$gUk45 zi~)OR7}J(qg?B?#Do=u|!Vr);m(I5cwJqxM_sz`yeogP9aMGsyPhI<8vc|!lG`~Ow zU}t3fAF`G`9b3$f=zr@8t(T8yqwy|*?HHacI$@jCE5_yWYVnfDXG8D#y*3Il!OEJx zGi70V&Fo*`*zu)wOx@M>zHwLT`s+~?^0~|2#xSjLdNQW(F~rprKK(we%kOBQ%yzme zpueGBE}y?Cv(J9RehrwI@}O0FU43smId%4MnpA!KtQ*=F$UB`4Q)e!*AOo_Eny|eo z*uo3C5bSVr-*7r-*Y}I^ei}0_>1~~zUJaG9&IAO#g<@^`SPEviJh(qfJW~Auzp-a9 zSolMi!QXf$RR3UiNG_d%s~u*Gw|uJs zquM^PH|>BIeCQT9ROA2}nlUM2=xNvu{6w8!i*|_x*A&vlEG>m7LR3ETK@FRxNb9^h z+=1VJ%h8aUqkt5#(j&fFJ5!zK)g*A}W51yvE`x7&Es9~d)ChBB_0u=mcrzf>z+qje z$ZS$r1Rr9leLa*(`myuIOhbAfaB~9T$65wcNehTCd=W-Qm+LXU*HM|TJxN|KUTQJ1 zy`uJREEJ^ZPrO>KmIogyhu2d_!L+Yyb&ISaFe*h=u`glecJiA+>Qgx)Jo*>xM zHhhkyO}M{<(Mx(X&W?i4h9ii0sbB|(zyNZo=Nqq>y}y#r)_ zt35{WBG~&eRh&J^g|G`2|x0DJ}*KSWPU&MS(Kd2wU4b!97gXk`I+2-akHSacLTtAE%34A z81ztx0ZfpwS&!|_KUO}wSTqYb_%tfvDPX0Zu_@T~T8&)J#ZP|4lG|t%?&6V8q11V} z4x=Fz*_1tbl%CrPOU)P1OFW=#*RX2*VtW<_1_0-L*^E<~fXF5N3NQ0YGgegc<6tD& zOkA3*`ovaHoUsKWn|86{{5aiHi;x9tSdqbUoW<{SkmUF`ISn-cWGSmXw?fhH7!>9_ zH93*JjF=0GWYZ4=_&;oN7x)EJASt&6ck$e>H$QW=5PC5?WtlQ(U3v>Cn$sMlca2>*BCxx^%XS%bgXq5u&o$LY~|-O0bSy z=fq)R_7>=9h0M=JPVo|zT-k@hFzo7z>ZYg%Uf^6~+MgDE#AS{o>W|NI6No?;t zXRP?lqCm%D$AQN|MI1ZsqlXhc4I!{NWB=vV`6;&v{4jd?)f z3FkuM;gTr{M&jZ42#g?f%u6!S|hU@r3`qJB?HuGf3yaux-I z=q_=w>{m4VoY1W>4<5tM%O7i*06_jG%NI0K+eQqUaCoW9*;FAWX0oZyN$_4%01#)O&3e&h2ld*-&llP_2J%QF(A>&{{;qsrdbhN@T(CYRX z(^Q6rMs)D7aq-t8ct2lu24B5QX^r_cNT}r0)|IVX+95MS~6udQnx{& zW_K|7s`P#`P6rs=PE;_mL5{=nKP|s~NKB%WUY){z{D0zWeu<)zK=?JI8ELtHo`wK1 zm!Y8l_r&33Nh=@(CI_(okAagiEkDEvJ9f((qMuJ5i${^7h#=`dY&(Z@ut4Ny80NVD z?AX*=v>oa1Sgpk|^V&DV0CnZxzb=B<(*wVv-Cn!@km~vj_PMN`=6`|E(ir1j2 z-Fvez_Yo$wxz1h>dc-^+k($StQV%}AWWKY9q^_B~=3d9xMS%u^8cO^(Y7VM+Nv_sc z3r%#($|i^~Mza#Sjwx)adOd8auIoz?r`orEp}%AHNFa7tk(NnrSy3&xn>vc)(lvk& z(9juZnhmzJ5}e6E_zQxfW|A>P>K6oM-IfIFAs?p8HcBR<`h$e808Ay%O0PI2!UVm9 zrAQi=dzvpP5J3C`1N42)w9u4|a2mu6efB5$P;MN)2vggLL+|1fcJ<`q0EJgEIpP1l zelBK0M#BFlf70p#0f2?|e{3@~e<$r|IAFJ5X-*)k!xPIP4WlG>~2 zH-7b#lgr1ZJgmx~Zk|aJCGiu(P{$T`QDifJ22f$YR~H{vpAI*l9<0a@Rl^Ovy5?V? zs@3*N+g^8PwQ%ZMx)vraV^Z}D-I}k6eMjB_CUbN8dnW=reukQ?)RD!eP~0czUJa=T z{C1X*e3wW$#lsiQ>a?5mGvsxuO`Yj(91WLEEqOcCUVkQlpuG+gr9prtu?Y`(<{@d= z}DD|n=1$d|Cetrc@#TdU zRcQmzXB!DT!yaWTDn3NGME+jzYYQhheTxpDQZo!c_&3+qraSFfz|_%X43$uFf@tX7 ztQ;-Y2aW9;$7W8NA!Tj%=w>a8TBUzDo=~E3- zhPA72(fxF~`Y#ksg{$L~poEnCrCX8a;gxmS=P1S&$a`$M1puo)={}2DBv>~G;L@zv z)9`F|J^#$Rs79s|+EkH54Q?n_= zeCZv@vtz9cW-Wu5=Xkge-r0Vio_#N~dEOodPy{x28H(vvl#gaeu#7&Z-yzmTx9e_X zmk~A!?lxGU6J;@U9<%$CUgaUa%LKijmez-Hs;wR2c%$%f_tF={DQvX>WeUrO9_^tH zXNp^?kM2-s_d6Us@SurzI_}w6Y2~+-gxij5L3-c!&w@w9phmYM0s(kW`FnU&TINdO zYu1vl_Ie0CeVWrge2@=m=c|p}e+?%k(S_0AFr z->l1`nuCvoO@)rBWC>+}HI$gzWnTfcSk3B0Xe9fKXodsEdd}o5S&ghM-rLkRhcx1E z4NjOgkF3P^g|^AylWlp(G-uZAwS79T`KXc?Tb>zJE>OpP)XR2y{A=Ckq(*3FAsal4 z?K$^xVsSoB$cFhZRRr)RT?WGwH$krH9hHI|h4xM7x7cN~bVC(jjUT6aP~+weQiG_$ zAL!A5FWV?*1${TzXMgCBM6*_Vp$^%zY;REUTb34iJWkrat4 z0s6Q}4AJD5_>$v2+TGzZKk*mr#w}pjt71zD`pF+AF4;&y2g^t!#=d6GBjiSfGEeXg z(I5|glD7xgBby5F8xTEGcK?gu1-7)x9@JY_WRsTj`H2Qd`Dt# zN7j;>S7+FZZOz=wYXfL5zIr#HvwVXcP|nGzMsHakX7nvFthZ1=_#Pkyn1|Ks;)`kg z(w!UT8Y}Ot@P?H=@J8NI#$2Cb8RB|j6>@a&d3E!7zQU56 zLBajj8k&%^`{I+!mLVlY`yFoN(hl4^KRsU86nkP0v*c+6z3u$rF1a?x^yHK0-E9^{ zzYS+?NGQqueGUTvds}Bn{{Lw1f9!}Hz|PL`e~!EsY^hk1j{6&pBgn|1y<9;dNKkyx z-k5EUp|Hft<+O~Uw}V@r!05fyikf2aHt7jctk2wzua5r0dji_|JwQ+P&)=U9+xKIQ zzd%bD-w)T(llFVbaFcDbfIe$m5Wm2nG38BCDi)`Nw-4rSiVnP^6g8Gbk0WX5a3SpAA?9L! z_vrWCJJm^L!)tI^t4Do|bpSG&B4L!EIPaaEvT3$cN265{$95}sbte`|u#+Vknrjna zhLdb+OM%!q7MSSpdDWT4hjHt?jQEcW9wz->3cdlJy7TUa8>{vmYK8yE9@Eo} zzNT93@~n%k8^>kw$$5qBDtXD4a6pbP)#6l|9RusE;$zP11>j0CPbpMplb^7gUPy(R z_~_MCv(8GB%%cS`CmMIXDCx}Gt7b>UOxf*ycSZ!wm{|)en7gle;CN<;R7R_$kq zxqe^%hdKlzGpA6}w?-+9iTOc@Vz9*An1 z3mh3p^v(jyC{YakxRYhaN6xUb9qLxWRhPKzfodP1?~wabiraSTjoj~j(NFBjm}t%k znvv27n*_9d`?oQU&9-J1mn_^K+)yyYRTMl=(+w+nUcuRTOIn761Gi)fvWRG6pS`8J z)nb|ZBF0tKHr;j5Eot?yyU>vL;cbXd;Qd5M1~)atu#rQyyn@HyZ^6Fe+d>Fxl>vS|+*D*pBk}vPF7RE6Jen?Ii;V z0#{;H(W&&)K3J^!OW=UE!qDK0F=_IEKVX!C24>?Cpu+q&EjbCfe2r8E!<}kV%Ev?c zTx<8;8+q3OjIW_H(601KKd>bVI}MA z$uJ^q!5-x?Ff$I@3UiW5hLePCxFJ}|lM__GVIJ;&G!$Xww-t3_jE$J)y7O6thCAU; z@8{I5c-5iLJ&Q#(Ucfmfo^}*iI##1z(qWZGD|blSMBo+RXe2 z{&>9{?p3la6E37}tV6h7(wxMfmZZ1R@-=qfdhgp(9Br&59=}kt!5q#Mk6mJYG6kn#lv~; zY;iP~?pGXK+c1lYXuL2HpZ_O7yr|u>N>8qZ!<{$&;%tU5E?}<`#2N?Z=8M158`a~DuNDszkLC;r^4Pq= zHnU=CPmnd4W4+i}Z+>t5?$e=)R~Gg;a>vORy?VADZC7bxg-Z3l@WBg!5+LwF_E5sH znV9rpTY4OdzBGc!d^|rgS>vmnCNhWVJ{w!9bgNwMLwGTO%6eP#j*F_vSJKX|9n=yI^iRe=pL6)`G*xaqV`y@c5M1+-$V-=riR+*OIW=?SMS`=F8RT z>U~VA!fPM53NXeu%#Z-3ubBu73wB3v2_u7*oukthoarmGJ4yrOj*zpj8&@&iy+OlP zsqDyOYSq%=8JvnB`{oTppA9;mRC%XEEbNy|Z@pDv{zEcrI@{Rh@Oyis#ZEruF1pXb ztspSl^+rZZrI!waQuB04n#_h_`3;-rtRuW~MCGZ%m>hRq6xqS<$-G9`vn)(v$Pq_S z2i$}u)|GK8KXn2YU|nd??I5i(4)jugKp;Y(9P_??x>L@PK_pqu2}~z|b;dne74a#9N@sG7c!HP}l z*0TnMS|iP0HE`|2=L`;^jg<(ExdvU;B;=+g(>O05n54mmYyVwKVmxn2ThV}1Ew&QM zF#JpZ7?%o&;oU+3UPZ$ES2^BzNF8|vH`#l>m-&k>Gh-h86=-AK+Vb4@brGIlpDNLn zK2_uLBjJ5Qhc~TP@{$cCbHV%8Z49@0>N@2BNa&Cqmy={>FNWkL)@j`n&Kek&9eLs0OgLixqp0+{|0Yq^tgy z=adiddahxHV3hbt{wkTqh4^8_awU{iCA}4et>2o1Z!6QS`;yjq{C+}bVQOZJah-yt z>WlVpnrRvLqkQ|ecUOMYn~(SJDP={;YY@1;8%>#Pl!0*7;4={l&El$l6{@8>?lV&e za*pT8QTYB$wN*x3frt2o-HljcvMcvBv=Io<0fx8p(H^hab_>zwl^mpzF1%UnRB7AM z324fi{SfAJdT@42EJ@cqhI^^VL-z4yOe1i=JU!3w&6iRLOSwv%*7KvKN?KudR@`4CXQONgvrX+zg- z`=_h>o9=9sWQop0m!Niilr+%}{TGa39Os?I2l45O0db3F#`WeU=VkV}boY^sHlJ3)_M!~fJO8J;VZ9s!3cE2oEHnfl3aof;k1eMdL>zgkk z`N)2sXGdYUCE(4ro_|H)hvm!p4P4ZTX;8rw?8Fdj39FEi+$151(apnAxnD%g zD1Nk5FVZhRC?EkLx!xVQ3}&&ON#Pk>V+&j-)Cq2}+5XNm8gS_R0MSLow&Po8x>9t4lHo`sJH-)0pL8Yx-|b~3L(`wK&>Wl@0EKD za7wZ6i|Ujjc43)?@%;>+AfK3tMC9pMY*y1m7-wIvm$|VJQ?|b3CP)!&+_stLUO^?H zED*^7`*T^lNUHej@J}^kZ44|*Oq8sDR6J0R-f|&TjdD17sZc8d~-Fxf9|bQdczbtetV`cvBwz{be%G zpxNFr1NB~{(*mqNoiWj9DqXj(u*^|1{}wr3b<Rmu}&iYO$pq*{RrrE$#s< z1`@<5zq+%WUYvtYu!qFkxyC4eb&Q6t>Q}>50HEf0oRo62(`6tAyDgn<>?KD>X;~R? zQ*XT@4P9aO*`9x87)c|KZ)TmN*lR8$BCLdjF?!2gpoZB;(ZlM|IAi?9>||Ao~w%vrfZl;-(`JfNtQwK>dmKCkS~39;Hah z1#lS44CHTNJVq3@(s`Y0aNg1nLFb?lyb|ncYY_Y8pQm$X>Jj-pYt;UgWzI1pjO266`QL0D z3zy(qwJ~BD0*Vo5v&auSjgldt*oJT7j4^&>`87Quffqp*Wb9(eDsFxP2!mGrEPxz1 zGI;+et(qkN>1ZWOp(;yaoy8Ob)e~~5Bp%wUpK9yHcp(Z=0<=D833XUm=1T6-n#v%n z@k|T(-1^cgjnzgho29h)jsW!eR1hkIKnVlg(U8ZZUgSojf@vb9BE?^jzr=oTQ~)DOl`VY9W)~m$&p^o;k5095%R_!@gY$*DfA^@` z2})Zt?pzv>*+q zPxR(iaLwpG)NaVbIZbOq22+lZYtHLSf`BW_ZBaJ}ZaA0t0(Y6&t7!AT{gh{B$}b5L zn^;oylbZhPw)9TVO*57uOv`2a9|IdpZ#H0cEmE}5wyS5u?8{Ue(nBVu`Y5;&Csddpdve-s9 zWq99000GDNLeKYq_cUN!kQFQlu@+kjSk6BS#_V5H0t6nhSIQ^mJX6rVUBm{La#@hR z%X3!U46n6t=kSBpu6PW$m7OoHa}rC$uQjm5V%&PjqC7Es&&Ue_DcmclGT_*Q!zASa|<;I9X={^PM%8CC6WvJ3Z5A7a+M*`~4DYtD0DMeAq$ zjJWw&oJj7pS6(ync6opC+%xk|4zBvS$O%T0n+x5ji8fT5AOnC;am$9;P8h`~4d!Hy zU`Lf1DpWyha8aqr5bM@-)@p=aaw&*g;qh?N$-edV!>cAL7(q%C8$&`@TLL=YV`fFs z;6jPLBicezbO>9v=TIJ0s?$SruQr8=9r%u2q^?#!wsbJ7ideRb!E3lYHX3rO_~%@z zXF-(|L`aR>7y!K@?f132AHI6)L8ykyAg4qA&KJ{rOwWw`7fN%2ZOe~dF?bg{kNoF5 z83y(FP7Cj5pyz?A`VL>=NGqvrpxgV4D)BkSk4cVL3KUb_pHil>GZ!)w>Cq!+Fdyiq z5h7C-vrj0{b5_tflxC0XQ;QEhOHmGdRXr*QuXiJQb%0P@*Z$*bVB;>9u;C^MKSRUl z>YlZ2OP#v4vCDioXqLv;n$tibLKy$q*65oFqQ5mSHFy$QflgmXe<~19DvwVFEkZ!M zq6@1m8wby{@(!vijqcyoL17!VJ1(!ZD3{c56l@r+-h0|#>HHf^Mtq*QAoEkEHTg(t z1eot|bOBF?4CcUBx9uw9b30G>w87a&eQay;7w%+LtV(K^5pwU!WAaB=PeH+#o0{-x z5zReJMm9Gqf0Oq2h$Rc{oepra%MbYt`kKzvCKz)0aSBz$k8Q$VFpR4v<4ewjwdM}J z%MYUh4~>r9HJ<6@#G`n4d*>r(#MNuOvtVm`O#z1+JdGW+`&II>dM3pMIBaX;HF*=_ z6{Zw_zcXnRnEuh4G@E8sft4yYKI@#4db`0kwikIrsu~K_EVv5Iw;GdL#@gR17^y)K z(Bq`uB`*qVS{7p54L6h8Po_+N!4{|wR1!XIx+~-=iU(JOrf4)CS#&PV%UO<}FE}k6 zX9KEAO`8NIh4G6@+5b@c(fd^}4-04))Yx&@bbfk3m{>wjT zyY2MW-`U^)qCbmmQp}w$j6S_BgDDh#dEWsog?U4-ZCPZJUd9gX`#J{T!>2hX#S5SU zvm`Yvk^wkb{zrqc2j{<-smpe^E}bBp`hp82P!rVx#>IW}Dw5uaf8;h8Bq0v(G2{;SPt>bm-y! zdDgu~Zd@Sj>#(`i4K#0eJzby<@LspOBm3ta?nuf1nhrDSkdq@Wi=^gv)DuYpq;_W_ z6J*{V7+N$`bq}9C$s<&}`~6+i*zj|8Y&TT^keu@${p|Z~;rlrq^ZVcQvz;mp_)|7A zOu7>$i)M3ty#GM`VK(8%%jZTCX*2G)O>DiH{+I4bYdJGj9|J@E=MHdtOfboig5D&k z3X$HnLwOhxJ<;-o(#j#K+nSBF&w>)e6v79;ezF4heiMHrd2|YX!}6PbQ9nwCj)4P) zGO4YBZtKtJ6M8yv`E@nv=N8Bz1uipO5U-2g%|rZOeo{t527&Yjnvn4Cr8VK+j23zZ zu;O}rT~Wh#WZSC&?Eo0o#=jqfW1TFaPMH=06B;7pBNU6Y)ncdvMe{(8{$6P3 zl_Hs+3l<4m9ZgOe_OmY0swxoG*DXelY6g~B7eS@CD%?P9U=3KuBEc@0RK=Dd{Y^9?MhZ8NVU@S}+#3m=*FaB3RgLvOM-e2rL zD4GfcJ*}DI-va=3=C4O%W*HytdQtyeun}Vg*dAVKrs%JJ;bf2PTHjwj^0?h4^44eY zr=PK)7RnAXin989#Io^fE{>U4ROtE5LW5ElLt*%!y`XW53v?44BE!pl-Z$qd3nwVr)Zh+ zUMRDsW#lq{aC?xOcBzWLeHTTa;9`U(S59q?VagMW(i5WOWZsIn zeuL!{8E7kwB7EM_I7g(`!!pt2D$II{iZ^ZVP;t?qZrCePP^JM^xeIu6t59e=H#r|S zl%|D~(;d_%*lYh66kP_&a;3Qyd)EySwrguF0GuG{RlE9Idq*a|&PvVkIM#Mna!gXq zdxL9_3Y_0Yj9TK|wO8HxT3pr^yRDpLM_j`X(rxh33dN>XmzF#yH#iNVOBpNA8c%#3 zqRYA3*_U2O%7j1SFgDeSRH#zXP=5@0t(_n&FkttSaGV=vc(&nV_uc$$#F7|JMfB*b z1O$_Z{VyuIUH+QPgnutbgHL;!l(I-K-^%sqkjGf2V>Om`JPCo>EPLj7k;PIvsuZ`( zas3LPXD-08+FbFDm|=^7x75>|&X;@Yvw{4o_}Dw^*~Wsu`che~`qz4uky@TqPhk#W z8~I7`ZAqt3h#=DXoMhILNiCp9{7!ogz=7t&4RlXFnI^+HA{Nu!a+G_ape>uP zDUf1oalJCiLI)OzJo?dkCVQkbCI>qpq}}l&WqoiIkuS7@XH+DO`eC|4|FEp9nzMG@ zth8Ney(^dn!+Q{(=sMbPn z;CKN_54FOA*%ywn3q}6cI|^eNXEMD(th?-)jAqW(9`cIXL6E6sW2t_@jhIxK_gy6` zZPH=gh%uw=$zl;_%e-HwtNKV_7p`{N9sE(UZpnIXo^sdgcb7Z#cv|BleodViH$W3( zkr9lbTrR&s%%*2&uRi~=09b~YCg~2`Dv)csYg%q zPUr`2k6@A`YuZ!5O81&(_M6NVoG#+q8>lPF7 zSR;*JT|jcmtm9>O?d6eTFqPH!W>aLd_ceYMvWwfNl+G0%&p~%%mYik-j2{9U$)YyAqGh3$)8*v-6!PjT4sRh4T*Qc5z@{AlSH% z|6{E3$xz~Q3$>Ki+Vwn)=7ut7M_1{v zG)E<206qqp>d}Gk_5341r#YPE_lM|ZXLmZ;-<`Uag=#5%Mc1us!ygJ9Uy}@34w;kURG)4=9Iy%OKP20y0kW)4mc8v2V7;HD>K%CN8`3e==|Fbo&YTp^b@G*#TmSB#d=i zSNvi#x?h5zc>zxTsT6>dt(20SGqc$KrTwOrlkHm+{NXEZDu$rc%eE%7`J5XlE&0KF z@#Km$ydn&~n+Mo5fzW_8hH3Cidg9wwE1crEOX zh-T{xi-4UTGdKaD&jzembVo9}xQfvtQ4~J2qU}QIksA(_aTD}d@+Cf2J5M27<>ao` zM0t@y`2^rg-I2>TEW;vwQiOD%;F^2~K()N)OzYtabC3@XS>$LSnl%T3g~a{UuWU>V z{#08L2md*+bkt~dK37!PEiJ`e$#Z2Nund_u{)pGLrK<vKbBD*y zNW*_5z1D$)e>E%14n@$eh)O#H*3s;5k-TG8Ev2!YSU9lt<0!(``BX?=(Uw?H5*t_8 z;8mwn!ptjTd3DE6(QxjXEQ8gJ>7pe<+ziOe)fePUTQdWVwA6#WR?F@%TjKZ#Z!;n#JGs zmJi*vV@nh3<%c5k>W5dXiu^}9E8cTnSoGznU~|>nCFe?RI3v5uaz%L~sV`BBJuw!i z%`o&USCF4gTl|`rV&lvBRINUtpuNxbd%?r2Ro$id23$xlFw$eeegSuTL7aM*17ww6 zqYD6>KMI0F=&V%`yx9tk7vzdmylkuRnmH8xJ_#EGtC4v-2$IoZ;FW1@-kry22WKYCg3Kgf_h*TFxHi>bTv z6P_W1_7wZJ7DEIhuSo__>ul{CNh6(4bpC)*d)eskF{6U2K8C}8 z`6jNV2UcGLx;s?i**46A4I>?`qTS>O@3n5&t#<2SDn&q#8li)+xu)>z=)Lc2AD|NU zL-oHMG{^sT&}?k~qb@hCJso?<3Ez9G@&+zVrvyM(95)O&2Y+Gja@D>nIH;U5Jz@0D zSk+hVOU_ok8s@`v(I7L`E*4cH5Kw-2`Ya}o_+2^z{++aZxBd9se7f$+Ohz8qIKK{T z(@#d)kh3TF^-Mv={mH%`ldO1_((DG5^8N4~mhtuYJ9~)j>z2qfz_V_bncwr%c6?Lt zou0=Qt(2{iOE*)L6%G?qP4MLrCR31}kKCsD%;x-jzRaGNwQ(X-Z9UZimg;^#P5JOi zS{!N#l7$A)yNuK>Ivpuc!U86eOAGd969wpe?WLtQ85VDo<_vRx!cQ_sa7zKZ5MN%HWm&0TO7&e z*f-}P)zL#fj)}ehe85R{fw4Q~G>(*O*JcatR1X6g8TXBiYSH1=fauJdFfZ!V&byw^ z`CZAhwolC`PPaDp&96pE;MD*Y*t9=-2pR!5pPO(;RG7*hbB5U17tT~VgX z6Gb}%F^-OA;gtPGjt@`fgYqOW@q4?kgu^r!Dy^(FT`WNed4wVvbRaBdGtz|66an(B zVh@;z=Df$k6=@>^P*W@X+|U^@j0G4@7+RozusTx)G{k~dFvm?EW?0GK<~5R33jMbX zB*=u;Xxz3S(Znz<3JL(UQi9(Evw`s!k?F#s2tJpBRAVBxIi=N#O@+Sb)%UT}W_Z>9(iM|W9 z=-Q>3x|rsMDohkf%W3Wod`4D=XUBStX}U>K;k6wKutrZdw=X7ge`3)~_HG*VPYEwm?Ohvr&6!&FK>NsQEP~$*_I3+ybk5eYMnG_WX z8#)|>i3*czxLW|c5iDQ9giA?B`MzD6BCduLIw&=D}f6yE} zU_D_)WXSfU#~zn_>n(%n_O$*;P&{1xO{K56aBv3|4tM|vgUq7qkhAnZCI_~*6$@bb z0(CQfB%Cd_(9V}}@Wp{-ksw(xm_2GxD!THm3!=?ooE9vPMj|NT^09trF4djKL_C$E z6!60j)Ho`t&e0L|lB@n8a%V@W_7Lq+qCyBJ3dmPu{fT|w%8b^d!-?tH)nsf`@1Hiq;h`i**YxK}dJhtrlb@yT>DejODqZssD^OU6zQqvr$wsP~L^4^}T_kx)X_N-%jz znUKOXU4D&2f!J0%+{J$$9znNVESoOAz+nJ_nob7KIMaNItM9CI!n=^MugOw&UIW9# zd-o-9sxR5vUM)P8hZ^963Zh1|sbodI%t;g(9m`~ckfocjE?YZyZi!0=afjfHC`D^K zkP#$2otKzu=`{skah$npQtD5}v*mHPk=#_}%kUIi?%uL%QL635SIZu`NUHIh@p1sO zSkzuG)GIn2Wni#fD_G1DZ!ctR@gA?thMXz(R;jz3i?EJJv(b^Ms&89DiIg@S< zp8SQIf6XqIu4GQfQ+i6bShPR4?0L{9yyF_#J2$?VjkKzG%2zilbX36ZgKd6#rH|Q9 z59Km^@LDC*Jq>_g7T(T+A&5jOZ+HO`GuQ7gwHqFol}YFdTYh$iBptBJZTw)qG&+v+ z`YTKDB`Hjkn9YwxsPi1?sa?6AihQsQom_4mm?zkJt8B*)5ONk_`Gu>x@H{iZr|{o% zCD-{t0n&pE5RhgDXipmE!{;`fAMNw8@syuxdt(wBa*+@_U|UjIAXvgQbt=*?$DvHTF3p%84)kwT8PIG0$qt__Dv!SX@#L!N^m zIp=BLT=janWzD*&8JZU+{KSB9RiSsq!M592z5>=`$mawdf8t{Q?#-IVbMNsk#i4J~ z1(pQ%+>^wqdm=n@dATiHjaDXomPcA)KJf3@CL}$McNTkzHw{WYPoRp`)Dvxnvi17C zbiU7QKEhf4$M?9Ck`<0Tn*!3)xenb{`3Jh)J9_VyK?Kd6K3hg=ipf7Bp&U%kdTMWy&;eBUPAgJEgMH3fX^~o} zD`u1wWHbL{i2ZsnuiUaD$_wbz(f!R@>K|Z6{HG^r!`t>nM#cOlY0Shs zi|Xu1G#=G3vT}ZB>Bw$uW969`5#Gs zkM?ZrBRhQG|1yoE%K#a{_#qJ6fF4(OyC^==3@L`|0`K$7v}DSN#A`=pw@9~M&R8+! zr8rcn`5}TJT(B>SFsXrGqxNt9uSegveF`o~E(q(eSDvpg^6B#JyPx~rB*ckUmi7$G#kjC&8nCLuY}{Sz$JxzPix+E_=k${Uf$dfA2Ar^=yaje3!ad z;z{?wFrlvC)Gk6F-@GbT;*#%+Mo8~%Rl@Z3wQ(gY1Dox_tu#`xNcbS|Yz|pq@in~C zr)B|Q@6(cWV4mH~e0Zd-{s8(L9<#=WWxHHnYR8^x=Dgpuo}7xfH&U(zHYeR44Wt!; z1>HXy%)5M!$0=8FWuZfXo5=u`HkG;Nsl}VtXD_e&VY$>vW-stqzkaw9gJMCwri9+q zlURc&4SVpNd2ROlwU3NzJj5KNs^Gd~`Y#Cpvz6Tzl+mm@!uE-!HGCF!hJAbKLg(Mr zz8YcqpZiC~KdM;fJnqGaiLTn>5r~`3%VFmR7au3Y1h}{%&h2V+U{$0U~stJqZj*s*gB^s&7v+_SEZemwr$(CZQFLf ziAvkHZQHhO+s-`ob)Spwh`!hn>lf^~))>zm!;H3@32Px8_&(x5h+#mi86SEf$cIUq zS*Hc?GHPtI84Y>nkb+-IjYSH-1fUld8hEsIX0$s>E^ucBX=}HIxRhAWB){y7l}NBz z080m>wWG11UL2ef<|B5Vo6|C<#Xi))H4P^IIJ*bN~F0$}a=m6=$)M69?_QBdcF# z6u%-vC5g1-Va$m&(fWlxS?(qghs}IEt3lvf5bu}dJ(zFpppp)b6iX|Ym;vo&dcTA| z5;nB?Y_P$^uU@geRc(Z;bTun^N%j6f-|I9VK`A*JOtremBfupoqr=Y~Tq9t!3Msbg z#u@(7L;VVD!1;1^b)Bk*Lvw?1V zx9oDT??{5O@z=u3s<6`xZzIpqgh09!BGTx_LV_ejC2voTWrEF^WDKAP5gi5{#g;cJ z$*N?{c6J+*!<|#3Xb;(*yGUGe=YRFb1AAp5<2PtYRDC~_BrzKM%yY^<^sZVNV-4tA z?~+V=xY;~N(TwMlwRS`FZodf*n}eG&TW`};&4yx*qeYUaiv>f^m##4o{UQ>ybYkF? z(22*Ex`;825jnE7_y^#3iN3~iG~>ifNxp_C4lo0?Jj~HXnR`0Z-xXZ-)f?J#pbQp!?*ooF6Z!eC)^vtXQokPlk^#FHPR646DX3z}c zTks0U@D)tW5{a&zcoYDt(7VQ2TE1(;oNFRahRYV8%yxL{Ytx}sVtvXd@qQb>(01qImW6>B zlhDR^^Gnd-m}XNbIF?x8NUv*&=Q-ogRnavJF&)hvw)40WlE;nyexKZE_C!#C9v>I! z$MrOjM8d_|?Lx;FQrx1iV8BCjYrZQ@<|huMcm zNs;H_UI)CaF;vW^3Z3?ZF2sZ0%E)onKP&5E^vf2^TGx#_*~WKjI%yd3Me#Vmt3uL? zN@r={u3Zaj1ykemJFKV9X`)0ft*jVn9oXZrPbRyX6 z^n<`UAhakYIf}EN%TRNKjC*cu04G5lvIs$tL-boPRc3Q0 zxG&o5okTZ0Lr(>^015L7rr8xoW4_oDm<)j3wVtGLq2wNPx%wKN-^%)C*yhWaiLl$~ zN#cDSe&j64RHAPQc>Ilmz{y~~x~_5Y_^lM^_oag4EX^ByOa^}S zQvZx6nU@aw^lWi^F;DwgVna64%hg$3z9!H2&-NJ$ z>-l%I_s~&EXz-9xNpO12C{K^N_TK1vV^d|pV$fAvvhMqiFDEs-3kp#;pJlSdbgC%J z#66oiAnINt9miySz+%?{Unk)!)3zYaYC*mW#$9Q2;$45|NRdVp%QKFCva6JZX?*C5RA^ISQNw&w&elHr54$vQ^?J^(v zpw)27VyqXdQkZ!TP5XB4d*=*jQ8IeYBh;~sE2yi>+bLB#LzS6uG`L%)Xo0`hE@x z?HKB&u~TqlIjq=@L3tyB&Ju)#ZIR`*_}a5*nlpBz34YDNp-=j$Nt?lHV5+(~uIzE0 zswl!c|00BS3AZIHJBW*tia%H^QXABbXHli14T~YCW zTz8q6{$*H@{boy$89)aFllC@MXmb`)%BtAP9w(0r%tw0H!B3O);L-kqRNR`kK8jnM z0(Jj|D-f&eOIv&T2%qeCCP#OIH&GKaQ9{?6t3nWbbQj-_*NYD7>f!zV(Xf2l)Limd zr^%JTyQiB3GDWIau>tBk{8a+G(~UG?9Yr3u*L=0hEE1MoUItVpHi-5 zFPzMSm^t+DFmgjc^&xOKR%l9qx6*Qboh}*!{f@4z=9lBw#z@`vxwr$rZSju{GIqrX z_23tHJ^P0>Sh~P&lyiH@0x{TrNqD% zU035*Hyw-PwxkWI*iq6XK^Zuz?MFgp1m7jl^*qCsY?7>FSZd#R_)g;9=Z)RZX{5@g zT9)?TlT$GG`;tblKSOPDQDID;z3z zI2(W5MWs#)u-T}C*ZUn@w`QuXIx!H+8g?CcD35qt^;}@ymFHEWCk90IU4uLb{ite* z{4qzTiLkk#%?pdSnaFamo1r3@Ydf^bT6m7<=!24urRv!&ibsX`J;6LY*A@w5TwFOF7O?%R7+cEP?(yjAlYI3A#o%x=`odW*!_rHRWf;tg(v=%6CBgl?u3)>)G-mvW}v_`Ou)sMAl zASG42U7O}1iZ1sUiVh`zlFSa^dmH!XOZ9?VJs(QFTppx`niifSggmlp^+NFelC>&D zKNOJbJ^4@>ZnM20FPqN24Rn0B*2fB~mj#v0rZr99ZA**4vK6--h9kP-cAOAV-_xf; z>pxdk>iWiodT_$}-2V$6sT&eE0d}PvYK8-SpW`Lx!mC&xF7YlSJE2^@q?}W>eYecL zW_EfB}C9NAAbVD;)Q^jn(MUhvo= zN{f+xo(sI@v8UI(gj=?L>w$KtN@=}tPt|N^WiJ!NulzvtLMiXFV`@dyBGvi1)igSO zjPd%>deaAOwN$@ZLXXon!L0bkPA1rz>fSm|OhZTvh0KG@NumtlVgTe+a#h?hYX;z# zaMyNuqOF}N+avZq)dYr9cHhDJ)RH-BZil-*z#end?7Q+bC*YQ8c7{`$X3abq%~o9gBqSP z*g|zCINLF&^}!3Jm<5l|OnU9=8<+N%vbmW)4J=+R^->b5Kr9<{w%c~P=oxO=mHfQdIVm!Cj*7x1sMeywTbTrN98o*%~cr&xdsib=30z2+_=toTGOpZO12utl(04G>aOizcp4qCq7LkBA;b+5CE^|v`CvYwh$3ua zjim;2q7ZG=ss8M~S29I@FDhW?2-BYYPTu<_qN6YCI~ZA>(rU94vuk#LMqnP%k;b^y zab1aD`MQx%2LyYTW_Q}!ccT@0GP)k!d3cb@psC!;1otP16j!Jr)BR)#CnrzUZIQ5& zpz8XqtO}tJq)BbBO_{sxB8&fDi1h1+_qHNkWJ5{euH1v__fkYk?(wS~Bk77#%MQ04@KBJqmDV_p(38`DKhcylRW z`7E&5JWGTN;U&H5r3qlKWfpx8QCjVVdoJ)n;c9u@&ruF^J0;Q0i*H9#e%Ys+te~v- zvaO!KdN&}(WzOV@B014W5XpI1n>(G=#aM7-7F*wGr9Hz51iR*HgKcDp_KNE-zR>6VWV&rxN~#6S+uN$*`?BH?$&AUToCq1 zV4}usg#W2*Z(w6G=BUw;PN^TrNq#gT>y&7I#yl6lF~GL^h#wjzloL%o0$JNzJXlRb zGUiXJ-6$SkoCZ*!XI6jphsXhEYBW{t0tmaq^jrcNELBEA~;vUJ~O(@uF_j;82|9 z1rbp5umQHZ0a34j7E;%x(pGz=eBh1Xq>AipyQLLA%nS(9>O+~8=2DItA4+#st+R;{ zo(s;+O*mb?S#%vN*&-PM611X~+xURlKN_ygz9vA7Vm|$Zx$p|xT5Qj0<(jW1Edziu zhj9zWsqLEW=pRL}E|`CE7@Eq6_*b=cYZHm&G3`On$-NJ9wH}c6U&&TzE4$hK^;UIV zlHl`jVFe_db9w0GiT*mlgq=64_Ud-+)a!CBZK|~WRBcsL<^)~bk>Rq~_r?yicrd0D zqiwCLT6W)P9>+Ck^g6jARPmQSuT3joKt+VR4lnPEs*sK=+kQXkwkyom+DPvJdw@Fi znjLOHl_~zc@=#jFp+dx~{+CElHj`{|`h_ybz5t+8RPve%;d;BkLg;2I=KYa`>TBlh zfrPR8xb?I>_!?i(WS?!KfFM3PHn21(6%rt*72S+h8Ul$O05Pgk+dc!ac-VF-u3^q> zAkwC))8tBpg#aw({)uI{3o|6WkhRr?~i4qXV4FdMslEf&g0eBmp~s zzUtD>$8~{fS9ynOS%XX@NkvXr<;XyB!AxHBoFn-no%dMDI;7CpSBq&qJZeU|wAzWU7hUB^MyHZP}QSSEg)U@WFswxp-3ZYU6cK=GEHu z3l=d&G%o!@cB{c(_m;a-$P5=?IT@H-eItOBjETtxU3+NtQ8$5d;~X19J|M$PU)~pY zNk~NmuO?z5JY|PSeqWA_WI;E4se@!bN^P911A{n>JiTxmfW=jUXG}DSF_Vu>+5%vd z)Nv=3bO@02wj3c9#?!p!=F-tjS#&*}?iZSr>S5s4f3_a=H!Vr%c>Seh_SpKABtxU# z=v$*}>5x~BzbJACt%9)$NyOu(*SR`oYid~^O-iQ^)bgr)<%MK~$gr$I6fiR(nfe?a zAfd2dVDj|^?EX6jjs^cpS5wf5{~wMf8FsG1*8z5oIQdFT+K1}s`?)RR5|AW%P8(OB{W`;A%`LDFWgVw^>Qi$ass(oYMQsv~y`18G!q$I`1&b6^}JEcn)a=fv2q4zyXvt8ylsAevNchV9-^^s1~m!+O61xC-sOzGkP3sK$$9+I`t!(X=zNfs<;AW5zDL^IVsL z0%Y;hD2lDT-nlV{0Dy0wj|;OnC8(CKgOcY5KECLAOvwH=1>=O(jlpfy zVt^hW<3+pA=thgh$60lw1ZDy;gT)7_&5mi1rVQ0Rik{lij>vRin=|q>{(?28)6Akh zjkP2+m5y#j6Fn)9fTiRlBUQ*wxv!a(2^DD*&Kd?qydh?ov8;Pj&OW{gd~-E(_ca+` z7DjSXv}*b>^_s8APFOvlF4M5BqDJ!Q2_a|E%Q!RPYl*G?qR%ECr%3WRQPy0Kt)L0e z&TXOI;o#wTKe&?8#c_DHfkK-xgE|wfe~;Tm20x{?j&$^m^ONo>Xobi^BC(N7e!^1h z&Y?iQKE}B{N0_H@YvPlq_XnIv;ckMlECW1RCaw-JUUR^Md%1`U93GX< z#P8j0D4cNOS;cy&7h}+jR-z(oD-t1O&Ba3bO}t^>bs$eX29bVV`qr|wAt_frqXu_Q zVU>K|SJK8{PjwXCX%uO3ZKDWCIvJ-?u6BA4TZ zDe*)r694e9eeN@1cqDoeH!u5P)#fzqoV72TmS9YY$d$|ntSI|pT;@UNln;!s^uZBF zL&t$YEX{#XQ>(K`h5SIWn0xZ#nZig~ZGwSRXn@hM$!83JI`p{k%>N91RJ>A1$&MOr z7FqR20U3&*YT7dEYDGF$_FUrriZ43q{*4<+qKQGp#q`aNF75+d8 zA_e~EWtNS)Y+yPjhB6Dm3a`T#hhZrW46c+-2?ztGt#nRuG6&7H4t>hd6(%66!cd)Z z98v;}nrs2cm&((+YWe&PDo`)oht{1|%zx^YEVxVE-_5OL&d*QD{BMM#meTacREwsa~0r308}cYZ@T% zqO|6In$)L5G0B%%sUA&7QZ)7AHd*&N5(JGl;QdY>zcCL2J4&1rY$vc3l~LgV?zb z1wq}6plWqTS3OE$@}kIR8&$YJahna5OAk1f#a9AtYLEu8rDKrQ{it)jfk@_3~)5l;%q&1vw(eh{AbK>^E=CAQV!}>fq@^AGbcQYcjni!c+ z82VpqNAIZvw{@atRS)RR3M?UGiI9ze6oaV3d1N#u(V`By676q=q@W#xbmnnR3lN>3 zWp})i-UZ~}e+^!>TXfC#;W5B7C4MD<1Q9ty?n(pkNd6k(r!*OSt<%RoY83V3$r=Kh zHhdbRUUoxVs{nIPPqGMZ)2$Zv;03_o{_QeFOB?c)A(%yos@jYr3WuaxZwu~8WmxV(Q(n_rcKh=!)pRJ)z1~$vA zcY{-1u5=MWAzmh9E&09Jswb}@-o8Vl`j|vtK`zm4j}4~js+n3StE1>-00)+rvrP?{ z6snkbCvGIuOBqlmi-WX)c0RpvLP^7Ca#NWAnNT}QGkd0`psPuNbC@t)rGy7w;;bh- zjNBd|5BToAV<>1NPEfAH1b`bxmc}BZ%Ht(SR))+ck6D{bFnDmc zxE6_CN6-Sk4G*2CSQp9zXc)CqAuMt?^eSUH_&YC@CM@G)rrp-;M>NmYm}GN3j-7LK z0l!3#@xAR(=xz{ZRjSE7mUr#Xx3Fz04!bFLw1amw1?GE|3n|WZpFmoep%=|gX3$A* zke}yIto-|J80J7mP)Qj0S1zlbh-+)_J1+Jsz%9iWt=t&X35a_F zGPXTu?{9{7$~LzJhkzW%@8Zl{I=Or%tp}>`QCan=#c0Z4r4!rLNnIUMbA|kRJ0k=8 zmymtN@-b*%G5vOSz?}RdSi=oIu*w>=AP@}4F6B;49_wG$wCnAa6{kHn!MWqi!Y&b?sv7Q{o|ZLy5y)31WKDE!Ws2-&btYc5 zGj5lfF>9GOgO$IFwPjD(#7Nsdt=c-LnWpaAFql-Qk~NHy0E=0TGMzFqOB(M_y^V

;h1gR?q_*;sU1zt$H6w%bou+NI&>nVd(Aa^|ZRU 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 tPNu)27ixmnEesU$Q95 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¨uSYo4BN*({r7tphJ#>p= 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 )7GsF|qEjnI)Sq$D%RYoYg)j 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 R3mX?VH#{Y!grX$;{{R~9C)5A{ diff --git a/doc/docsrc/Makefile.am b/doc/docsrc/Makefile.am index 394a195f7..9c75b0c50 100644 --- a/doc/docsrc/Makefile.am +++ b/doc/docsrc/Makefile.am @@ -8,6 +8,6 @@ regen: $(XELATEX) $(XELATEX_FLAGS) -no-pdf $(TEXSRC) $(XELATEX) $(XELATEX_FLAGS) $(TEXSRC) -EXTRA_DIST = $(srcdir)/*.tex +EXTRA_DIST = $(srcdir)/*.tex $(srcdir)/*.inc CLEANFILES = *.*~ *.aux *.dvi *.log *.out *.toc diff --git a/doc/docsrc/asn1c-usage.tex b/doc/docsrc/asn1c-usage.tex index ed93bce5d..1b91adcdc 100644 --- a/doc/docsrc/asn1c-usage.tex +++ b/doc/docsrc/asn1c-usage.tex @@ -15,6 +15,8 @@ \usepackage{fancyhdr} \usepackage{fancyref} \usepackage{longtable} +\usepackage{array} +\usepackage{enumitem} \usepackage{booktabs} \usepackage{url} \usepackage{xcolor} @@ -32,7 +34,6 @@ \setmonofont[Scale=1.05]{\courierFont} \setmathfont[Scale=1.05]{Cambria Math} - \makeatletter %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands. @@ -69,11 +70,15 @@ morecomment=[n]{/*}{*/} } +\lstnewenvironment{signature}[1][]{\lstset{style=listingStyle,language=C,xleftmargin=0pt,#1}}{} +\lstnewenvironment{example}[1][]{\lstset{style=listingStyle,language=C,basicstyle=\scriptsize\listingfont,#1}}{} \lstnewenvironment{codesample}[1][]{\lstset{style=listingStyle,language=C,#1}}{} \lstnewenvironment{bash}[1][]{\lstset{style=listingStyle,language=bash,#1}}{} \lstnewenvironment{asn}[1][]{\lstset{style=listingStyle,language=asn1,#1}}{} -\newcommand{\code}[1]{\lstinline{#1}} +\newcommand{\api}[2]{\hyperref[#1]{\code{#2}}} +\newcommand{\seealso}[2]{\api{#1}{#2} at page \pageref{#1}} +\newcommand{\code}[1]{\texttt{\textbf{\lstinline{#1}}}} \newcommand{\cmd}[1]{\texttt{#1}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands. @@ -94,6 +99,7 @@ xetex ]{hyperref} + \makeatother \usepackage{babel} @@ -183,7 +189,7 @@ \section{A “Rectangle” Encoder} memory and encodes it using BER and XER encoding rules. Let's name the file \textbf{main.c}: -\begin{codesample}[basicstyle=\scriptsize\listingfont] +\begin{example} #include #include #include /* Rectangle ASN.1 type */ @@ -239,7 +245,7 @@ \section{A “Rectangle” Encoder} return 0; /* Encoding finished successfully */ } -\end{codesample} +\end{example} \item Compile all files together using C compiler (varies by platform): \begin{bash} @@ -280,7 +286,7 @@ \section{\label{sec:A-Rectangle-Decoder}A “Rectangle” Decoder} it as it were a BER-encoded Rectangle type, and prints out the text (XML) representation of the Rectangle type. Let's name the file \textbf{main.c}: -\begin{codesample}[basicstyle=\scriptsize\listingfont] +\begin{example} #include #include #include /* Rectangle ASN.1 type */ @@ -328,7 +334,7 @@ \section{\label{sec:A-Rectangle-Decoder}A “Rectangle” Decoder} return 0; /* Decoding finished successfully */ } -\end{codesample} +\end{example} \item Compile all files together using C compiler (varies by platform): \begin{bash} @@ -363,7 +369,7 @@ \section{Adding constraints to a “Rectangle”} by placing the following snippet of code \emph{before} encoding and/or \emph{after} decoding the Rectangle type: -\begin{codesample}[basicstyle=\scriptsize\listingfont] +\begin{example} int ret; /* Return value */ char errbuf[128]; /* Buffer for error message */ size_t errlen = sizeof(errbuf); /* Size of the buffer */ @@ -378,7 +384,7 @@ \section{Adding constraints to a “Rectangle”} } /* ... here goes the Rectangle %\emph{encoding}% code ... */ -\end{codesample} +\end{example} \item Compile the resulting C code as shown in the previous chapters. \item Test the constraints checking code by assigning integer value 101 to the \textbf{.height} member of the Rectangle structure, or @@ -563,30 +569,536 @@ \section{\label{sec:Command-line-options}Command line options} \chapter{API reference} -\section{ASN\_STRUCT\_FREE} -\section{ASN\_STRUCT\_FREE\_CONTENTS\_ONLY} -\section{ASN\_STRUCT\_RESET} -\section{asn\_check\_constraints} -\section{asn\_decode} -\section{asn\_encode} +The functions desribed in this chapter are to be used by the application +programmer. These functions won't likely change change or get removed until +the next major release. + +The API calls not listed here are not public and should not be used by the +application level code. + +\clearpage{} +\section{\label{sec:ASN_STRUCT_FREE}ASN\_STRUCT\_FREE() macro} + +\subsection*{Synopsis} + +\begin{signature} +#define ASN_STRUCT_FREE(type_descriptor, struct_ptr) +\end{signature} + +\subsection*{Description} + +Recursively releases memory occupied by the structure +described by the \code{type\_descriptor} and referred to +by the \code{struct\_ptr} pointer. + +Does nothing when \code{struct\_ptr} is NULL. + +\subsection*{Return values} +Does not return a value. + +\subsection*{Example} + +\begin{example} +Rectangle_t *rect = ...; +ASN_STRUCT_FREE(asn_DEF_Rectangle, rect); +\end{example} + +\section{\label{sec:ASN_STRUCT_RESET}ASN\_STRUCT\_RESET() macro} + +\subsection*{Synopsis} + +\begin{signature} +#define ASN_STRUCT_RESET(type_descriptor, struct_ptr) +\end{signature} + +\subsection*{Description} + +Recursively releases memory occupied by the members of the structure +described by the \code{type\_descriptor} and referred to +by the \code{struct\_ptr} pointer. + +Does not release the memory pointed to by \code{struct\_ptr} itself. +Instead it clears the memory block by filling it out with 0 bytes. + +Does nothing when \code{struct\_ptr} is NULL. + +\subsection*{Return values} +Does not return a value. + +\subsection*{Example} + +\begin{example} +struct my_figure { /* The custom structure */ + int flags; /* */ + /* The type is generated by the ASN.1 compiler */ + Rectangle_t rect; + /* other members of the structure */ +}; + +struct my_figure *fig = ...; +ASN_STRUCT_RESET(asn_DEF_Rectangle, &fig->rect); +\end{example} + +\section{asn\_check\_constraints()} + +\subsection*{Synopsis} + +\begin{signature} +int asn_check_constraints( + const asn_TYPE_descriptor_t *type_descriptor, + const void *struct_ptr, /* Target language's structure */ + char *errbuf, /* Returned error description */ + size_t *errlen /* Length of the error description */ +); +\end{signature} + +\subsection*{Description} + +Validate the structure according to the ASN.1 constraints. +If errbuf and errlen are given, they shall be pointing to the appropriate +buffer space and its length before calling this function. Alternatively, +they could be passed as NULLs. If constraints validation fails, +errlen will contain the actual number of bytes used in errbuf +to encode an error message, properly 0-terminated. + +\subsection*{Return values} + +This function returns 0 in case all ASN.1 constraints are met +and -1 if one or more ASN.1 constraints were violated. + +\subsection*{Example} + +\begin{codesample}[basicstyle=\scriptsize\listingfont] +Rectangle_t *rect = ...; + +char errbuf[128]; /* Buffer for error message */ +size_t errlen = sizeof(errbuf); /* Size of the buffer */ + +int ret = asn_check_constraints(&asn_DEF_Rectangle, rectangle, errbuf, &errlen); +/* assert(errlen < sizeof(errbuf)); // Guaranteed: you may rely on that */ +if(ret) { + fprintf(stderr, "Constraint validation failed: %\%%s\n", errbuf); +} +\end{codesample} + +\section{\label{sec:asn_decode}asn\_decode()} + +\subsection*{Synopsis} +\begin{signature} +asn_dec_rval_t asn_decode( + const asn_codec_ctx_t *opt_codec_parameters, + enum asn_transfer_syntax syntax, + const asn_TYPE_descriptor_t *type_descriptor, + void **struct_ptr_ptr,/* Pointer to a target structure's ptr */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of that buffer */ +); +\end{signature} + +\subsection*{Description} + +The \code{asn\_decode()} function parses the data given by the \code{buffer} +and \code{size} arguments. The encoding rules are specified in the \code{syntax} +argument and the type to be decoded is specified by the \code{type_descriptor}. + +The \code{struct_ptr_ptr} must point to the memory location which contains the +pointer to the structure being decoded. Initially the \code{*struct_ptr_ptr} +pointer is typically set to 0. In that case, \code{asn\_decode()} will +dynamically allocate memory for the structure and its members as needed +during the parsing. +If \code{*struct\_ptr\_ptr} already points to some memory, the \code{asn\_decode()} +will allocate the subsequent members as needed during the parsing. + +\subsection*{Return values} + +\input{asn_dec_rval.inc} + +The \code{.consumed} value is in bytes, even for PER decoding. +For PER, use \code{uper\_decode()} in case you need to get +the number of consumed bits. + +\subsection*{Restartability} + +Some transfer syntax parsers (such as ATS\_BER) support restartability. + +That means that in case the buffer has less data than expected, +the \code{asn_decode()} will process whatever is available and ask for more +data to be provided using the RC\_WMORE return \code{.code}. + +Note that in the RC\_WMORE case the decoder may have processed less data than +it is available in the buffer, which means that you must be able to arrange +the next buffer to contain the unprocessed part of the previous buffer. + +The \code{RC_WMORE} code may still be returned by parser not supporting +restartabilty. In such cases, the partially decoded structure shall be +discarded and the next invocation should use the extended buffer to parse +from the very beginning. + +\subsection*{Example} + +\begin{example} +Rectangle_t *%$\underbracket{\textrm{\listingfont rect = 0}}$%; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */ +asn_dec_rval_t rval; +rval = asn_decode(0, ATS_BER, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size); +switch(rval.code) { +case RC_OK: + asn_fprint(stdout, &asn_DEF_Rectangle, rect); + ASN_STRUCT_FREE(&asn_DEF_Rectangle, rect); + break; +case RC_WMORE: +case RC_FAIL: +default: + ASN_STRUCT_FREE(&asn_DEF_Rectangle, rect); + break; +} +\end{example} + +\subsection*{See also} +\seealso{sec:asn_fprint}{asn_fprint()}. + +\section{\label{sec:asn_encode}asn\_encode()} \section{asn\_encode\_to\_buffer} + +\subsection*{Example} +\begin{example} +uint8_t buffer[128]; +size_t buf_size = sizeof(buffer); +asn_enc_rval_t er; +er = asn_encode_to_buffer(0, ATS_DER, &asn_DEF_Rectangle, buffer, buf_size); +if(er.encoded > buf_size) { + fprintf(stderr, "Buffer of size %\%%zu is too small for %\%%s, need %\%%zu\n", + buf_size, asn_DEF_Rectangle.name, er.encoded); +} +\end{example} + \section{asn\_encode\_to\_new\_buffer} -\section{asn\_fprint} -\section{ber\_decode} -\section{der\_encode} + +\subsection*{Example} +\begin{example} +asn_encode_to_new_buffer_result_t res; +res = asn_encode_to_new_buffer(0, ATS_DER, &asn_DEF_Rectangle, buffer, buf_size); +if(res.buffer) { + /* Encoded successfully. */ + free(res.buffer); +} else { + fprintf(stderr, "Failed to encode %\%%s, estimated %\%%zd bytes\n", + asn_DEF_Rectangle.name, res.result.encoded); +} +\end{example} + +\section{\label{sec:asn_fprint}asn\_fprint()} + +\subsection*{Synopsis} +\begin{signature} +int asn_fprint(FILE *stream, /* Destination file */ + const asn_TYPE_descriptor_t *type_descriptor, + const void *struct_ptr /* Structure to be printed */ +); +\end{signature} + +\subsection*{Description} + +The \code{asn_fprint()} function prints human readable description +of the target language's structure into the file stream specified by +\code{stream} pointer. + +The output format does not conform to any standard. + +The \code{asn_fprint()} function attempts to +produce a valid output even for incomplete and broken structures, which +makes it more suitable for debugging complex cases than +\api{sec:xer_fprint}{xer_fprint()}. + +\subsection*{Return values} + +\begin{tabular}[h!]{rl} +0 & Output was successfully made \\ +-1 & Error printing out the structure +\end{tabular} + +\subsection*{Example} +\begin{example} +Rectangle_t *rect = ...; +asn_fprint(stdout, &asn_DEF_Rectangle, rect); +\end{example} + +\subsection*{See also} +\seealso{sec:xer_fprint}{xer_fprint()}. + +\section{\label{sec:asn_random_fill}asn\_random\_fill()} + +\subsection*{Synopsis} +\begin{signature} +int asn_random_fill( + const asn_TYPE_descriptor_t *type_descriptor, + void **struct_ptr_ptr,/* Pointer to a target structure's ptr */ + size_t approx_max_length_limit +); +\end{signature} + +\subsection*{Description} + +Create or initialize a structure with random contents, according to the type +specification and optional member constraints. + +For best results, the code should be generated with \cmd{-gen-PER} option +to \cmd{asn1c}, that will make it follow the PER visible constraints and +sometimes break out of extensible contstraints' ranges. + +The \code{asn_random_fill()} function has a bias to generate edge case +values. This property makes it useful for debugging the application level +code and for security testing, as random data can be a good seed to fuzzing. + +The \code{approx_max_length_limit} specifies the approximate limit of the +resulting structure in units closely resembling bytes. The actual result +might be several times larger or smaller than the given length limit. +A rule of thumb way to select the initial value for this parameter +is to take a typical structure and use twice its DER output size. + +\subsection*{Return values} + +\begin{tabular}[h!]{rl} +0 & Structure was properly initialized with random data \\ +-1 & Failure to initialize the structure with random data +\end{tabular} + +\clearpage{} +\section{\label{sec:ber_decode}ber\_decode()} + +\subsection*{Synopsis} +\begin{signature} +asn_dec_rval_t ber_decode( + const asn_codec_ctx_t *opt_codec_ctx, + const asn_TYPE_descriptor_t *type_descriptor, + void **struct_ptr_ptr,/* Pointer to a target structure's ptr */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of that buffer */ +); +\end{signature} + +\subsection*{Description} + +Decode BER, DER and CER data +(Basic Encoding Rules, Distinguished Encoding Rules, Canonical Encoding Rules), +as defined by ITU-T~X.690. + +DER and CER are different subsets of BER. + +Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_BER)}. + +\subsection*{Return values} +\input{asn_dec_rval.inc} + +The \code{.consumed} value is in bytes. + +\subsection*{Restartability} + +The \code{ber_decode()} function is restartable (stream-oriented). +That means that in case the buffer has less data than expected, +the decoder will process whatever is available and ask for more data +to be provided using the RC\_WMORE return \code{.code}. + +Note that in the RC\_WMORE case the decoder may have processed less data than +it is available in the buffer, which means that you must be able to arrange +the next buffer to contain the unprocessed part of the previous buffer. + +\subsection*{See also} +\seealso{sec:der_encode}{der_encode()}. + +\section{\label{sec:der_encode}der\_encode} + +\subsection*{See also} +\seealso{sec:ber_decode}{ber_decode()}, +\seealso{sec:asn_decode}{asn_decode(ATS_BER)}. + \section{der\_encode\_to\_buffer} -\section{oer\_decode} -\section{oer\_encode} + +\clearpage{} +\section{\label{sec:oer_decode}oer\_decode()} + +\subsection*{Synopsis} +\begin{signature} +asn_dec_rval_t oer_decode( + const asn_codec_ctx_t *opt_codec_ctx, + const asn_TYPE_descriptor_t *type_descriptor, + void **struct_ptr_ptr,/* Pointer to a target structure's ptr */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of that buffer */ +); +\end{signature} + +\subsection*{Description} + +Decode the BASIC-OER and CANONICAL-OER (Octet Encoding Rules), +as defined by ITU-T~X.696. + +Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_BASIC_OER)}. + +\subsection*{Return values} +\input{asn_dec_rval.inc} + +The \code{.consumed} value is in bytes. + +\subsection*{Restartability} + +The \code{oer_decode()} function is restartable (stream-oriented). +That means that in case the buffer has less data than expected, +the decoder will process whatever is available and ask for more data +to be provided using the RC\_WMORE return \code{.code}. + +Note that in the RC\_WMORE case the decoder may have processed less data than +it is available in the buffer, which means that you must be able to arrange +the next buffer to contain the unprocessed part of the previous buffer. + +\section{\label{sec:oer_encode}oer\_encode} \section{oer\_encode\_to\_buffer} -\section{uper\_decode} -\section{uper\_decode\_complete} -\section{uper\_encode} + +\clearpage{} +\section{\label{sec:uper_decode}uper\_decode()} + +\subsection*{Synopsis} + +\begin{signature} +asn_dec_rval_t uper_decode( + const asn_codec_ctx_t *opt_codec_ctx, + const asn_TYPE_descriptor_t *type_descriptor, + void **struct_ptr_ptr,/* Pointer to a target structure's ptr */ + const void *buffer, /* Data to be decoded */ + size_t size, /* Size of the input data buffer, bytes */ + int skip_bits, /* Number of unused leading bits, 0..7 */ + int unused_bits /* Number of unused tailing bits, 0..7 */ +); +\end{signature} + +\subsection*{Description} + +Decode the Unaligned BASIC or CANONICAL PER (Packed Encoding Rules), +as defined by ITU-T~X.691 + +Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_UNALIGNED_BASIC_PER)}. + +\subsection*{Return values} +\input{asn_dec_rval.inc} +Note that the \code{.consumed} value is in bits. +Use \code{(.consumed+7)/8} to convert to bytes. + +\subsection*{Restartability} +The \code{uper_decode()} function is not restartable. +Failures are final. + +\section{uper\_decode\_complete()} + +\subsection*{Synopsis} + +\begin{signature} +asn_dec_rval_t uper_decode_complete( + const asn_codec_ctx_t *opt_codec_ctx, + const asn_TYPE_descriptor_t *type_descriptor, + void **struct_ptr_ptr,/* Pointer to a target structure's ptr */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of data buffer */ +); +\end{signature} + +\subsection*{Description} + +Decode a ``Production of a complete encoding'', +according to ITU-T~X.691 (08/2015) \#11.1. + +Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_UNALIGNED_BASIC_PER)}. + +\subsection*{Return values} +\input{asn_dec_rval.inc} + +The the \code{.consumed} value is returned in bytes. + +\subsection*{Restartability} +The \code{uper_decode_complete()} function is not restartable. +Failures are final. + +The complete encoding contains at least one byte, so on success +\code{.consumed} will be greater or equal to 1. + +\section{\label{sec:uper_encode}uper\_encode} \section{uper\_encode\_to\_buffer} \section{uper\_encode\_to\_new\_buffer} -\section{xer\_decode} -\section{xer\_encode} -\section{xer\_equivalent} -\section{xer\_fprint} +\clearpage{} +\section{\label{sec:xer_decode}xer\_decode()} + +\subsection*{Synopsis} + +\begin{signature} +asn_dec_rval_t xer_decode( + const asn_codec_ctx_t *opt_codec_ctx, + const asn_TYPE_descriptor_t *type_descriptor, + void **struct_ptr_ptr,/* Pointer to a target structure's ptr */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of data buffer */ +); +\end{signature} + +\subsection*{Description} + +Decode the BASIC-XER and CANONICAL-XER (XML Encoding Rules) encoding, +as defined by ITU-T~X.693. + +Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_BASIC_XER)}. + +\subsection*{Return values} +\input{asn_dec_rval.inc} + +The \code{.consumed} value is in bytes. + +\subsection*{Restartability} + +The \code{xer_decode()} function is restartable (stream-oriented). +That means that in case the buffer has less data than expected, +the decoder will process whatever is available and ask for more data +to be provided using the RC\_WMORE return \code{.code}. + +Note that in the RC\_WMORE case the decoder may have processed less data than +it is available in the buffer, which means that you must be able to arrange +the next buffer to contain the unprocessed part of the previous buffer. + +\section{\label{sec:xer_encode}xer\_encode} +\section{\label{sec:xer_fprint}xer\_fprint()} + +\subsection*{Synopsis} +\begin{signature} +int xer_fprint(FILE *stream, /* Destination file */ + const asn_TYPE_descriptor_t *type_descriptor, + const void *struct_ptr /* Structure to be printed */ +); +\end{signature} + +\subsection*{Description} + +The \code{xer_fprint()} function outputs XML-based serialization +of the given structure into the file stream specified by +\code{stream} pointer. + +The output conforms to BASIC-XER, as defined by ITU-T~X.693. + +\subsection*{Return values} + +\begin{tabular}[h!]{rl} +0 & XML output was successfully made \\ +-1 & Error printing out the structure +\end{tabular} + +\noindent{}Since the \code{xer_fprint()} function attempts to produce a conforming output, +it will likely break on partial structures by writing incomplete data +to the output stream and returning -1. This makes it less suitable for +debugging complex cases than \api{sec:asn_fprint}{asn_fprint()}. + +\subsection*{Example} +\begin{example} +Rectangle_t *rect = ...; +xer_fprint(stdout, &asn_DEF_Rectangle, rect); +\end{example} + +\subsection*{See also} +\seealso{sec:asn_fprint}{asn_fprint()}. \chapter{API usage examples} @@ -608,7 +1120,7 @@ \chapter{API usage examples} \end{codesample} This code defines a \emph{rect} pointer which points to the Rectangle\_t structure which needs to be freed. The second line uses a generic -\code{ASN\_STRUCT\_FREE()} macro which invokes the memory deallocation routine +\api{sec:ASN_STRUCT_FREE}{ASN\_STRUCT\_FREE()} macro which invokes the memory deallocation routine created specifically for this Rectangle\_t structure. The \emph{asn\_DEF\_Rectangle} is the type descriptor which holds a collection of routines and operations defined for the Rectangle\_t structure. @@ -618,7 +1130,7 @@ \section{\label{sec:Generic-Encoding}Generic encoders and decoders} Before we start describing specific encoders and decoders, let's step back a little and check out a simple high level way. -The asn1c runtime supplies (see \emph{asn\_application.h}) two sets of high level functions, \emph{asn\_encode*} and \emph{asn\_decode*}, which take a transfer syntax selector as the argument. The transfer syntax selector is defined as this: +The asn1c runtime supplies (see \emph{asn\_application.h}) two sets of high level functions, \api{sec:asn_encode}{asn_encode*} and \api{sec:asn_decode}{asn_decode*}, which take a transfer syntax selector as an argument. The transfer syntax selector is defined as this: \begin{codesample}[basicstyle=\scriptsize\listingfont] /* @@ -675,12 +1187,14 @@ \section{\label{sec:Decoding-BER}Decoding BER} \emph{The ASN.1 compiler provides the generic BER decoder which is capable of decoding BER, CER and DER encoded data.} -The decoder is restartable (stream-oriented), which means that in -case the buffer has less data than it is expected, the decoder will -process whatever there is available and ask for more data to be provided. -Please note that the decoder may actually process less data than it -was given in the buffer, which means that you must be able to make -the next buffer contain the unprocessed part of the previous buffer. +The decoder is restartable (stream-oriented). +That means that in case the buffer has less data than expected, +the decoder will process whatever is available and ask for more data +to be provided using the RC\_WMORE return \code{.code}. + +Note that in the RC\_WMORE case the decoder may have processed less data than +it is available in the buffer, which means that you must be able to arrange +the next buffer to contain the unprocessed part of the previous buffer. Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes. \begin{itemize} diff --git a/doc/docsrc/asn_dec_rval.inc b/doc/docsrc/asn_dec_rval.inc index 82b855135..06ece1957 100644 --- a/doc/docsrc/asn_dec_rval.inc +++ b/doc/docsrc/asn_dec_rval.inc @@ -1,3 +1,10 @@ + +Upon unsuccessful termination, the \code{*struct_ptr_ptr} +may contain partially decoded data. This data may be useful for debugging +(such as by using \code{asn_fprint()}). +Don't forget to discard the unused partially decoded data by calling +\code{ASN_STRUCT_FREE()} or \code{ASN_STRUCT_RESET()}. + The return value is returned in a compound structure: \begin{codesample} typedef struct { @@ -12,11 +19,11 @@ typedef struct { The \code{.code} member specifies the decoding outcome. -\begin{description}[labelindent=\parindent] -\item[RC\_OK] Decoded successfully and completely -\item[RC\_WMORE] More data expected, call again -\item[RC\_FAIL] Failed for good -\end{description} +\begin{tabular}[h!]{ll} +\texttt{RC\_OK} & Decoded successfully and completely \\ +\texttt{RC\_WMORE} & More data expected, call again \\ +\texttt{RC\_FAIL} & Failed for good +\end{tabular} The \code{.consumed} member specifies the amount of \code{buffer} data that was used during parsing, irrespectively of the \code{.code}. From 5f4dbb751abf333bd0d5f0d842893fcea937f65e Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sat, 11 Nov 2017 14:52:11 -0800 Subject: [PATCH 21/41] earlier detection of unknown -pdu=Type --- libasn1compiler/asn1c_save.c | 187 +++++++++++++++++++++-------------- 1 file changed, 114 insertions(+), 73 deletions(-) diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c index 5fe1b3733..f302ceb4f 100644 --- a/libasn1compiler/asn1c_save.c +++ b/libasn1compiler/asn1c_save.c @@ -32,18 +32,26 @@ static size_t safe_fwrite(const void *ptr, size_t size, size_t nitems, FILE *str ? safe_fprintf(fp_h, "#include \"%s\"\n", s) \ : safe_fprintf(fp_h, "#include <%s>\n", s)) \ +enum include_type_result { + TI_NOT_INCLUDED, + TI_INCLUDED_FROM_BULK, + TI_INCLUDED_FROM_CMDLINE +}; + static int asn1c_dump_streams(arg_t *arg, asn1c_fdeps_t *, int, char **); static int asn1c_print_streams(arg_t *arg); static int asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *, int, char **); static int asn1c_copy_over(arg_t *arg, char *path); static int identical_files(const char *fname1, const char *fname2); static int need_to_generate_pdu_collection(arg_t *arg); +static abuf *generate_pdu_collection(arg_t *arg); static int generate_pdu_collection_file(arg_t *arg); static int generate_preamble(arg_t *, FILE *, int optc, char **argv); -static int include_type_to_pdu_collection(arg_t *arg); -static void pdu_collection_print_unused_types(arg_t *arg); +static enum include_type_result include_type_to_pdu_collection(arg_t *arg); +static int pdu_collection_has_unused_types(arg_t *arg); static const char *generate_pdu_C_definition(void); static void asn1c__cleanup_pdu_type(void); +static int asn1c__pdu_type_lookup(const char *typename); static int asn1c__save_library_makefile(arg_t *arg, const asn1c_fdeps_t *deps, const char *datadir, const char *makefile_name) { @@ -211,12 +219,29 @@ asn1c__save_example_makefile(arg_t *arg, const asn1c_fdeps_t *deps, return 0; } +static int +can_generate_pdu_collection(arg_t *arg) { + abuf *buf = generate_pdu_collection(arg); + if(!buf) { + return -1; + } + abuf_free(buf); + return 0; +} + int asn1c_save_compiled_output(arg_t *arg, const char *datadir, int argc, int optc, char **argv) { asn1c_fdeps_t *deps = 0; int ret = -1; + /* + * Early check that we can properly generate PDU collection. + */ + if(can_generate_pdu_collection(arg) == -1) { + return -1; + } + do { asn1p_module_t *mod; @@ -570,63 +595,79 @@ asn1c_copy_over(arg_t *arg, char *path) { static int generate_pdu_collection_file(arg_t *arg) { - asn1p_module_t *mod; - FILE *fp; + abuf *buf = generate_pdu_collection(arg); + assert(buf); - fp = asn1c_open_file("pdu_collection", ".c", 0); + FILE *fp = asn1c_open_file("pdu_collection", ".c", 0); if(fp == NULL) { perror("pdu_collection.c"); return -1; } + safe_fwrite(buf->buffer, buf->length, 1, fp); + fclose(fp); - safe_fprintf(fp, - "/*\n" - " * Generated by asn1c-" VERSION " (http://lionet.info/asn1c)\n" - " */\n\n"); - safe_fprintf(fp, "struct asn_TYPE_descriptor_s;\t" - "/* Forward declaration */\n\n"); - - TQ_FOR(mod, &(arg->asn->modules), mod_next) { - TQ_FOR(arg->expr, &(mod->members), next) { - if(!include_type_to_pdu_collection(arg)) - continue; - safe_fprintf(fp, "extern struct asn_TYPE_descriptor_s " - "asn_DEF_%s;\n", - asn1c_make_identifier(0, arg->expr, NULL)); - } - } + safe_fprintf(stderr, "Generated pdu_collection.c\n"); + return 0; +} - safe_fprintf(fp, "\n\n"); - safe_fprintf(fp, "struct asn_TYPE_descriptor_s *asn_pdu_collection[] = {\n"); - TQ_FOR(mod, &(arg->asn->modules), mod_next) { - int mod_printed = 0; - TQ_FOR(arg->expr, &(mod->members), next) { - if(!include_type_to_pdu_collection(arg)) - continue; - if(!mod_printed++) - safe_fprintf(fp, "\t/* From module %s in %s */\n", - arg->expr->module->ModuleName, - arg->expr->module->source_file_name); - safe_fprintf(fp, "\t&asn_DEF_%s,\t\n", - asn1c_make_identifier(0, arg->expr, NULL)); - } - } +static abuf * +generate_pdu_collection(arg_t *arg) { + asn1p_module_t *mod; + abuf *buf = abuf_new(); + + abuf_printf(buf, "/*\n * Generated by asn1c-" VERSION + " (http://lionet.info/asn1c)\n */\n\n"); + + TQ_FOR(mod, &(arg->asn->modules), mod_next) { + TQ_FOR(arg->expr, &(mod->members), next) { + if(include_type_to_pdu_collection(arg) == TI_NOT_INCLUDED) continue; + abuf_printf(buf, + "extern asn_TYPE_descriptor_t " + "asn_DEF_%s;\n", + asn1c_make_identifier(0, arg->expr, NULL)); + } + } - safe_fprintf(fp, "\t0\n};\n\n"); + abuf_printf(buf, "\n\n"); + abuf_printf(buf, "struct asn_TYPE_descriptor_s *asn_pdu_collection[] = {\n"); + TQ_FOR(mod, &(arg->asn->modules), mod_next) { + int mod_printed = 0; + TQ_FOR(arg->expr, &(mod->members), next) { + switch(include_type_to_pdu_collection(arg)) { + case TI_NOT_INCLUDED: + continue; + case TI_INCLUDED_FROM_BULK: + /* Increment */ + asn1c__pdu_type_lookup(arg->expr->Identifier); + break; + case TI_INCLUDED_FROM_CMDLINE: + break; + } + if(!mod_printed++) { + abuf_printf(buf, "\t/* From module %s in %s */\n", + arg->expr->module->ModuleName, + arg->expr->module->source_file_name); + } + abuf_printf(buf, "\t&asn_DEF_%s,\t\n", + asn1c_make_identifier(0, arg->expr, NULL)); + } + } - pdu_collection_print_unused_types(arg); + abuf_printf(buf, "\t0\n};\n\n"); - fclose(fp); - safe_fprintf(stderr, "Generated pdu_collection.c\n"); + if(pdu_collection_has_unused_types(arg)) { + abuf_free(buf); + return NULL; + } - return 0; + return buf; } static struct PDUType { char *typename; int used; } *pduType; -static int pduTypes; +static size_t pduTypes; static const char * generate_pdu_C_definition(void) { @@ -661,8 +702,7 @@ asn1c__add_pdu_type(const char *ctypename) { static void asn1c__cleanup_pdu_type() { - int i; - for(i = 0; i < pduTypes; i++) { + for(size_t i = 0; i < pduTypes; i++) { free(pduType[i].typename); } free(pduType); @@ -672,15 +712,14 @@ asn1c__cleanup_pdu_type() { static int asn1c__pdu_type_lookup(const char *typename) { - int i; - for(i = 0; i < pduTypes; i++) { - struct PDUType *pt = &pduType[i]; - if(strcmp(pt->typename, typename) == 0) { - pt->used++; - return 1; - } - } - return 0; + for(size_t i = 0; i < pduTypes; i++) { + struct PDUType *pt = &pduType[i]; + if(strcmp(pt->typename, typename) == 0) { + pt->used++; + return 1; + } + } + return 0; } static int @@ -692,34 +731,36 @@ need_to_generate_pdu_collection(arg_t *arg) { return 0; } -static void -pdu_collection_print_unused_types(arg_t *arg) { - int i; - for(i = 0; i < pduTypes; i++) { - struct PDUType *pt = &pduType[i]; - if(!pt->used) { - WARNING("Missing type specified in -pdu=%s", - pt->typename); - } - } +static int +pdu_collection_has_unused_types(arg_t *arg) { + int ret = 0; + + for(size_t i = 0; i < pduTypes; i++) { + struct PDUType *pt = &pduType[i]; + if(!pt->used) { + FATAL("Unknown ASN.1 type specified in -pdu=%s", pt->typename); + ret = -1; + } + } + + return ret; } -static int +static enum include_type_result include_type_to_pdu_collection(arg_t *arg) { - if(!asn1_lang_map[arg->expr->meta_type] - [arg->expr->expr_type].type_cb) - return 0; + if(!asn1_lang_map[arg->expr->meta_type][arg->expr->expr_type].type_cb) + return 0; /* Parameterized types can't serve as PDU's without instantiation. */ if(arg->expr->lhs_params) { return 0; } - if((arg->flags & A1C_PDU_ALL) - || ((arg->flags & A1C_PDU_AUTO) && !arg->expr->_type_referenced) - || asn1c__pdu_type_lookup(arg->expr->Identifier)) { - return 1; - } + if((arg->flags & A1C_PDU_ALL) + || ((arg->flags & A1C_PDU_AUTO) && !arg->expr->_type_referenced) + || asn1c__pdu_type_lookup(arg->expr->Identifier)) { + return 1; + } - return 0; + return 0; } From 3be4919d0145214c907029bb3c8a21c025c1bb10 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sat, 11 Nov 2017 16:13:32 -0800 Subject: [PATCH 22/41] make -pdu=auto a default --- libasn1compiler/asn1c_save.c | 23 +++++++-- skeletons/converter-example.c | 88 ++++++++++++++++++++++------------- 2 files changed, 75 insertions(+), 36 deletions(-) diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c index f302ceb4f..6a094f79f 100644 --- a/libasn1compiler/asn1c_save.c +++ b/libasn1compiler/asn1c_save.c @@ -617,12 +617,16 @@ generate_pdu_collection(arg_t *arg) { abuf_printf(buf, "/*\n * Generated by asn1c-" VERSION " (http://lionet.info/asn1c)\n */\n\n"); + abuf_printf(buf, + "struct asn_TYPE_descriptor_s;\t" + "/* Forward declaration */\n\n"); + TQ_FOR(mod, &(arg->asn->modules), mod_next) { TQ_FOR(arg->expr, &(mod->members), next) { if(include_type_to_pdu_collection(arg) == TI_NOT_INCLUDED) continue; abuf_printf(buf, - "extern asn_TYPE_descriptor_t " + "extern struct asn_TYPE_descriptor_s " "asn_DEF_%s;\n", asn1c_make_identifier(0, arg->expr, NULL)); } @@ -724,10 +728,19 @@ asn1c__pdu_type_lookup(const char *typename) { static int need_to_generate_pdu_collection(arg_t *arg) { + /* If -pdu=all or -pdu=auto are given, we need to generate one. */ if(arg->flags & (A1C_PDU_ALL|A1C_PDU_AUTO)) return 1; - if(arg->flags & A1C_PDU_TYPE) - return (pduTypes > 1) ? 1 : 0; + + /* + * If no -pdu=... flags were given, need to do it, too, + * effectively producing -pdu=auto. + */ + if(!(arg->flags & (A1C_PDU_ALL | A1C_PDU_AUTO | A1C_PDU_TYPE))) return 1; + + if(arg->flags & A1C_PDU_TYPE) { + return (pduTypes > 1) ? 1 : 0; + } return 0; } @@ -757,7 +770,11 @@ include_type_to_pdu_collection(arg_t *arg) { } if((arg->flags & A1C_PDU_ALL) + /* -pdu=auto */ || ((arg->flags & A1C_PDU_AUTO) && !arg->expr->_type_referenced) + /* No -pdu=... whatsoever, act as if -pdu=auto */ + || (!(arg->flags & (A1C_PDU_ALL | A1C_PDU_AUTO | A1C_PDU_TYPE)) + && !arg->expr->_type_referenced) || asn1c__pdu_type_lookup(arg->expr->Identifier)) { return 1; } diff --git a/skeletons/converter-example.c b/skeletons/converter-example.c index 98b54cc8e..2da07d064 100644 --- a/skeletons/converter-example.c +++ b/skeletons/converter-example.c @@ -23,24 +23,26 @@ #include /* for ASN__DEFAULT_STACK_MAX */ /* Convert "Type" defined by -DPDU into "asn_DEF_Type" */ - -#ifndef NO_ASN_PDU -#ifndef PDU -#error Define -DPDU to compile this sample converter. -#error `asn1c -pdu=...` adds it automatically. -#endif -#ifdef ASN_PDU_COLLECTION /* Generated by asn1c: -pdu=... */ -extern asn_TYPE_descriptor_t *asn_pdu_collection[]; -#endif +#ifdef PDU #define ASN_DEF_PDU(t) asn_DEF_ ## t #define DEF_PDU_Type(t) ASN_DEF_PDU(t) #define PDU_Type DEF_PDU_Type(PDU) - extern asn_TYPE_descriptor_t PDU_Type; /* ASN.1 type to be decoded */ #define PDU_Type_Ptr (&PDU_Type) -#else /* NO_ASN_PDU */ +#else /* !PDU */ #define PDU_Type_Ptr NULL -#endif /* NO_ASN_PDU */ +#endif /* PDU */ + +#ifdef ASN_PDU_COLLECTION /* Generated by asn1c -pdu=... */ +extern asn_TYPE_descriptor_t *asn_pdu_collection[]; +#endif + +#ifndef NO_ASN_PDU +#if !defined(PDU) && !defined(ASN_PDU_COLLECTION) +#error Define -DPDU to compile this example converter. +#error `asn1c -pdu=...` adds necessary flags automatically. +#endif +#endif /* * Open file and parse its contens. @@ -190,7 +192,8 @@ ats_by_name(const char *name, const asn_TYPE_descriptor_t *td, int main(int ac, char *av[]) { FILE *binary_out; - static asn_TYPE_descriptor_t *pduType = PDU_Type_Ptr; + asn_TYPE_descriptor_t *pduType = PDU_Type_Ptr; + asn_TYPE_descriptor_t *anyPduType = PDU_Type_Ptr; ssize_t suggested_bufsize = 8192; /* close or equal to stdio buffer */ int number_of_iterations = 1; int num; @@ -199,22 +202,27 @@ main(int ac, char *av[]) { enum asn_transfer_syntax isyntax = ATS_INVALID; enum asn_transfer_syntax osyntax = ATS_BASIC_XER; -#ifndef PDU - if(!pduType) { - fprintf(stderr, "No -DPDU defined during compilation.\n"); -#ifdef NO_ASN_PDU - exit(0); + if(!anyPduType) { +#ifdef ASN_PDU_COLLECTION + anyPduType = asn_pdu_collection[0]; + if(!anyPduType) { + fprintf(stderr, + "Empty PDU collection, no reference PDU to choose from.\n"); + exit(EX_SOFTWARE); + } #else + fprintf(stderr, "Either asn1c -pdu=... or cc -DPDU should be used.\n"); exit(EX_SOFTWARE); #endif } -#endif - /* Figure out if specialty decoder needs to be default */ - if(ats_by_name("oer", pduType, input_encodings)) - isyntax = ATS_BASIC_OER; - if(ats_by_name("per", pduType, input_encodings)) - isyntax = ATS_UNALIGNED_BASIC_PER; + /* Figure out if a specialty decoder needs to be default */ +#ifndef ASN_DISABLE_OER_SUPPORT + isyntax = ATS_BASIC_OER; +#endif +#ifndef ASN_DISABLE_PER_SUPPORT + isyntax = ATS_UNALIGNED_BASIC_PER; +#endif /* * Pocess the command-line argments. @@ -222,7 +230,7 @@ main(int ac, char *av[]) { while((ch = getopt(ac, av, "i:o:1b:cdn:p:hs:" JUNKOPT RANDOPT)) != -1) switch(ch) { case 'i': - sel = ats_by_name(optarg, pduType, input_encodings); + sel = ats_by_name(optarg, anyPduType, input_encodings); if(sel) { isyntax = sel->syntax; } else { @@ -232,7 +240,7 @@ main(int ac, char *av[]) { } break; case 'o': - sel = ats_by_name(optarg, pduType, output_encodings); + sel = ats_by_name(optarg, anyPduType, output_encodings); if(sel) { osyntax = sel->syntax; } else { @@ -283,19 +291,23 @@ main(int ac, char *av[]) { asn_TYPE_descriptor_t **pdu = asn_pdu_collection; while(*pdu && strcmp((*pdu)->name, optarg)) pdu++; if(*pdu) { pduType = *pdu; break; } - fprintf(stderr, "-p %s: Unrecognized PDU\n", optarg); + fprintf(stderr, "-p %s: Unrecognized PDU. Try '-p list'.\n", + optarg); exit(EX_USAGE); } #else /* Without -pdu=auto there's just a single type */ if(strcmp(optarg, "list") == 0) { fprintf(stderr, "Available PDU types:\n"); - printf("%s\n", pduType->name); + if(pduType) { + printf("%s\n", pduType->name); + } exit(0); } else if(optarg[0] >= 'A' && optarg[0] <= 'Z') { - if(strcmp(optarg, pduType->name) == 0) { + if(pduType && strcmp(optarg, pduType->name) == 0) { break; } - fprintf(stderr, "-p %s: Unrecognized PDU\n", optarg); + fprintf(stderr, "-p %s: Unrecognized PDU. Try '-p list'.\n", + optarg); exit(EX_USAGE); } #endif /* ASN_PDU_COLLECTION */ @@ -342,21 +354,21 @@ main(int ac, char *av[]) { fprintf(stderr, "Usage: %s [options] ...\n", av[0]); fprintf(stderr, "Where options are:\n"); for(sel = input_encodings; sel->name; sel++) { - if(ats_by_name(sel->name, pduType, sel)) { + if(ats_by_name(sel->name, anyPduType, sel)) { fprintf(stderr, " -i%s %s%s\n", sel->name, sel->full_name, (sel->syntax == isyntax) ? " (DEFAULT)" : ""); } } for(sel = output_encodings; sel->name; sel++) { - if(ats_by_name(sel->name, pduType, sel)) { + if(ats_by_name(sel->name, anyPduType, sel)) { fprintf(stderr, " -o%s%s %s%s\n", sel->name, strlen(sel->name) > 3 ? "" : " ", sel->full_name, (sel->syntax == osyntax) ? " (DEFAULT)" : ""); } } - if(pduType->op->uper_decoder) { + if(anyPduType->op->uper_decoder) { fprintf(stderr, " -per-nopad Assume PER PDUs are not padded (-iper)\n"); } @@ -384,6 +396,16 @@ main(int ac, char *av[]) { ac -= optind; av += optind; + if(!pduType) { +#ifdef NO_ASN_PDU + fprintf(stderr, "No -DPDU defined during compilation.\n"); + exit(0); +#else + fprintf(stderr, "Use '-p ' or '-p list' to select ASN.1 type.\n"); + exit(EX_USAGE); +#endif /* NO_ASN_PDU */ + } + if(ac < 1 && isyntax != ATS_RANDOM) { fprintf(stderr, "%s: No input files specified. " "Try '-h' for more information\n", From d5f6647fc52debe7157bfee0acc3dd9d0a1145b7 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sat, 11 Nov 2017 17:08:26 -0800 Subject: [PATCH 23/41] remove superfluous -pdu --- doc/docsrc/asn1c-usage.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/docsrc/asn1c-usage.tex b/doc/docsrc/asn1c-usage.tex index 1b91adcdc..0694a1b43 100644 --- a/doc/docsrc/asn1c-usage.tex +++ b/doc/docsrc/asn1c-usage.tex @@ -142,7 +142,7 @@ \section{A “Rectangle” converter and debugger} \item Compile it into the set of .c and .h files using \cmd{asn1c} compiler: \begin{bash} -asn1c -pdu=%\textbf{Rectangle}% -gen-OER -gen-PER %\textbf{rectangle.asn}% +asn1c -gen-OER -gen-PER %\textbf{rectangle.asn}% \end{bash} \item Create the converter and dumper: From d1c28aa809eeaed200c379ce74c149e9b241419f Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sat, 11 Nov 2017 18:04:26 -0800 Subject: [PATCH 24/41] generate OER and PER by default. add -no-gen-example --- ChangeLog | 2 + asn1c/asn1c.c | 28 +++++++++++--- doc/asn1c-usage.pdf | Bin 244068 -> 244231 bytes doc/docsrc/asn1c-usage.tex | 24 ++++++------ libasn1compiler/asn1c_save.c | 39 ++++++++++++-------- libasn1compiler/asn1compiler.h | 4 ++ tests/tests-asn1c-compiler/check-parsing.sh | 4 +- tests/tests-randomized/check-bundles.sh | 2 +- 8 files changed, 68 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1207fa2c5..7459cc6fd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,8 @@ then ensure the new clang is in the way: CC=clang CXX=clang++ ./configure --enable-Werror --enable-test-fuzzer * uper_encode() API got new argument (breaks API compatibility). + * asn1c -gen-XXX flags are deprecated. Use -no-gen-XXX to disable codecs. + * asn1c -no-gen-example option to disable converter-example generation. FIXES: * CVE-2017-12966 verified not present. diff --git a/asn1c/asn1c.c b/asn1c/asn1c.c index b3fc220db..e87438bfd 100644 --- a/asn1c/asn1c.c +++ b/asn1c/asn1c.c @@ -56,7 +56,8 @@ int main(int ac, char **av) { enum asn1p_flags asn1_parser_flags = A1P_NOFLAGS; enum asn1f_flags asn1_fixer_flags = A1F_NOFLAGS; - enum asn1c_flags asn1_compiler_flags = A1C_NO_C99; + enum asn1c_flags asn1_compiler_flags = + A1C_NO_C99 | A1C_GEN_OER | A1C_GEN_PER | A1C_GEN_EXAMPLE; enum asn1print_flags asn1_printer_flags = APF_NOFLAGS; int print_arg__print_out = 0; /* Don't compile, just print parsed */ int print_arg__fix_n_print = 0; /* Fix and print */ @@ -71,7 +72,7 @@ main(int ac, char **av) { /* * Process command-line options. */ - while((ch = getopt(ac, av, "EFf:g:hLPp:RS:vW:X")) != -1) switch(ch) { + while((ch = getopt(ac, av, "EFf:g:hn:LPp:RS:vW:X")) != -1) switch(ch) { case 'E': print_arg__print_out = 1; break; @@ -121,6 +122,8 @@ main(int ac, char **av) { asn1_compiler_flags |= A1C_GEN_PER; } else if(strcmp(optarg, "en-OER") == 0) { asn1_compiler_flags |= A1C_GEN_OER; + } else if(strcmp(optarg, "en-example") == 0) { + asn1_compiler_flags |= A1C_GEN_EXAMPLE; } else { fprintf(stderr, "-g%s: Invalid argument\n", optarg); exit(EX_USAGE); @@ -128,6 +131,18 @@ main(int ac, char **av) { break; case 'h': usage(av[0]); + case 'n': + if(strcmp(optarg, "o-gen-PER") == 0) { + asn1_compiler_flags &= ~A1C_GEN_PER; + } else if(strcmp(optarg, "o-gen-OER") == 0) { + asn1_compiler_flags &= ~A1C_GEN_OER; + } else if(strcmp(optarg, "o-gen-example") == 0) { + asn1_compiler_flags &= ~A1C_GEN_EXAMPLE; + } else { + fprintf(stderr, "-n%s: Invalid argument\n", optarg); + exit(EX_USAGE); + } + break; case 'P': asn1_compiler_flags |= A1C_PRINT_COMPILED; asn1_compiler_flags &= ~A1C_NO_C99; @@ -500,14 +515,15 @@ usage(const char *av0) { " -fincludes-quoted Generate #includes in \"double\" instead of quotes\n" " -fknown-extern-type= Pretend the specified type is known\n" " -fline-refs Include ASN.1 module's line numbers in comments\n" -" -fno-constraints Do not generate constraint checking code\n" -" -fno-include-deps Do not generate courtesy #includes for dependencies\n" +" -fno-constraints Do not generate the constraint checking code\n" +" -fno-include-deps Do not generate the courtesy #includes for dependencies\n" " -funnamed-unions Enable unnamed unions in structures\n" " -fwide-types Use INTEGER_t instead of \"long\" by default, etc.\n" "\n" -" -gen-OER Generate OER (X.696) support code\n" -" -gen-PER Generate PER (X.691) support code\n" +" -no-gen-OER Do not generate the OER (X.696) support code\n" +" -no-gen-PER Do not generate the PER (X.691) support code\n" +" -no-gen-example Do not generate the ASN.1 format converter example\n" " -pdu={all|auto|Type} Generate PDU table (discover PDUs automatically)\n" "\n" diff --git a/doc/asn1c-usage.pdf b/doc/asn1c-usage.pdf index 972ea178c5331a424099d3ce8720a3a9cf4bacca..f802f0ffbca44ef81a00eeddd86fa2eb74e81522 100644 GIT binary patch delta 20558 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

  • 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 delta 20398 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[i]->usage == FDEP_CONVERTER + && !(arg->flags & A1C_GEN_EXAMPLE)) + continue; + + if(asn1c_copy_over(arg, buf) == -1) { safe_fprintf(mkf, ">>>ABORTED<<<"); fclose(mkf); return -1; @@ -156,7 +160,6 @@ asn1c__save_example_makefile(arg_t *arg, const asn1c_fdeps_t *deps, const char *makefile_name, const char *library_makefile_name, int argc, char **argv) { - asn1c_fdeps_t *dlist; FILE *mkf; mkf = asn1c_open_file(makefile_name, "", 0); @@ -176,16 +179,18 @@ asn1c__save_example_makefile(arg_t *arg, const asn1c_fdeps_t *deps, (arg->flags & A1C_PDU_TYPE) ? generate_pdu_C_definition() : "", need_to_generate_pdu_collection(arg) ? "-DASN_PDU_COLLECTION " : ""); - dlist = asn1c_deps_flatten(deps); - if(dlist) { - /* only CONVERTER data in the makefile */ - for(int i = 0; i < dlist->el_count; i++) { - if(dlist->elements[i]->usage == FDEP_CONVERTER) { - safe_fprintf(mkf, "\\\n\t%s", dlist->elements[i]->filename); - } - } - asn1c_deps_freelist(dlist); - } + if(arg->flags & A1C_GEN_EXAMPLE) { + asn1c_fdeps_t *dlist = asn1c_deps_flatten(deps); + if(dlist) { + /* only CONVERTER data in the makefile */ + for(int i = 0; i < dlist->el_count; i++) { + if(dlist->elements[i]->usage == FDEP_CONVERTER) { + safe_fprintf(mkf, "\\\n\t%s", dlist->elements[i]->filename); + } + } + asn1c_deps_freelist(dlist); + } + } if(need_to_generate_pdu_collection(arg)) { safe_fprintf(mkf, "\\\n\tpdu_collection.c"); @@ -274,9 +279,13 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir, ret = asn1c__save_library_makefile(arg, deps, datadir, "Makefile.am.libasncodec"); if(ret) break; - ret = asn1c__save_example_makefile(arg, deps, "Makefile.am.example", - "Makefile.am.libasncodec", argc, argv); - if(ret) break; + + if(arg->flags & A1C_GEN_EXAMPLE) { + ret = asn1c__save_example_makefile(arg, deps, "Makefile.am.example", + "Makefile.am.libasncodec", argc, + argv); + if(ret) break; + } } while(0); asn1c_deps_freelist(deps); diff --git a/libasn1compiler/asn1compiler.h b/libasn1compiler/asn1compiler.h index 8e656b533..65d50aae4 100644 --- a/libasn1compiler/asn1compiler.h +++ b/libasn1compiler/asn1compiler.h @@ -84,6 +84,10 @@ enum asn1c_flags { * Generate Packed Encoding Rules support code */ A1C_GEN_PER = 0x80000, + /* + * Generate converter-example.c and Makefile.am.example + */ + A1C_GEN_EXAMPLE = 0x100000, }; /* diff --git a/tests/tests-asn1c-compiler/check-parsing.sh b/tests/tests-asn1c-compiler/check-parsing.sh index f10aad422..852623521 100755 --- a/tests/tests-asn1c-compiler/check-parsing.sh +++ b/tests/tests-asn1c-compiler/check-parsing.sh @@ -31,13 +31,13 @@ for ref in ${top_srcdir}/tests/tests-asn1c-compiler/*.asn1.-*; do newversion=${template}.new PROCESSING="$ref (from $src)" LANG=C sed -e 's/^found in .*/found in .../' < "$ref" > "$oldversion" - (${top_builddir}/asn1c/asn1c -S ${top_srcdir}/skeletons "-$flags" "$src" | LANG=C sed -e 's/^found in .*/found in .../' > "$newversion") || ec=$? + (${top_builddir}/asn1c/asn1c -S ${top_srcdir}/skeletons -no-gen-OER -no-gen-PER "-$flags" "$src" | LANG=C sed -e 's/^found in .*/found in .../' > "$newversion") || ec=$? if [ $? = 0 ]; then diff $diffArgs "$oldversion" "$newversion" || ec=$? fi rm -f $oldversion $newversion if [ "$1" = "regenerate" ]; then - ${top_builddir}/asn1c/asn1c -S ${top_srcdir}/skeletons "-$flags" "$src" > "$ref" + ${top_builddir}/asn1c/asn1c -S ${top_srcdir}/skeletons -no-gen-OER -no-gen-PER "-$flags" "$src" > "$ref" fi done diff --git a/tests/tests-randomized/check-bundles.sh b/tests/tests-randomized/check-bundles.sh index 27c95429f..f62f6295e 100755 --- a/tests/tests-randomized/check-bundles.sh +++ b/tests/tests-randomized/check-bundles.sh @@ -254,7 +254,7 @@ asn1c_invoke() { } > ${tmpfile} echo "${abs_top_builddir}/asn1c/asn1c -S ${abs_top_srcdir}/skeletons" if "${abs_top_builddir}/asn1c/asn1c" -S "${abs_top_srcdir}/skeletons" \ - -gen-OER -gen-PER ${asn1c_flags} $@ ${tmpfile} + ${asn1c_flags} $@ ${tmpfile} then echo "ASN.1 compiled OK" else From 227b94455857750190c4b7724af6db15af0ceb4d Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sat, 11 Nov 2017 18:08:33 -0800 Subject: [PATCH 25/41] changelog order fix --- ChangeLog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7459cc6fd..15d102248 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,7 +9,7 @@ NOTABLE: * converter-sample.c renamed into converter-example.c. - * OBJECT IDENTIFIER and RELATIVE-OID API simplified. + * asn1c -no-gen-example option to disable converter-example generation. * Added random value generation (-R option to converter-example). * Added LibFuzzer-based randomized tests for supported transfer syntaxes (DER, OER, UPER, XER) into tests/tests-randomized. See the following @@ -17,9 +17,9 @@ https://medium.com/@levwalkin/compile-llvm-clang-libfuzzer-b61e82718430 then ensure the new clang is in the way: CC=clang CXX=clang++ ./configure --enable-Werror --enable-test-fuzzer + * OBJECT IDENTIFIER and RELATIVE-OID API simplified. * uper_encode() API got new argument (breaks API compatibility). * asn1c -gen-XXX flags are deprecated. Use -no-gen-XXX to disable codecs. - * asn1c -no-gen-example option to disable converter-example generation. FIXES: * CVE-2017-12966 verified not present. From 30566d131068fc4347695a2566ef041f35d46f33 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sun, 12 Nov 2017 15:27:36 -0800 Subject: [PATCH 26/41] add asn1c compile smoke test --- .gitignore | 8 +++ configure.ac | 1 + tests/Makefile.am | 2 + tests/README | 10 +-- tests/tests-asn1c-smoke/Makefile.am | 9 +++ tests/tests-asn1c-smoke/README | 2 + tests/tests-asn1c-smoke/check-asn1c-smoke.sh | 74 ++++++++++++++++++++ 7 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 tests/tests-asn1c-smoke/Makefile.am create mode 100644 tests/tests-asn1c-smoke/README create mode 100755 tests/tests-asn1c-smoke/check-asn1c-smoke.sh diff --git a/.gitignore b/.gitignore index 306fcf878..34af5cf46 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,14 @@ stamp-h* # /skeletons /skeletons/check-* +# /tests/ +/tests/tests-asn1c-smoke/Makefile.am.libasncodec +/tests/tests-asn1c-smoke/Makefile.am.sample +/tests/tests-asn1c-smoke/*.[acho] +/tests/tests-asn1c-smoke/*.asn +/tests/tests-asn1c-smoke/*.txt +/tests/tests-asn1c-smoke/converter-example + # /tests/ /tests/tests-c-compiler/test-* diff --git a/configure.ac b/configure.ac index 2df1580f9..b0e5ffdfa 100644 --- a/configure.ac +++ b/configure.ac @@ -288,6 +288,7 @@ AM_CONDITIONAL([HAVE_PANDOC], [test -n "$PANDOC"]) AC_CONFIG_FILES([\ tests/tests-c-compiler/check-src/Makefile \ tests/tests-asn1c-compiler/Makefile \ +tests/tests-asn1c-smoke/Makefile \ tests/tests-randomized/Makefile \ tests/tests-c-compiler/Makefile \ tests/tests-skeletons/Makefile \ diff --git a/tests/Makefile.am b/tests/Makefile.am index 740321667..d1342728f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,9 @@ +# Tests are ordered in the rough order of the time it takes to go through them. SUBDIRS = \ tests-asn1c-compiler \ tests-skeletons \ + tests-asn1c-smoke \ tests-c-compiler \ tests-randomized diff --git a/tests/README b/tests/README index 8f11f1747..7e9b97cbd 100644 --- a/tests/README +++ b/tests/README @@ -1,6 +1,6 @@ - -tests-asn1c-compiler - tests behavior of asn1c compiler, textually -tests-c-compiler - attempts to compile C results of asn1c output -tests-skeletons - verify correctness of "skeletons" code -tests-randomized - thorough testing of DER/OER/PER/XER with fuzzing +tests-asn1c-compiler - asn1c produces expected textual output +tests-asn1c-smoke - asn1c compiler produces compilable code for simple types +tests-c-compiler - C code compiles and runs, and produces expected result +tests-skeletons - "skeletons" code primitives are correct +tests-randomized - fuzz-testing of DER/OER/PER/XER codecs diff --git a/tests/tests-asn1c-smoke/Makefile.am b/tests/tests-asn1c-smoke/Makefile.am new file mode 100644 index 000000000..eae3322cf --- /dev/null +++ b/tests/tests-asn1c-smoke/Makefile.am @@ -0,0 +1,9 @@ + +dist_check_SCRIPTS = check-asn1c-smoke.sh +TESTS_ENVIRONMENT= MAKE=${MAKE} \ + top_builddir=${top_builddir} \ + top_srcdir=${top_srcdir} +TESTS = $(dist_check_SCRIPTS) +CLEANFILES = Makefile.am.* test* *.[acho] + +EXTRA_DIST = README diff --git a/tests/tests-asn1c-smoke/README b/tests/tests-asn1c-smoke/README new file mode 100644 index 000000000..57467e302 --- /dev/null +++ b/tests/tests-asn1c-smoke/README @@ -0,0 +1,2 @@ +Test that asn1c compiler produces compilable code for basic ASN.1 types, +while trying to disable different codecs and vary other compiler flags. diff --git a/tests/tests-asn1c-smoke/check-asn1c-smoke.sh b/tests/tests-asn1c-smoke/check-asn1c-smoke.sh new file mode 100755 index 000000000..d909af2ca --- /dev/null +++ b/tests/tests-asn1c-smoke/check-asn1c-smoke.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +set -x +set -e +set -o pipefail + +top_builddir=${top_builddir:-../..} +top_srcdir=${top_srcdir:-../..} + +cleanup() { + rm -rf *.[cho] Makefile.am.* *.txt *.asn + rm -f converter-example +} + +print_state() { + local err=$? + set +x + set +e + trap "" EXIT ERR + echo "Error $err while processing:" + cat test.asn + cat status.txt + echo "FAILED" + exit $err +} + +verify() { + local type="$1" + local flags="$2" + + cleanup + + asncmd="${top_builddir}/asn1c/asn1c -flink-skeletons -S ${top_srcdir}/skeletons $flags test.asn" + + { + echo "$asncmd" + echo "${MAKE:-make} -f Makefile.am.example" + } > status.txt + + echo "Module DEFINITIONS::=BEGIN T::=$type END" > test.asn + $asncmd + CFLAGS=-O0 ${MAKE:-make} -f Makefile.am.example | tail -10 +} + +verify_type_with_variants() { + local type="$1" + for flags in "-no-gen-PER" "-no-gen-OER" "-no-gen-PER -no-gen-OER" ""; do + for native in "" "-fwide-types"; do + verify "$type" "$flags $native" + done + done +} + +verify_compile_and_link_variants() { + for type in INTEGER "ENUMERATED{foo}" NULL BOOLEAN "BIT STRING" \ + "OBJECT IDENTIFIER" "RELATIVE-OID" "SEQUENCE{f INTEGER}" \ + "CHOICE{f INTEGER}" "OCTET STRING" IA5String UTF8String \ + REAL "SET OF INTEGER" "SEQUENCE OF INTEGER"; do + verify_type_with_variants "$type" + + done +} + +trap print_state EXIT ERR +if [ "x$*" = "x" ]; then + verify_compile_and_link_variants +else + for type in "$@"; do + verify_type_with_variants "$type" + done +fi +trap '' EXIT ERR + +cleanup From 7d5d9303931b15bc88ba30812c8086e176db843e Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Mon, 13 Nov 2017 22:17:20 -0800 Subject: [PATCH 27/41] more precise OER and PER code bundling --- libasn1compiler/asn1c_compat.c | 4 - libasn1compiler/asn1c_fdeps.c | 340 ++++++++++--------- libasn1compiler/asn1c_fdeps.h | 76 +++-- libasn1compiler/asn1c_internal.h | 5 + libasn1compiler/asn1c_save.c | 116 ++++--- skeletons/INTEGER.h | 1 - skeletons/file-dependencies | 24 +- tests/tests-asn1c-smoke/check-asn1c-smoke.sh | 13 +- 8 files changed, 323 insertions(+), 256 deletions(-) diff --git a/libasn1compiler/asn1c_compat.c b/libasn1compiler/asn1c_compat.c index ae0f475f8..f55032c16 100644 --- a/libasn1compiler/asn1c_compat.c +++ b/libasn1compiler/asn1c_compat.c @@ -1,10 +1,6 @@ #include "asn1c_internal.h" #include "asn1c_compat.h" -#ifndef PATH_MAX -#define PATH_MAX 1024 -#endif - /* Normally file permissions are (DEFFILEMODE & ~umask(2)) */ #ifndef DEFFILEMODE /* Normally in */ diff --git a/libasn1compiler/asn1c_fdeps.c b/libasn1compiler/asn1c_fdeps.c index 18dd63775..ed8af9bc2 100644 --- a/libasn1compiler/asn1c_fdeps.c +++ b/libasn1compiler/asn1c_fdeps.c @@ -1,82 +1,84 @@ #include "asn1c_internal.h" #include "asn1c_fdeps.h" -#ifndef PATH_MAX -#define PATH_MAX 1024 -#endif - -static asn1c_fdeps_t *asn1c_new_dep(const char *filename); -static int asn1c_dep_add(asn1c_fdeps_t *deps, asn1c_fdeps_t *d); - -int -asn1c_activate_dependency(asn1c_fdeps_t *deps, asn1c_fdeps_t *cur, const char *data) { - char fname_scratch[PATH_MAX]; - const char *fname; - int i; - - if(!deps || !data || !*data) - return 0; - if(!cur) cur = deps; - - if(cur->usage > FDEP_NOTUSED) - return 1; /* Already activated */ - - fname = data; - if(*data == '#') { - const char *start = data; - const char *end = 0; - - start = strchr(data, '<'); - if(start) { - start++; - end = strchr(start, '>'); - } else if((start = strchr(data, '\"'))) { - start++; - end = strchr(start, '\"'); - } - if(end) { - assert((end-start) + 1 < (ssize_t)sizeof(fname_scratch)); - memcpy(fname_scratch, start, end - start); - fname_scratch[end-start] = '\0'; - fname = fname_scratch; - } else { - return 0; - } - } - - if(cur->filename && strcmp(cur->filename, fname) == 0) { - cur->usage = FDEP_REFERRED; - - /* Activate subdependencies */ - for(i = 0; i < cur->el_count; i++) { - asn1c_activate_dependency(deps, - cur->elements[i], - cur->elements[i]->filename); - } - - /* - * This might be a link to someplace else. - */ - return asn1c_activate_dependency(deps, NULL, fname); - } else { - for(i = 0; i < cur->el_count; i++) { - asn1c_activate_dependency(deps, - cur->elements[i], fname); - } - } +static asn1c_dep_filename *asn1c_new_dep_filename(const char *filename); +static void asn1c_dep_add(asn1c_dep_chain *dlist, const char *filename, + int lineno, int column); +static asn1c_dep_chain *asn1c_new_dep_chain(); + +static asn1c_dep_chain * +asn1c_dep_chains_add_new(asn1c_dep_chainset *deps, + enum asn1c_dep_section section, int active) { + asn1c_dep_chain *dc = asn1c_new_dep_chain(); + asn1c_tagged_dep_chain *tc = calloc(1, sizeof(*tc)); + tc->chain = dc; + tc->section = section; + tc->activated.active = active; + + deps->chains = realloc(deps->chains, + sizeof(deps->chains[0]) * (deps->chains_count + 1)); + assert(deps->chains); + deps->chains[deps->chains_count] = tc; + deps->chains_count++; + + return dc; +} - return 0; +void +asn1c_activate_dependency(asn1c_dep_chainset *deps, const char *data, + const char *by) { + char fname_scratch[PATH_MAX]; + + if(!deps || !data || !*data) { + return; + } + + assert(deps->chains_count); + + const char *fname = data; + if(*data == '#') { + const char *start = data; + const char *end = 0; + + start = strchr(data, '<'); + if(start) { + start++; + end = strchr(start, '>'); + } else if((start = strchr(data, '\"'))) { + start++; + end = strchr(start, '\"'); + } + if(end) { + assert((end-start) + 1 < (ssize_t)sizeof(fname_scratch)); + memcpy(fname_scratch, start, end - start); + fname_scratch[end-start] = '\0'; + fname = fname_scratch; + } else { + return; + } + } + + for(size_t i = 0; i < deps->chains_count; i++) { + asn1c_tagged_dep_chain *ch = deps->chains[i]; + if(!ch->activated.active && ch->chain->deps_count > 0 + && strcmp(ch->chain->deps[0]->filename, fname) == 0) { + ch->activated.by = strdup(by); + ch->activated.active = 1; + + for(size_t j = 0; j < ch->chain->deps_count; j++) { + asn1c_activate_dependency(deps, ch->chain->deps[j]->filename, + by); + } + } + } } -asn1c_fdeps_t * +asn1c_dep_chainset * asn1c_read_file_dependencies(arg_t *arg, const char *datadir) { char buf[4096]; - asn1c_fdeps_t *deps; - asn1c_fdeps_t *cur; + asn1c_dep_chainset *deps; FILE *f; - enum fdep_usage special_section = FDEP_NOTUSED; - - (void)arg; + int lineno = 0; if(!datadir || strlen(datadir) > sizeof(buf) / 2) { errno = EINVAL; @@ -88,146 +90,162 @@ asn1c_read_file_dependencies(arg_t *arg, const char *datadir) { f = fopen(buf, "r"); if(!f) return NULL; - deps = asn1c_new_dep(0); + deps = calloc(1, sizeof(*deps)); assert(deps); + enum asn1c_dep_section section = FDEP_COMMON_FILES; + int activate = 0; - while(fgets(buf, sizeof(buf), f)) { + while(fgets(buf, sizeof(buf), f)) { char *p = strchr(buf, '#'); if(p) *p = '\0'; /* Remove comments */ - cur = deps; - for(p = strtok(buf, " \t\r\n"); p; + lineno++; + + asn1c_dep_chain *dc = asn1c_dep_chains_add_new(deps, section, activate); + + for(p = strtok(buf, " \t\r\n"); p; p = strtok(NULL, " \t\r\n")) { - asn1c_fdeps_t *d; /* * Special "prefix" section. */ if(strchr(p, ':')) { - special_section = FDEP_IGNORE; if(strcmp(p, "COMMON-FILES:") == 0) { - special_section = FDEP_COMMON_FILES; + section = FDEP_COMMON_FILES; + activate = 1; } else if(strcmp(p, "CONVERTER:") == 0) { - special_section = FDEP_CONVERTER; + activate = 1; + section = FDEP_CONVERTER; } else if((arg->flags & A1C_GEN_OER) && strcmp(p, "CODEC-OER:") == 0) { - special_section = FDEP_CODEC_OER; + activate = 0; + section = FDEP_CODEC_OER; } else if((arg->flags & A1C_GEN_PER) && strcmp(p, "CODEC-PER:") == 0) { - special_section = FDEP_CODEC_PER; - } - break; + activate = 0; + section = FDEP_CODEC_PER; + } else { + section = FDEP_IGNORE; + activate = 0; + } + break; } - if(special_section == FDEP_IGNORE) - continue; - - d = asn1c_new_dep(p); - d->usage = special_section; - - if(asn1c_dep_add(cur, d) == 1) - cur = d; - } + asn1c_dep_add(dc, p, lineno, p - buf); + } } fclose(f); + /* A single filename by itself means that we should include that */ + for(size_t i = 0; i < deps->chains_count; i++) { + asn1c_tagged_dep_chain *ch = deps->chains[i]; + if(!ch->activated.active && ch->chain->deps_count == 1) { + asn1c_activate_dependency(deps, ch->chain->deps[0]->filename, + "implicit"); + } + } + return deps; } -static asn1c_fdeps_t * -asn1c_new_dep(const char *filename) { - asn1c_fdeps_t *d; +static asn1c_dep_filename * +asn1c_new_dep_filename(const char *filename) { + asn1c_dep_filename *d; - d = calloc(1, sizeof(*d)); - if(filename) { - d->filename = strdup(filename); - if(!d->filename) return NULL; - } + assert(filename); + + d = calloc(1, sizeof(*d)); + assert(d); + d->filename = strdup(filename); + assert(d->filename); return d; } -static void -asn1c_free_dep(asn1c_fdeps_t *d) { +static asn1c_dep_chain * +asn1c_new_dep_chain() { + return calloc(1, sizeof(asn1c_dep_chain)); +} - if(d) { - if(d->filename) free(d->filename); - d->filename = 0; - free(d); - } +static void +asn1c_dep_add(asn1c_dep_chain *dlist, const char *filename, int lineno, int column) { + asn1c_dep_filename *df = asn1c_new_dep_filename(filename); + df->lineno = lineno; + df->column = column; + + dlist->deps = + realloc(dlist->deps, (dlist->deps_count + 1) * sizeof(dlist->deps[0])); + assert(dlist->deps); + dlist->deps[dlist->deps_count] = df; + dlist->deps_count += 1; } static int -asn1c_dep_add(asn1c_fdeps_t *deps, asn1c_fdeps_t *d) { - int n; - - /* Check for duplicates */ - for(n = 0; n < deps->el_count; n++) { - if(strcmp(deps->elements[n]->filename, d->filename) == 0) - return 0; - } - - if(deps->el_count == deps->el_size) { - void *p; - n = deps->el_size?deps->el_size << 2:16; - p = realloc(deps->elements, - n * sizeof(deps->elements[0])); - assert(p); - deps->elements = p; - deps->el_size = n; - } - - deps->elements[deps->el_count++] = d; - return 1; +asn1c_dep_has_filename(const asn1c_dep_chain *dlist, const char *filename) { + for(size_t i = 0; i < dlist->deps_count; i++) { + if(strcmp(dlist->deps[i]->filename, filename) == 0) { + return 1; + } + } + return 0; } -asn1c_fdeps_t * -asn1c_deps_flatten(const asn1c_fdeps_t *deps) { - asn1c_fdeps_t *dlist; - asn1c_fdeps_t *d; +asn1c_dep_chain * +asn1c_deps_flatten(const asn1c_dep_chainset *deps, + enum asn1c_dep_section include_section) { + asn1c_dep_chain *dlist; if(!deps) { errno = EINVAL; return 0; } - dlist = asn1c_new_dep(0); + dlist = asn1c_new_dep_chain(); - if(deps->filename && deps->usage != FDEP_NOTUSED) { - d = asn1c_new_dep(deps->filename); - d->usage = deps->usage; - if(!asn1c_dep_add(dlist, d)) { - asn1c_free_dep(d); - } - } + for(size_t i = 0; i < deps->chains_count; i++) { + asn1c_tagged_dep_chain *tc = deps->chains[i]; + asn1c_dep_chain *dc = tc->chain; - for(int i = 0; i < deps->el_count; i++) { - d = asn1c_deps_flatten(deps->elements[i]); - assert(!d->filename); - for(int j = 0; j < d->el_count; j++) { - if(asn1c_dep_add(dlist, d->elements[j])) { - d->elements[j] = 0; - } - } - asn1c_deps_freelist(d); - } + if(!tc->activated.active) { + continue; + } + if((tc->section & include_section) == 0) { + continue; + } + + for(size_t j = 0; j < dc->deps_count; j++) { + if(!asn1c_dep_has_filename(dlist, dc->deps[j]->filename)) { + asn1c_dep_add(dlist, dc->deps[j]->filename, dc->deps[j]->lineno, + dc->deps[j]->column); + } + } + } return dlist; } void -asn1c_deps_freelist(asn1c_fdeps_t *deps) { +asn1c_dep_chain_free(asn1c_dep_chain *dc) { + if(dc) { + for(size_t i = 0; i < dc->deps_count; i++) { + asn1c_dep_filename *df = dc->deps[i]; + free(df->filename); + free(df); + } + free(dc->deps); + } +} + +void +asn1c_dep_chainset_free(asn1c_dep_chainset *deps) { if(deps) { - int i; - if(deps->elements) { - for(i = 0; i < deps->el_count; i++) { - asn1c_deps_freelist(deps->elements[i]); - deps->elements[i] = 0; - } - free(deps->elements); - deps->elements = 0; - } - asn1c_free_dep(deps); - } + for(size_t i = 0; i < deps->chains_count; i++) { + asn1c_dep_chain_free(deps->chains[i]->chain); + free(deps->chains[i]->activated.by); + free(deps->chains[i]); + } + free(deps->chains); + free(deps); + } } diff --git a/libasn1compiler/asn1c_fdeps.h b/libasn1compiler/asn1c_fdeps.h index 3be9e803a..7b025babb 100644 --- a/libasn1compiler/asn1c_fdeps.h +++ b/libasn1compiler/asn1c_fdeps.h @@ -1,31 +1,61 @@ #ifndef ASN1C_FDEPS_H #define ASN1C_FDEPS_H -typedef struct asn1c_fdeps_s { - char *filename; /* Or 0, if root. */ - - enum fdep_usage { - FDEP_IGNORE = -1, /* Ignore contents of the section */ - FDEP_NOTUSED = 0, - FDEP_REFERRED = 1, /* Dynamic list of dependencies */ - FDEP_CONVERTER = 2, /* Name of the int main() file */ - FDEP_COMMON_FILES = 3, /* Section for mandatory dependencies */ - FDEP_CODEC_OER = 4, /* Use contents only if -gen-OER */ - FDEP_CODEC_PER = 8, /* Use contents only if -gen-PER */ - } usage; /* Some file refers to it */ - - struct asn1c_fdeps_s **elements; - int el_size; - int el_count; -} asn1c_fdeps_t; - -asn1c_fdeps_t *asn1c_read_file_dependencies(arg_t *arg, const char *datadir); +typedef struct { + char *filename; + int lineno; + int column; +} asn1c_dep_filename; + + +/* + * Format: + * [ ...] + */ +typedef struct { + asn1c_dep_filename **deps; + size_t deps_count; +} asn1c_dep_chain; + +/* + * A single dependency chain, marked with the usage tag and activation tag. + */ +typedef struct { + enum asn1c_dep_section { + FDEP_IGNORE = 0, /* Section is not used */ + FDEP_DEFAULT = (1 << 1), /* Default dependency list */ + FDEP_REFERRED = (1 << 2), /* Dynamic list of dependencies */ + FDEP_CONVERTER = (1 << 3), /* Name of the file with int main() */ + FDEP_COMMON_FILES = (1 << 4), /* Section for mandatory dependencies */ + FDEP_CODEC_OER = (1 << 5), /* Use contents only if -gen-OER */ + FDEP_CODEC_PER = (1 << 6), /* Use contents only if -gen-PER */ + } section; /* Some file refers to it */ + + /* Whether this chain is alive and has to be present in the output */ + struct { + int active; + char *by; + } activated; + + asn1c_dep_chain *chain; +} asn1c_tagged_dep_chain; + +typedef struct { + asn1c_tagged_dep_chain **chains; + size_t chains_count; +} asn1c_dep_chainset; + +asn1c_dep_chainset *asn1c_read_file_dependencies(arg_t *arg, + const char *datadir); /* Data may be a filename or an "#include <>" string. */ -int asn1c_activate_dependency(asn1c_fdeps_t *deps, asn1c_fdeps_t *cur, - const char *data); +void asn1c_activate_dependency(asn1c_dep_chainset *deps, const char *data, + const char *by); + +asn1c_dep_chain *asn1c_deps_flatten(const asn1c_dep_chainset *deps, + enum asn1c_dep_section); -asn1c_fdeps_t *asn1c_deps_flatten(const asn1c_fdeps_t *deps); -void asn1c_deps_freelist(asn1c_fdeps_t *deps); +void asn1c_dep_chain_free(asn1c_dep_chain *); +void asn1c_dep_chainset_free(asn1c_dep_chainset *); #endif /* ASN1C_FDEPS_H */ diff --git a/libasn1compiler/asn1c_internal.h b/libasn1compiler/asn1c_internal.h index e74371c44..7a07e3540 100644 --- a/libasn1compiler/asn1c_internal.h +++ b/libasn1compiler/asn1c_internal.h @@ -10,6 +10,7 @@ #include /* for strlen(3) and memset(3) */ #include /* for isalnum(3) */ #include /* for fstat(2) */ +#include /* for PATH_MAX */ #include #include #include @@ -22,6 +23,10 @@ #include /* for unlink(2) */ #endif +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + #ifdef _WIN32 #include #include diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c index c734062c1..2aaee05fa 100644 --- a/libasn1compiler/asn1c_save.c +++ b/libasn1compiler/asn1c_save.c @@ -38,10 +38,10 @@ enum include_type_result { TI_INCLUDED_FROM_CMDLINE }; -static int asn1c_dump_streams(arg_t *arg, asn1c_fdeps_t *, int, char **); +static int asn1c_dump_streams(arg_t *arg, asn1c_dep_chainset *, int, char **); static int asn1c_print_streams(arg_t *arg); -static int asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *, int, char **); -static int asn1c_copy_over(arg_t *arg, char *path); +static int asn1c_save_streams(arg_t *arg, asn1c_dep_chainset *, int, char **); +static int asn1c_copy_over(arg_t *arg, const char *path, const char *msg); static int identical_files(const char *fname1, const char *fname2); static int need_to_generate_pdu_collection(arg_t *arg); static abuf *generate_pdu_collection(arg_t *arg); @@ -54,8 +54,8 @@ static void asn1c__cleanup_pdu_type(void); static int asn1c__pdu_type_lookup(const char *typename); static int -asn1c__save_library_makefile(arg_t *arg, const asn1c_fdeps_t *deps, const char *datadir, const char *makefile_name) { - asn1c_fdeps_t *dlist; +asn1c__save_library_makefile(arg_t *arg, const asn1c_dep_chainset *deps, + const char *datadir, const char *makefile_name) { asn1p_module_t *mod; FILE *mkf; @@ -90,49 +90,51 @@ asn1c__save_library_makefile(arg_t *arg, const asn1c_fdeps_t *deps, const char * /* * Move necessary skeleton files and add them to Makefile.am.targets. */ - dlist = asn1c_deps_flatten(deps); - if(dlist) { - char buf[8129]; + asn1c_dep_chain *dlist = asn1c_deps_flatten(deps, ~FDEP_CONVERTER); + if(dlist) { + char dstpath[PATH_MAX]; char *dir_end; size_t dlen = strlen(datadir); - assert(dlen < (sizeof(buf) / 2 - 2)); - memcpy(buf, datadir, dlen); - dir_end = buf + dlen; + assert(dlen < (sizeof(dstpath) / 2 - 2)); + memcpy(dstpath, datadir, dlen); + dir_end = dstpath + dlen; *dir_end++ = '/'; - for(int i = 0; i < dlist->el_count; i++) { + for(size_t i = 0; i < dlist->deps_count; i++) { + char where[32]; /* Location of the */ char *what_kind; /* HEADERS or SOURCES */ - char *fname = dlist->elements[i]->filename; + const asn1c_dep_filename *dep_file = dlist->deps[i]; + char *fname = dep_file->filename; char *dotH; - assert(strlen(fname) < (sizeof(buf) / 2)); + assert(strlen(fname) < (sizeof(dstpath) / 2)); strcpy(dir_end, fname); - if(dlist->elements[i]->usage == FDEP_CONVERTER - && !(arg->flags & A1C_GEN_EXAMPLE)) - continue; + if(arg->flags & A1C_DEBUG) { + snprintf(where, sizeof(where), "(line %d col %d)", + dep_file->lineno, dep_file->column); + } else { + where[0] = '\0'; + } - if(asn1c_copy_over(arg, buf) == -1) { + if(asn1c_copy_over(arg, dstpath, where) == -1) { safe_fprintf(mkf, ">>>ABORTED<<<"); fclose(mkf); return -1; } - /* no CONVERTER data in Makefile.am.targets */ - if(dlist->elements[i]->usage != FDEP_CONVERTER) { - /* HEADERS versus SOURCES */ - dotH = strrchr(fname, 'h'); - if(dotH && fnameflags & A1C_GEN_EXAMPLE) { - asn1c_fdeps_t *dlist = asn1c_deps_flatten(deps); + asn1c_dep_chain *dlist = asn1c_deps_flatten(deps, FDEP_CONVERTER); if(dlist) { - /* only CONVERTER data in the makefile */ - for(int i = 0; i < dlist->el_count; i++) { - if(dlist->elements[i]->usage == FDEP_CONVERTER) { - safe_fprintf(mkf, "\\\n\t%s", dlist->elements[i]->filename); + for(size_t i = 0; i < dlist->deps_count; i++) { + char dstpath[PATH_MAX]; + int ret = snprintf(dstpath, sizeof(dstpath), "%s/%s", datadir, + dlist->deps[i]->filename); + assert(ret > 0 && (size_t)ret < sizeof(dstpath)); + if(asn1c_copy_over(arg, dstpath, "implicit") == -1) { + safe_fprintf(mkf, ">>>ABORTED<<<"); + fclose(mkf); + return -1; } + safe_fprintf(mkf, "\\\n\t%s", dlist->deps[i]->filename); } - asn1c_deps_freelist(dlist); + asn1c_dep_chain_free(dlist); } } @@ -237,7 +245,6 @@ can_generate_pdu_collection(arg_t *arg) { int asn1c_save_compiled_output(arg_t *arg, const char *datadir, int argc, int optc, char **argv) { - asn1c_fdeps_t *deps = 0; int ret = -1; /* @@ -247,6 +254,7 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir, return -1; } + asn1c_dep_chainset *deps; do { asn1p_module_t *mod; @@ -281,14 +289,14 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir, if(ret) break; if(arg->flags & A1C_GEN_EXAMPLE) { - ret = asn1c__save_example_makefile(arg, deps, "Makefile.am.example", - "Makefile.am.libasncodec", argc, - argv); + ret = asn1c__save_example_makefile( + arg, deps, datadir, "Makefile.am.example", + "Makefile.am.libasncodec", argc, argv); if(ret) break; } } while(0); - asn1c_deps_freelist(deps); + asn1c_dep_chainset_free(deps); asn1c__cleanup_pdu_type(); return ret; @@ -298,8 +306,9 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir, * Dump the streams. */ static int -asn1c_dump_streams(arg_t *arg, asn1c_fdeps_t *deps, int optc, char **argv) { - if(arg->flags & A1C_PRINT_COMPILED) { +asn1c_dump_streams(arg_t *arg, asn1c_dep_chainset *deps, int optc, + char **argv) { + if(arg->flags & A1C_PRINT_COMPILED) { return asn1c_print_streams(arg); } else { return asn1c_save_streams(arg, deps, optc, argv); @@ -330,8 +339,9 @@ asn1c_print_streams(arg_t *arg) { } static int -asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps, int optc, char **argv) { - asn1p_expr_t *expr = arg->expr; +asn1c_save_streams(arg_t *arg, asn1c_dep_chainset *deps, int optc, + char **argv) { + asn1p_expr_t *expr = arg->expr; compiler_streams_t *cs = expr->data; out_chunk_t *ot; FILE *fp_c, *fp_h; @@ -373,7 +383,7 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps, int optc, char **argv) { if(TQ_FIRST(&(cs->destination[idx].chunks)) && *msg) \ safe_fprintf(fp, "\n/* %s */\n", msg); \ TQ_FOR(ot, &(cs->destination[idx].chunks), next) { \ - if(actdep) asn1c_activate_dependency(deps, 0, ot->buf); \ + if(actdep) asn1c_activate_dependency(deps, ot->buf, header_id); \ safe_fwrite(ot->buf, ot->len, 1, fp); \ } \ } while(0) @@ -554,7 +564,7 @@ real_copy(const char *src, const char *dst) { } static int -asn1c_copy_over(arg_t *arg, char *path) { +asn1c_copy_over(arg_t *arg, const char *path, const char *msg) { #ifdef _WIN32 int use_real_copy = 1; #else @@ -595,10 +605,12 @@ asn1c_copy_over(arg_t *arg, char *path) { } } - safe_fprintf(stderr, "%s %s\t-> %s\n", - use_real_copy ? "Copied" : "Symlinked", path, fname); + const int has_msg = msg && *msg; + safe_fprintf(stderr, "%s %s\t-> %s%s%s\n", + use_real_copy ? "Copied" : "Symlinked", path, fname, + has_msg ? " " : "", has_msg ? msg : ""); - return 1; + return 1; } diff --git a/skeletons/INTEGER.h b/skeletons/INTEGER.h index 8efd75c0e..cc760ffa9 100644 --- a/skeletons/INTEGER.h +++ b/skeletons/INTEGER.h @@ -7,7 +7,6 @@ #include #include -#include #ifdef __cplusplus extern "C" { diff --git a/skeletons/file-dependencies b/skeletons/file-dependencies index 012ea6c9b..76bc30140 100644 --- a/skeletons/file-dependencies +++ b/skeletons/file-dependencies @@ -69,17 +69,19 @@ CONVERTER: # THIS IS A SPECIAL SECTION converter-example.c # A default name for the example transcoder CODEC-OER: # THIS IS A SPECIAL SECTION -oer_decoder.h oer_decoder.c OPEN_TYPE.h # OER decoding support -oer_encoder.h oer_encoder.c # OER encoding support -oer_support.h oer_support.c # OER support +oer_decoder.h +oer_encoder.h +oer_support.h +oer_decoder.h oer_decoder.c OPEN_TYPE.h +oer_encoder.h oer_encoder.c +oer_support.h oer_support.c OPEN_TYPE.h OPEN_TYPE_oer.c constr_CHOICE.h -INTEGER_oer.c INTEGER.h -OCTET_STRING_oer.c -NativeInteger_oer.c NativeInteger.h -NativeEnumerated_oer.c NativeEnumerated.h -constr_SEQUENCE_oer.c constr_SEQUENCE.h -constr_CHOICE_oer.c -constr_SET_OF_oer.c constr_SET_OF.h asn_SET_OF.h asn_SET_OF.c -BIT_STRING_oer.c +INTEGER.h INTEGER_oer.c +BIT_STRING.h BIT_STRING_oer.c OCTET_STRING_oer.c +NativeInteger.h NativeInteger_oer.c +NativeEnumerated.h NativeEnumerated_oer.c +constr_CHOICE.h constr_CHOICE_oer.c +constr_SEQUENCE.h constr_SEQUENCE_oer.c +constr_SET_OF.h constr_SET_OF_oer.c CODEC-PER: # THIS IS A SPECIAL SECTION diff --git a/tests/tests-asn1c-smoke/check-asn1c-smoke.sh b/tests/tests-asn1c-smoke/check-asn1c-smoke.sh index d909af2ca..f374e67de 100755 --- a/tests/tests-asn1c-smoke/check-asn1c-smoke.sh +++ b/tests/tests-asn1c-smoke/check-asn1c-smoke.sh @@ -30,7 +30,7 @@ verify() { cleanup - asncmd="${top_builddir}/asn1c/asn1c -flink-skeletons -S ${top_srcdir}/skeletons $flags test.asn" + asncmd="${top_builddir}/asn1c/asn1c -Wdebug-compiler -flink-skeletons -S ${top_srcdir}/skeletons $flags test.asn" { echo "$asncmd" @@ -52,9 +52,12 @@ verify_type_with_variants() { } verify_compile_and_link_variants() { - for type in INTEGER "ENUMERATED{foo}" NULL BOOLEAN "BIT STRING" \ - "OBJECT IDENTIFIER" "RELATIVE-OID" "SEQUENCE{f INTEGER}" \ - "CHOICE{f INTEGER}" "OCTET STRING" IA5String UTF8String \ + for type in INTEGER "INTEGER(0..1)" "ENUMERATED{foo}" NULL BOOLEAN \ + "BIT STRING" \ + "OBJECT IDENTIFIER" "RELATIVE-OID" \ + "SEQUENCE{f INTEGER}" \ + "CHOICE{f INTEGER}" \ + "OCTET STRING" IA5String "IA5String(SIZE(1))" UTF8String \ REAL "SET OF INTEGER" "SEQUENCE OF INTEGER"; do verify_type_with_variants "$type" @@ -69,6 +72,8 @@ else verify_type_with_variants "$type" done fi +set +x trap '' EXIT ERR cleanup +echo "OK" From 8ae074ce79cf0b8d628276e2d082813ae1c57f46 Mon Sep 17 00:00:00 2001 From: "Bi-Ruei, Chiu" Date: Thu, 9 Nov 2017 11:55:06 +0800 Subject: [PATCH 28/41] Fix 'make check' error under sample.source.RRC --- skeletons/asn_application.c | 2 +- skeletons/converter-example.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/skeletons/asn_application.c b/skeletons/asn_application.c index b8852ea65..3d834784a 100644 --- a/skeletons/asn_application.c +++ b/skeletons/asn_application.c @@ -204,7 +204,7 @@ asn_encode_to_new_buffer(const asn_codec_ctx_t *opt_codec_ctx, && (size_t)res.result.encoded != buf_key.computed_size) { ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE " yet produced %" ASN_PRI_SIZE " bytes", - er.encoded, buf_key.computed_size); + res.result.encoded, buf_key.computed_size); assert(res.result.encoded < 0 || (size_t)res.result.encoded == buf_key.computed_size); } diff --git a/skeletons/converter-example.c b/skeletons/converter-example.c index 2da07d064..b54045250 100644 --- a/skeletons/converter-example.c +++ b/skeletons/converter-example.c @@ -746,13 +746,13 @@ static void add_bytes_to_buffer(const void *data2add, size_t bytes) { static int is_syntax_PER(enum asn_transfer_syntax syntax) { - return (syntax != ATS_UNALIGNED_BASIC_PER - && syntax != ATS_UNALIGNED_CANONICAL_PER); + return (syntax == ATS_UNALIGNED_BASIC_PER + || syntax == ATS_UNALIGNED_CANONICAL_PER); } static int restartability_supported(enum asn_transfer_syntax syntax) { - return is_syntax_PER(syntax); + return !is_syntax_PER(syntax); } static void * From 0299037ed8dd7423c937a2d4e4928d81e85ffe16 Mon Sep 17 00:00:00 2001 From: "Bi-Ruei, Chiu" Date: Mon, 13 Nov 2017 00:34:27 +0800 Subject: [PATCH 29/41] Fix memory leakeage --- libasn1fix/asn1fix_retrieve.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libasn1fix/asn1fix_retrieve.c b/libasn1fix/asn1fix_retrieve.c index 40acbe5a4..75ba3f01b 100644 --- a/libasn1fix/asn1fix_retrieve.c +++ b/libasn1fix/asn1fix_retrieve.c @@ -286,6 +286,7 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t return NULL; } + DISPOSE_OF_MY_NAMESPACE(); my_namespace = asn1_namespace_new_from_module(imports_from, 1); DEBUG("Lookup (%s) in %s for line %d", asn1f_printable_reference(ref), asn1_namespace_string(my_namespace), ref->_lineno); @@ -341,6 +342,7 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t ref_tc->Identifier, asn1f_printable_reference(ref), ref->_lineno); errno = EPERM; + DISPOSE_OF_MY_NAMESPACE(); return NULL; } if(rhs_pspecs && ref_tc->lhs_params) { @@ -383,6 +385,7 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t asn1_namespace_string(arg->ns), asn1f_printable_reference(ref), ref->_lineno); errno = ETOOMANYREFS; + DISPOSE_OF_MY_NAMESPACE(); return NULL; } From 2a923864b9f2c1efd49b0793a8d75954f32d2f41 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Mon, 13 Nov 2017 22:24:27 -0800 Subject: [PATCH 30/41] invert -gen-PER as -no-gen-OER --- examples/sample.source.RRC/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/sample.source.RRC/Makefile b/examples/sample.source.RRC/Makefile index 9ddcc724c..dcf3f1d32 100644 --- a/examples/sample.source.RRC/Makefile +++ b/examples/sample.source.RRC/Makefile @@ -10,7 +10,7 @@ DL-DCCH-Message.c: ../sample.makefile.regen ../rrc-7.1.0.asn1 make regen-makefile: - ASN_CMDOPTS="-pdu=auto -fcompound-names -gen-PER" \ + ASN_CMDOPTS="-pdu=auto -fcompound-names -no-gen-OER" \ ASN_MODULES="../rrc-7.1.0.asn1" \ ASN_PDU=DL-DCCH-Message \ ASN_PROGRAM=rrc-dump \ From 076bbbc7abd4d82b593f6d10f2dfcbd936a57821 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Mon, 13 Nov 2017 22:29:46 -0800 Subject: [PATCH 31/41] invert -gen-xxx to -no-gen-yyy --- examples/sample.source.1609.2/Makefile | 2 +- examples/sample.source.J2735/Makefile | 2 +- examples/sample.source.LTE-RRC/Makefile | 2 +- examples/sample.source.ULP/Makefile | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/sample.source.1609.2/Makefile b/examples/sample.source.1609.2/Makefile index 9bb5387b6..14715be4a 100644 --- a/examples/sample.source.1609.2/Makefile +++ b/examples/sample.source.1609.2/Makefile @@ -11,7 +11,7 @@ Certificate.c: ../sample.makefile.regen ../IEEE-1609.2-2016.asn1 regen-makefile: TITLE="IEEE 1609.2-2016 decoder" \ - ASN_CMDOPTS="-pdu=auto -pdu=Ieee1609Dot2Data -fcompound-names -gen-OER" \ + ASN_CMDOPTS="-pdu=auto -pdu=Ieee1609Dot2Data -fcompound-names" \ ASN_MODULES="../IEEE-1609.2-2016.asn1" \ ASN_PDU=Certificate \ ASN_PROGRAM=1609-2-dump \ diff --git a/examples/sample.source.J2735/Makefile b/examples/sample.source.J2735/Makefile index efe9fa0b0..79570fe35 100644 --- a/examples/sample.source.J2735/Makefile +++ b/examples/sample.source.J2735/Makefile @@ -11,7 +11,7 @@ MessageFrame.c: ../sample.makefile.regen ../J2735_201603.asn1 regen-makefile: TITLE="J2735 DSRC decoder" \ - ASN_CMDOPTS="-fcompound-names -gen-PER -pdu=all" \ + ASN_CMDOPTS="-fcompound-names -pdu=auto" \ ASN_MODULES="../J2735_201603.asn1" \ ASN_PDU=MessageFrame \ ASN_PROGRAM=j2735-dump \ diff --git a/examples/sample.source.LTE-RRC/Makefile b/examples/sample.source.LTE-RRC/Makefile index d918a97b2..1c4b2bbd4 100644 --- a/examples/sample.source.LTE-RRC/Makefile +++ b/examples/sample.source.LTE-RRC/Makefile @@ -3608,7 +3608,7 @@ DL-DCCH-Message.c: ../sample.makefile.regen ../lte-rrc-14.2.1.asn1 make regen-makefile: - ASN_CMDOPTS="-pdu=auto -fcompound-names -gen-PER" \ + ASN_CMDOPTS="-pdu=auto -fcompound-names -no-gen-OER" \ ASN_MODULES="../lte-rrc-14.2.1.asn1" \ ASN_PDU=DL-DCCH-Message \ ASN_PROGRAM=lte-rrc-dump \ diff --git a/examples/sample.source.ULP/Makefile b/examples/sample.source.ULP/Makefile index 3e65fceaf..e666e3e98 100644 --- a/examples/sample.source.ULP/Makefile +++ b/examples/sample.source.ULP/Makefile @@ -11,7 +11,7 @@ ULP-PDU.c: ../sample.makefile.regen ../ulp.asn1 regen-makefile: TITLE="OMA UserPlane Location Protocol decoder" \ - ASN_CMDOPTS="-pdu=SUPLINIT -fcompound-names -gen-PER" \ + ASN_CMDOPTS="-pdu=SUPLINIT -fcompound-names -no-gen-OER" \ ASN_MODULES="../ulp.asn1" \ ASN_PDU=ULP-PDU \ ASN_PROGRAM=ulp-dump \ From e7bd48aa5e5c6328808a222a83b0dea1769b0fce Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Mon, 13 Nov 2017 23:12:49 -0800 Subject: [PATCH 32/41] better cleanup --- tests/tests-asn1c-smoke/check-asn1c-smoke.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/tests-asn1c-smoke/check-asn1c-smoke.sh b/tests/tests-asn1c-smoke/check-asn1c-smoke.sh index f374e67de..54edce334 100755 --- a/tests/tests-asn1c-smoke/check-asn1c-smoke.sh +++ b/tests/tests-asn1c-smoke/check-asn1c-smoke.sh @@ -8,7 +8,7 @@ top_builddir=${top_builddir:-../..} top_srcdir=${top_srcdir:-../..} cleanup() { - rm -rf *.[cho] Makefile.am.* *.txt *.asn + rm -rf *.[acho] Makefile.am.* *.txt *.asn rm -f converter-example } @@ -60,7 +60,6 @@ verify_compile_and_link_variants() { "OCTET STRING" IA5String "IA5String(SIZE(1))" UTF8String \ REAL "SET OF INTEGER" "SEQUENCE OF INTEGER"; do verify_type_with_variants "$type" - done } From d3fd7a4bdfa1eb8176c3bacabc6e3cdcd8acc177 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Mon, 13 Nov 2017 23:13:11 -0800 Subject: [PATCH 33/41] update dependencies --- skeletons/file-dependencies | 46 +++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/skeletons/file-dependencies b/skeletons/file-dependencies index 76bc30140..c150fb48c 100644 --- a/skeletons/file-dependencies +++ b/skeletons/file-dependencies @@ -1,37 +1,38 @@ # This file contains dependency information for the asn1c compiler's skeletons. # Feel free to edit this file. # The format is like this: -# ... +# # Include this file unconditionally +# ... # Include dependencies of . # -ANY.h ANY.c +ANY.h ANY.c OCTET_STRING.h OPEN_TYPE.h OPEN_TYPE.c constr_CHOICE.h -BMPString.h BMPString.c UTF8String.h +BMPString.h BMPString.c UTF8String.h OCTET_STRING.h BOOLEAN.h BOOLEAN.c ENUMERATED.h ENUMERATED.c INTEGER.h NativeEnumerated.h -GeneralString.h GeneralString.c -GeneralizedTime.h GeneralizedTime.c -GraphicString.h GraphicString.c -IA5String.h IA5String.c +GeneralString.h GeneralString.c OCTET_STRING.h +GeneralizedTime.h GeneralizedTime.c OCTET_STRING.h +GraphicString.h GraphicString.c OCTET_STRING.h +IA5String.h IA5String.c OCTET_STRING.h INTEGER.h INTEGER.c -ISO646String.h ISO646String.c +ISO646String.h ISO646String.c OCTET_STRING.h NULL.h NULL.c BOOLEAN.h NativeEnumerated.h NativeEnumerated.c NativeInteger.h NativeInteger.h NativeInteger.c INTEGER.h NativeReal.h NativeReal.c REAL.h -NumericString.h NumericString.c +NumericString.h NumericString.c OCTET_STRING.h OBJECT_IDENTIFIER.h OBJECT_IDENTIFIER.c INTEGER.h ObjectDescriptor.h ObjectDescriptor.c GraphicString.h -PrintableString.h PrintableString.c -REAL.h REAL.c INTEGER.h -RELATIVE-OID.h RELATIVE-OID.c OBJECT_IDENTIFIER.h -T61String.h T61String.c -TeletexString.h TeletexString.c -UTCTime.h UTCTime.c GeneralizedTime.h -UTF8String.h UTF8String.c -UniversalString.h UniversalString.c UTF8String.h -VideotexString.h VideotexString.c -VisibleString.h VisibleString.c +PrintableString.h PrintableString.c OCTET_STRING.h +REAL.h REAL.c INTEGER.h OCTET_STRING.h +RELATIVE-OID.h RELATIVE-OID.c OBJECT_IDENTIFIER.h OCTET_STRING.h +T61String.h T61String.c OCTET_STRING.h +TeletexString.h TeletexString.c OCTET_STRING.h +UTCTime.h UTCTime.c GeneralizedTime.h OCTET_STRING.h +UTF8String.h UTF8String.c OCTET_STRING.h +UniversalString.h UniversalString.c UTF8String.h OCTET_STRING.h +VideotexString.h VideotexString.c OCTET_STRING.h +VisibleString.h VisibleString.c OCTET_STRING.h asn_SEQUENCE_OF.h asn_SEQUENCE_OF.c asn_SET_OF.h asn_SET_OF.h asn_SET_OF.c constr_CHOICE.h constr_CHOICE.c @@ -48,8 +49,8 @@ asn_codecs.h # Return types of encoders and decoders asn_internal.h asn_internal.c # Internal stuff asn_random_fill.h asn_random_fill.c # Initialize with a random value asn_bit_data.h asn_bit_data.c # Bit streaming support -OCTET_STRING.h OCTET_STRING.c # This one is used too widely -BIT_STRING.h BIT_STRING.c # This one is necessary for the above one +OCTET_STRING.h OCTET_STRING.c +BIT_STRING.h BIT_STRING.c OCTET_STRING.h asn_codecs_prim.c asn_codecs_prim.h # enc/decoders for primitive types ber_tlv_length.h ber_tlv_length.c # BER TLV L (length) ber_tlv_tag.h ber_tlv_tag.c # BER TLV T (tag) @@ -77,7 +78,8 @@ oer_encoder.h oer_encoder.c oer_support.h oer_support.c OPEN_TYPE.h OPEN_TYPE_oer.c constr_CHOICE.h INTEGER.h INTEGER_oer.c -BIT_STRING.h BIT_STRING_oer.c OCTET_STRING_oer.c +BIT_STRING.h BIT_STRING_oer.c +OCTET_STRING.h OCTET_STRING_oer.c NativeInteger.h NativeInteger_oer.c NativeEnumerated.h NativeEnumerated_oer.c constr_CHOICE.h constr_CHOICE_oer.c From f09cf4888d77877db219bffba1f3648949d0ada6 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Mon, 13 Nov 2017 23:16:06 -0800 Subject: [PATCH 34/41] update dependencies --- skeletons/file-dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skeletons/file-dependencies b/skeletons/file-dependencies index c150fb48c..0bfa12795 100644 --- a/skeletons/file-dependencies +++ b/skeletons/file-dependencies @@ -78,7 +78,7 @@ oer_encoder.h oer_encoder.c oer_support.h oer_support.c OPEN_TYPE.h OPEN_TYPE_oer.c constr_CHOICE.h INTEGER.h INTEGER_oer.c -BIT_STRING.h BIT_STRING_oer.c +BIT_STRING.h BIT_STRING_oer.c OCTET_STRING.h OCTET_STRING.h OCTET_STRING_oer.c NativeInteger.h NativeInteger_oer.c NativeEnumerated.h NativeEnumerated_oer.c From f9a94dfa1d9a8c98e12bbd7f61eb613f2841a2c8 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Mon, 13 Nov 2017 23:23:19 -0800 Subject: [PATCH 35/41] update dependencies --- skeletons/file-dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skeletons/file-dependencies b/skeletons/file-dependencies index 0bfa12795..59e2ce68f 100644 --- a/skeletons/file-dependencies +++ b/skeletons/file-dependencies @@ -21,7 +21,7 @@ NativeEnumerated.h NativeEnumerated.c NativeInteger.h NativeInteger.h NativeInteger.c INTEGER.h NativeReal.h NativeReal.c REAL.h NumericString.h NumericString.c OCTET_STRING.h -OBJECT_IDENTIFIER.h OBJECT_IDENTIFIER.c INTEGER.h +OBJECT_IDENTIFIER.h OBJECT_IDENTIFIER.c INTEGER.h OCTET_STRING.h ObjectDescriptor.h ObjectDescriptor.c GraphicString.h PrintableString.h PrintableString.c OCTET_STRING.h REAL.h REAL.c INTEGER.h OCTET_STRING.h From 288e95d5b11ebcd1f359bb9412c613b7d591d0e6 Mon Sep 17 00:00:00 2001 From: "Bi-Ruei, Chiu" Date: Tue, 14 Nov 2017 15:16:24 +0800 Subject: [PATCH 36/41] Fix crash when processing S1AP Ref : https://github.com/vlm/asn1c/pull/237#issuecomment-342356046 --- libasn1fix/asn1fix_retrieve.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libasn1fix/asn1fix_retrieve.c b/libasn1fix/asn1fix_retrieve.c index 75ba3f01b..16f5c1c3e 100644 --- a/libasn1fix/asn1fix_retrieve.c +++ b/libasn1fix/asn1fix_retrieve.c @@ -63,8 +63,8 @@ asn1f_lookup_in_imports(arg_t *arg, asn1p_module_t *mod, const char *name) { if(!fromModule) continue; - asn1p_expr_t *v = v = - asn1f_lookup_in_module(fromModule, tc->Identifier); + asn1p_expr_t *v = + asn1f_lookup_in_module(fromModule, name); if(v) break; } if(tc) break; From 304a70e9acd1d670365870f7fe9c3bfacc16d877 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Mon, 13 Nov 2017 23:28:28 -0800 Subject: [PATCH 37/41] remove warnings --- skeletons/constr_SET_OF.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c index 565c8e49e..96c5c09ea 100644 --- a/skeletons/constr_SET_OF.c +++ b/skeletons/constr_SET_OF.c @@ -320,7 +320,6 @@ static int _el_buf_cmp(const void *ap, const void *bp) { else common_len = b->length; - //constr_SET_OF.c:315:13: runtime error: null pointer passed as argument 1, which is declared to never be null if (a->buf && b->buf) { ret = memcmp(a->buf, b->buf, common_len); } @@ -489,8 +488,8 @@ SET_OF_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr, SET_OF__encode_sorted_free(encoded_els, list->count); if(edx == list->count) { - assert(computed_size == (size_t)encoding_size); asn_enc_rval_t erval; + assert(computed_size == (size_t)encoding_size); erval.encoded = computed_size; ASN__ENCODED_OK(erval); } else { From d0ee2b143613a1629317d8c8da6e2b60865d955b Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Tue, 14 Nov 2017 00:07:05 -0800 Subject: [PATCH 38/41] rename a bit for consistency --- libasn1compiler/asn1c_fdeps.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libasn1compiler/asn1c_fdeps.c b/libasn1compiler/asn1c_fdeps.c index ed8af9bc2..60a52cbb9 100644 --- a/libasn1compiler/asn1c_fdeps.c +++ b/libasn1compiler/asn1c_fdeps.c @@ -1,15 +1,15 @@ #include "asn1c_internal.h" #include "asn1c_fdeps.h" -static asn1c_dep_filename *asn1c_new_dep_filename(const char *filename); +static asn1c_dep_filename *asn1c_dep_filename_new(const char *filename); static void asn1c_dep_add(asn1c_dep_chain *dlist, const char *filename, int lineno, int column); -static asn1c_dep_chain *asn1c_new_dep_chain(); +static asn1c_dep_chain *asn1c_dep_chain_new(void); static asn1c_dep_chain * asn1c_dep_chains_add_new(asn1c_dep_chainset *deps, enum asn1c_dep_section section, int active) { - asn1c_dep_chain *dc = asn1c_new_dep_chain(); + asn1c_dep_chain *dc = asn1c_dep_chain_new(); asn1c_tagged_dep_chain *tc = calloc(1, sizeof(*tc)); tc->chain = dc; tc->section = section; @@ -150,7 +150,7 @@ asn1c_read_file_dependencies(arg_t *arg, const char *datadir) { } static asn1c_dep_filename * -asn1c_new_dep_filename(const char *filename) { +asn1c_dep_filename_new(const char *filename) { asn1c_dep_filename *d; assert(filename); @@ -164,13 +164,13 @@ asn1c_new_dep_filename(const char *filename) { } static asn1c_dep_chain * -asn1c_new_dep_chain() { +asn1c_dep_chain_new() { return calloc(1, sizeof(asn1c_dep_chain)); } static void asn1c_dep_add(asn1c_dep_chain *dlist, const char *filename, int lineno, int column) { - asn1c_dep_filename *df = asn1c_new_dep_filename(filename); + asn1c_dep_filename *df = asn1c_dep_filename_new(filename); df->lineno = lineno; df->column = column; @@ -201,7 +201,7 @@ asn1c_deps_flatten(const asn1c_dep_chainset *deps, return 0; } - dlist = asn1c_new_dep_chain(); + dlist = asn1c_dep_chain_new(); for(size_t i = 0; i < deps->chains_count; i++) { asn1c_tagged_dep_chain *tc = deps->chains[i]; From 37b579919d2c6f46c6530cd0c1eea4bb5e54821a Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Tue, 14 Nov 2017 21:13:21 -0800 Subject: [PATCH 39/41] updated doc --- doc/asn1c-usage.pdf | Bin 244231 -> 244236 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/asn1c-usage.pdf b/doc/asn1c-usage.pdf index f802f0ffbca44ef81a00eeddd86fa2eb74e81522..1c585ca68e604f722db04e9732d66b094334d09b 100644 GIT binary patch delta 4877 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 delta 4946 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 Date: Tue, 14 Nov 2017 22:00:57 -0800 Subject: [PATCH 40/41] constness fix --- skeletons/asn_application.c | 4 ++-- skeletons/asn_application.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/skeletons/asn_application.c b/skeletons/asn_application.c index 3d834784a..8ce0261b8 100644 --- a/skeletons/asn_application.c +++ b/skeletons/asn_application.c @@ -131,8 +131,8 @@ callback_failure_catch_cb(const void *data, size_t size, void *keyp) { asn_enc_rval_t asn_encode(const asn_codec_ctx_t *opt_codec_ctx, - enum asn_transfer_syntax syntax, asn_TYPE_descriptor_t *td, - void *sptr, asn_app_consume_bytes_f *callback, void *callback_key) { + enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td, + const void *sptr, asn_app_consume_bytes_f *callback, void *callback_key) { struct callback_failure_catch_key cb_key; asn_enc_rval_t er; diff --git a/skeletons/asn_application.h b/skeletons/asn_application.h index acc91ab7f..3ca9f138e 100644 --- a/skeletons/asn_application.h +++ b/skeletons/asn_application.h @@ -129,8 +129,8 @@ typedef int(asn_app_consume_bytes_f)(const void *buffer, size_t size, asn_enc_rval_t asn_encode( const asn_codec_ctx_t *opt_codec_parameters, /* See asn_codecs.h */ enum asn_transfer_syntax, - struct asn_TYPE_descriptor_s *type_to_encode, - void *structure_to_encode, + const struct asn_TYPE_descriptor_s *type_to_encode, + const void *structure_to_encode, asn_app_consume_bytes_f *callback, void *callback_key); From 07f8c3eaf5face938f792b9bb1bc893bc6687e47 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Wed, 15 Nov 2017 00:21:51 -0800 Subject: [PATCH 41/41] add asn_encode* and other encoders --- doc/docsrc/asn1c-usage.tex | 531 +++++++++++++++++++++++++++++++----- doc/docsrc/asn_dec_rval.inc | 6 +- doc/docsrc/asn_enc_rval.inc | 17 ++ 3 files changed, 481 insertions(+), 73 deletions(-) create mode 100644 doc/docsrc/asn_enc_rval.inc diff --git a/doc/docsrc/asn1c-usage.tex b/doc/docsrc/asn1c-usage.tex index fe2cb4ae4..cdcd3ee9e 100644 --- a/doc/docsrc/asn1c-usage.tex +++ b/doc/docsrc/asn1c-usage.tex @@ -76,6 +76,7 @@ \lstnewenvironment{bash}[1][]{\lstset{style=listingStyle,language=bash,#1}}{} \lstnewenvironment{asn}[1][]{\lstset{style=listingStyle,language=asn1,#1}}{} +\newcommand{\apisection}[2]{\clearpage\section{\label{#1}#2}} \newcommand{\api}[2]{\hyperref[#1]{\code{#2}}} \newcommand{\seealso}[2]{\api{#1}{#2} at page \pageref{#1}} \newcommand{\code}[1]{\texttt{\textbf{\lstinline{#1}}}} @@ -577,8 +578,7 @@ \chapter{API reference} The API calls not listed here are not public and should not be used by the application level code. -\clearpage{} -\section{\label{sec:ASN_STRUCT_FREE}ASN\_STRUCT\_FREE() macro} +\apisection{sec:ASN_STRUCT_FREE}{ASN\_STRUCT\_FREE() macro} \subsection*{Synopsis} @@ -604,7 +604,7 @@ \subsection*{Example} ASN_STRUCT_FREE(asn_DEF_Rectangle, rect); \end{example} -\section{\label{sec:ASN_STRUCT_RESET}ASN\_STRUCT\_RESET() macro} +\apisection{sec:ASN_STRUCT_RESET}{ASN\_STRUCT\_RESET() macro} \subsection*{Synopsis} @@ -640,7 +640,7 @@ \subsection*{Example} ASN_STRUCT_RESET(asn_DEF_Rectangle, &fig->rect); \end{example} -\section{asn\_check\_constraints()} +\apisection{sec:asn_check_constraints}{asn\_check\_constraints()} \subsection*{Synopsis} @@ -655,12 +655,13 @@ \subsection*{Synopsis} \subsection*{Description} -Validate the structure according to the ASN.1 constraints. -If errbuf and errlen are given, they shall be pointing to the appropriate -buffer space and its length before calling this function. Alternatively, -they could be passed as NULLs. If constraints validation fails, -errlen will contain the actual number of bytes used in errbuf -to encode an error message, properly 0-terminated. +Validate a given structure according to the ASN.1 constraints. +If \code{errbuf} and \code{errlen} are given, they shall point to the +appropriate buffer space and its length before calling this function. +Alternatively, they could be passed as \code{NULL}s. +If constraints validation fails, \code{errlen} will contain the actual +number of bytes used in \code{errbuf} to encode an error message. +The message is going to be properly 0-terminated. \subsection*{Return values} @@ -682,12 +683,12 @@ \subsection*{Example} } \end{codesample} -\section{\label{sec:asn_decode}asn\_decode()} +\apisection{sec:asn_decode}{asn\_decode()} \subsection*{Synopsis} \begin{signature} asn_dec_rval_t asn_decode( - const asn_codec_ctx_t *opt_codec_parameters, + const asn_codec_ctx_t *opt_codec_ctx, enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *type_descriptor, void **struct_ptr_ptr,/* Pointer to a target structure's ptr */ @@ -757,27 +758,178 @@ \subsection*{Example} \subsection*{See also} \seealso{sec:asn_fprint}{asn_fprint()}. -\section{\label{sec:asn_encode}asn\_encode()} -\section{asn\_encode\_to\_buffer} +\apisection{sec:asn_encode}{asn\_encode()} + +\subsection*{Synopsis} + +\begin{signature} +#include + +asn_enc_rval_t asn_encode( + const asn_codec_ctx_t *opt_codec_ctx, + enum asn_transfer_syntax syntax, + const asn_TYPE_descriptor_t *type_to_encode, + const void *structure_to_encode, + asn_app_consume_bytes_f *callback, void *callback_key); +\end{signature} + +\subsection*{Description} + +The \code{asn_encode()} function serializes the given \code{structure_to_encode} using the chosen ASN.1 transfer \code{syntax}. + +During serialization, a user-specified \code{callback} is invoked zero +or more times with bytes of data to add to the output stream (if any), and +the \code{callback_key}. The signature for the callback is as follows: + +\begin{signature} +typedef int(asn_app_consume_bytes_f)(const void *buffer, size_t size, void *callback_key); +\end{signature} + +\subsection*{Return values} +\input{asn_enc_rval.inc} + +The serialized output size is returned in \textbf{bytes} irrespectively of the +ASN.1 transfer \code{syntax} chosen.\footnote{This is different from some +lower level encoding functions, such as \api{sec:uper_encode}{uper_encode()}, +which returns the number of encoded \emph{bits} instead of bytes.} + +On error (when \code{.encoded} is set to -1), +the \code{errno} is set to one of the following values: + +\begin{tabular}[h!]{ll} +\texttt{EINVAL} & Incorrect parameters to the function, such as NULLs \\ +\texttt{ENOENT} & Encoding transfer syntax is not defined (for this type) \\ +\texttt{EBADF} & The structure has invalid form or content constraint failed \\ +\texttt{EIO} & The callback has returned negative value during encoding +\end{tabular} \subsection*{Example} \begin{example} +static int +save_to_file(const void *data, size_t size, void *key) { + FILE *fp = key; + return (fwrite(data, 1, size, fp) == size) ? 0 : -1; +} + +Rectangle_t *rect = ...; +FILE *fp = ...; +asn_enc_rval_t er; +er = asn_encode(0, ATS_DER, &asn_DEF_Rectangle, rect, save_to_file, fp); +if(er.encoded == -1) { + fprintf(stderr, "Failed to encode %\%%s\n", asn_DEF_Rectangle.name); +} else { + fprintf(stderr, "%\%%s encoded in %\%%zd bytes\n", asn_DEF_Rectangle.name, er.encoded); +} +\end{example} + +\apisection{sec:asn_encode_to_buffer}{asn\_encode\_to\_buffer()} + +\subsection*{Synopsis} + +\begin{signature} +#include + +asn_enc_rval_t asn_encode_to_buffer( + const asn_codec_ctx_t *opt_codec_ctx, + enum asn_transfer_syntax syntax, + const asn_TYPE_descriptor_t *type_to_encode, + const void *structure_to_encode, + void *buffer, size_t buffer_size); +\end{signature} + +\subsection*{Description} + +The \code{asn_encode_to_buffer()} function serializes the given \code{structure_to_encode} using the chosen ASN.1 transfer \code{syntax}. + +The function places the serialized data into the given +\code{buffer} of size \code{buffer_size}. + +\subsection*{Return values} +\input{asn_enc_rval.inc} + +The serialized output size is returned in \textbf{bytes} irrespectively of the +ASN.1 transfer \code{syntax} chosen.\footnote{This is different from some +lower level encoding functions, such as \api{sec:uper_encode}{uper_encode()}, +which returns the number of encoded \emph{bits} instead of bytes.} + +If \code{.encoded} size exceeds the specified \code{buffer_size}, +the serialization effectively failed due to insufficient space. The function +will succeed if subsequently called with buffer size no less than the returned +\code{.encoded} size. This behavior modeled after \code{snprintf()}. + +On error (when \code{.encoded} is set to -1), +the \code{errno} is set to one of the following values: + +\begin{tabular}[h!]{ll} +\texttt{EINVAL} & Incorrect parameters to the function, such as NULLs \\ +\texttt{ENOENT} & Encoding transfer syntax is not defined (for this type) \\ +\texttt{EBADF} & The structure has invalid form or content constraint failed +\end{tabular} + +\subsection*{Example} +\begin{example} +Rectangle_t *rect = ...; uint8_t buffer[128]; -size_t buf_size = sizeof(buffer); asn_enc_rval_t er; -er = asn_encode_to_buffer(0, ATS_DER, &asn_DEF_Rectangle, buffer, buf_size); -if(er.encoded > buf_size) { +er = asn_encode_to_buffer(0, ATS_DER, &asn_DEF_Rectangle, rect, buffer, sizeof(buffer)); +if(er.encoded == -1) { + fprintf(stderr, "Serialization of %\%%s failed.\n", asn_DEF_Rectangle.name); +} else if(er.encoded > sizeof(buffer)) { fprintf(stderr, "Buffer of size %\%%zu is too small for %\%%s, need %\%%zu\n", buf_size, asn_DEF_Rectangle.name, er.encoded); } \end{example} -\section{asn\_encode\_to\_new\_buffer} +\subsection*{See also} +\seealso{sec:asn_encode_to_new_buffer}{asn_encode_to_new_buffer()}. + +\apisection{sec:asn_encode_to_new_buffer}{asn\_encode\_to\_new\_buffer()} + +\subsection*{Synopsis} + +\begin{signature} +#include + +typedef struct { + void *buffer; /* NULL if failed to encode. */ + asn_enc_rval_t result; +} asn_encode_to_new_buffer_result_t; +asn_encode_to_new_buffer_result_t asn_encode_to_new_buffer( + const asn_codec_ctx_t *opt_codec_ctx, + enum asn_transfer_syntax syntax, + const asn_TYPE_descriptor_t *type_to_encode, + const void *structure_to_encode); +\end{signature} + +\subsection*{Description} + +The \code{asn_encode_to_new_buffer()} function serializes the given \code{structure_to_encode} using the chosen ASN.1 transfer \code{syntax}. + +The function places the serialized data into the newly allocated buffer +which it returns in a compound structure. + +\subsection*{Return values} + +On failure, the \code{.buffer} is set to \code{NULL} +and \code{.result.encoded} is set to -1. The global \code{errno} is set +to one of the following values: + +\begin{tabular}[h!]{ll} +\texttt{EINVAL} & Incorrect parameters to the function, such as NULLs \\ +\texttt{ENOENT} & Encoding transfer syntax is not defined (for this type) \\ +\texttt{EBADF} & The structure has invalid form or content constraint failed \\ +\texttt{ENOMEM} & Memory allocation failed due to system or internal limits +\end{tabular} + +\noindent{}On success, the \code{.result.encoded} is set to the number of +\textbf{bytes} that it took to serialize the structure. +The \code{.buffer} contains the serialized content. +The user is responsible for freeing the \code{.buffer}. \subsection*{Example} \begin{example} asn_encode_to_new_buffer_result_t res; -res = asn_encode_to_new_buffer(0, ATS_DER, &asn_DEF_Rectangle, buffer, buf_size); +res = asn_encode_to_new_buffer(0, ATS_DER, &asn_DEF_Rectangle, rect); if(res.buffer) { /* Encoded successfully. */ free(res.buffer); @@ -787,7 +939,10 @@ \subsection*{Example} } \end{example} -\section{\label{sec:asn_fprint}asn\_fprint()} +\subsection*{See also} +\seealso{sec:asn_encode_to_buffer}{asn_encode_to_buffer()}. + +\apisection{sec:asn_fprint}{asn\_fprint()} \subsection*{Synopsis} \begin{signature} @@ -826,7 +981,7 @@ \subsection*{Example} \subsection*{See also} \seealso{sec:xer_fprint}{xer_fprint()}. -\section{\label{sec:asn_random_fill}asn\_random\_fill()} +\apisection{sec:asn_random_fill}{asn\_random\_fill()} \subsection*{Synopsis} \begin{signature} @@ -864,8 +1019,7 @@ \subsection*{Return values} -1 & Failure to initialize the structure with random data \end{tabular} -\clearpage{} -\section{\label{sec:ber_decode}ber\_decode()} +\apisection{sec:ber_decode}{ber\_decode()} \subsection*{Synopsis} \begin{signature} @@ -884,9 +1038,9 @@ \subsection*{Description} (Basic Encoding Rules, Distinguished Encoding Rules, Canonical Encoding Rules), as defined by ITU-T~X.690. -DER and CER are different subsets of BER. +DER and CER are different subsets of BER.\newline -Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_BER)}. +\noindent\emph{Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_BER)}.} \subsection*{Return values} \input{asn_dec_rval.inc} @@ -907,16 +1061,107 @@ \subsection*{Restartability} \subsection*{See also} \seealso{sec:der_encode}{der_encode()}. -\section{\label{sec:der_encode}der\_encode} +\apisection{sec:der_encode}{der\_encode} + +\subsection*{Synopsis} + +\begin{signature} +asn_enc_rval_t der_encode( + const asn_TYPE_descriptor_t *type_descriptor, + const void *structure_to_encode, + asn_app_consume_bytes_f *callback, + void *callback_key +\end{signature} + +\subsection*{Description} + +The \code{der_encode()} function serializes the given \code{structure_to_encode} using the DER transfer syntax (a variant of BER, Basic Encoding Rules). + +During serialization, a user-specified \code{callback} is invoked zero +or more times with bytes of data to add to the output stream (if any), and +the \code{callback_key}. The signature for the callback is as follows: + +\begin{signature} +typedef int(asn_app_consume_bytes_f)(const void *buffer, size_t size, void *callback_key); +\end{signature} + +\noindent\emph{Consider using a more generic function \api{sec:asn_encode}{asn_encode(ATS_DER)}.} + +\subsection*{Return values} +\input{asn_enc_rval.inc} + +The serialized output size is returned in \textbf{bytes}. + +\subsection*{Example} +\begin{example} +static int +save_to_file(const void *data, size_t size, void *key) { + FILE *fp = key; + return (fwrite(data, 1, size, fp) == size) ? 0 : -1; +} + +Rectangle_t *rect = ...; +FILE *fp = ...; +asn_enc_rval_t er; +er = der_encode(&asn_DEF_Rectangle, rect, save_to_file, fp); +if(er.encoded == -1) { + fprintf(stderr, "Failed to encode %\%%s\n", asn_DEF_Rectangle.name); +} else { + fprintf(stderr, "%\%%s encoded in %\%%zd bytes\n", asn_DEF_Rectangle.name, er.encoded); +} +\end{example} \subsection*{See also} \seealso{sec:ber_decode}{ber_decode()}, \seealso{sec:asn_decode}{asn_decode(ATS_BER)}. -\section{der\_encode\_to\_buffer} +\apisection{sec:der_encode_to_buffer}{der\_encode\_to\_buffer()} -\clearpage{} -\section{\label{sec:oer_decode}oer\_decode()} +\subsection*{Synopsis} + +\begin{signature} +asn_enc_rval_t der_encode_to_buffer( + const asn_TYPE_descriptor_t *type_descriptor, + const void *structure_to_encode, + void *buffer, size_t buffer_size); +\end{signature} + +\subsection*{Description} + +The \code{der_encode_to_buffer()} function serializes the given \code{structure_to_encode} using the DER transfer syntax (a variant of BER, Basic Encoding Rules). + +The function places the serialized data into the given +\code{buffer} of size \code{buffer_size}.\newline + +\noindent\emph{Consider using a more generic function \api{sec:asn_encode_to_buffer}{asn_encode_to_buffer(ATS_DER)}.} + +\subsection*{Return values} +\input{asn_enc_rval.inc} + +The serialized output size is returned in \textbf{bytes}. + +The \code{.encoded} never exceeds the available buffer size.\footnote{This +behavior is different from \api{sec:asn_encode_to_buffer}{asn_encode_to_buffer()}.} +If the \code{buffer_size} is not sufficient, the \code{.encoded} +will be set to -1 and encoding would fail. + +\subsection*{Example} +\begin{example} +Rectangle_t *rect = ...; +uint8_t buffer[128]; +asn_enc_rval_t er; +er = der_encode_to_buffer(&asn_DEF_Rectangle, rect, buffer, sizeof(buffer)); +if(er.encoded == -1) { + fprintf(stderr, "Serialization of %\%%s failed.\n", asn_DEF_Rectangle.name); +} +\end{example} + +\subsection*{See also} +\seealso{sec:ber_decode}{ber_decode()}, +\seealso{sec:asn_decode}{asn_decode(ATS_BER)}, +\seealso{sec:asn_encode_to_buffer}{asn_encode_to_buffer(ATS_DER)}. + +\apisection{sec:oer_decode}{oer\_decode()} \subsection*{Synopsis} \begin{signature} @@ -932,9 +1177,9 @@ \subsection*{Synopsis} \subsection*{Description} Decode the BASIC-OER and CANONICAL-OER (Octet Encoding Rules), -as defined by ITU-T~X.696. +as defined by ITU-T~X.696.\newline -Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_BASIC_OER)}. +\noindent\emph{Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_BASIC_OER)}.} \subsection*{Return values} \input{asn_dec_rval.inc} @@ -952,11 +1197,107 @@ \subsection*{Restartability} it is available in the buffer, which means that you must be able to arrange the next buffer to contain the unprocessed part of the previous buffer. -\section{\label{sec:oer_encode}oer\_encode} -\section{oer\_encode\_to\_buffer} +\apisection{sec:oer_encode}{oer\_encode()} -\clearpage{} -\section{\label{sec:uper_decode}uper\_decode()} +\subsection*{Synopsis} + +\begin{signature} +asn_enc_rval_t oer_encode( + const asn_TYPE_descriptor_t *type_descriptor, + const void *structure_to_encode, + asn_app_consume_bytes_f *callback, + void *callback_key); +\end{signature} + +\subsection*{Description} + +The \code{oer_encode()} function serializes the given \code{structure_to_encode} using the CANONICAL-OER transfer syntax (Octet Encoding Rules, ITU-T~X.691). + +During serialization, a user-specified \code{callback} is invoked zero +or more times with bytes of data to add to the output stream (if any), and +the \code{callback_key}. The signature for the callback is as follows: + +\begin{signature} +typedef int(asn_app_consume_bytes_f)(const void *buffer, size_t size, void *callback_key); +\end{signature} + +\noindent\emph{Consider using a more generic function \api{sec:asn_encode}{asn_encode(ATS_CANONICAL_OER)}.} + +\subsection*{Return values} +\input{asn_enc_rval.inc} + +The serialized output size is returned in \textbf{bytes}. + +\subsection*{Example} +\begin{example} +static int +save_to_file(const void *data, size_t size, void *key) { + FILE *fp = key; + return (fwrite(data, 1, size, fp) == size) ? 0 : -1; +} + +Rectangle_t *rect = ...; +FILE *fp = ...; +asn_enc_rval_t er; +er = oer_encode(&asn_DEF_Rectangle, rect, save_to_file, fp); +if(er.encoded == -1) { + fprintf(stderr, "Failed to encode %\%%s\n", asn_DEF_Rectangle.name); +} else { + fprintf(stderr, "%\%%s encoded in %\%%zd bytes\n", asn_DEF_Rectangle.name, er.encoded); +} +\end{example} + +\subsection*{See also} +\seealso{sec:asn_encode}{asn_encode(ATS_CANONICAL_OER)}. + +\apisection{sec:oer_encode_to_buffer}{oer\_encode\_to\_buffer()} + +\subsection*{Synopsis} + +\begin{signature} +asn_enc_rval_t oer_encode_to_buffer( + const asn_TYPE_descriptor_t *type_descriptor, + const asn_oer_constraints_t *constraints, + const void *structure_to_encode, + void *buffer, size_t buffer_size); +\end{signature} + +\subsection*{Description} + +The \code{oer_encode_to_buffer()} function serializes the given \code{structure_to_encode} using the CANONICAL-OER transfer syntax (Octet Encoding Rules, ITU-T~X.691). + +The function places the serialized data into the given +\code{buffer} of size \code{buffer_size}.\newline + +\noindent\emph{Consider using a more generic function \api{sec:asn_encode_to_buffer}{asn_encode_to_buffer(ATS_CANONICAL_OER)}.} + +\subsection*{Return values} +\input{asn_enc_rval.inc} + +The serialized output size is returned in \textbf{bytes}. + +The \code{.encoded} never exceeds the available buffer size.\footnote{This +behavior is different from \api{sec:asn_encode_to_buffer}{asn_encode_to_buffer()}.} +If the \code{buffer_size} is not sufficient, the \code{.encoded} +will be set to -1 and encoding would fail. + +\subsection*{Example} +\begin{example} +Rectangle_t *rect = ...; +uint8_t buffer[128]; +asn_enc_rval_t er; +er = oer_encode_to_buffer(&asn_DEF_Rectangle, 0, rect, buffer, sizeof(buffer)); +if(er.encoded == -1) { + fprintf(stderr, "Serialization of %\%%s failed.\n", asn_DEF_Rectangle.name); +} +\end{example} + +\subsection*{See also} +\seealso{sec:ber_decode}{ber_decode()}, +\seealso{sec:asn_decode}{asn_decode(ATS_BER)}, +\seealso{sec:asn_encode_to_buffer}{asn_encode_to_buffer(ATS_DER)}. + +\apisection{sec:uper_decode}{uper\_decode()} \subsection*{Synopsis} @@ -975,9 +1316,9 @@ \subsection*{Synopsis} \subsection*{Description} Decode the Unaligned BASIC or CANONICAL PER (Packed Encoding Rules), -as defined by ITU-T~X.691 +as defined by ITU-T~X.691.\newline -Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_UNALIGNED_BASIC_PER)}. +\noindent\emph{Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_UNALIGNED_BASIC_PER)}.} \subsection*{Return values} \input{asn_dec_rval.inc} @@ -988,7 +1329,7 @@ \subsection*{Restartability} The \code{uper_decode()} function is not restartable. Failures are final. -\section{uper\_decode\_complete()} +\apisection{sec:uper_decode_complete}{uper\_decode\_complete()} \subsection*{Synopsis} @@ -1005,14 +1346,14 @@ \subsection*{Synopsis} \subsection*{Description} Decode a ``Production of a complete encoding'', -according to ITU-T~X.691 (08/2015) \#11.1. +according to ITU-T~X.691 (08/2015) \#11.1.\newline -Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_UNALIGNED_BASIC_PER)}. +\noindent\emph{Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_UNALIGNED_BASIC_PER)}.} \subsection*{Return values} \input{asn_dec_rval.inc} -The the \code{.consumed} value is returned in bytes. +The the \code{.consumed} value is returned in whole \emph{bytes} (NB). \subsection*{Restartability} The \code{uper_decode_complete()} function is not restartable. @@ -1021,11 +1362,10 @@ \subsection*{Restartability} The complete encoding contains at least one byte, so on success \code{.consumed} will be greater or equal to 1. -\section{\label{sec:uper_encode}uper\_encode} -\section{uper\_encode\_to\_buffer} -\section{uper\_encode\_to\_new\_buffer} -\clearpage{} -\section{\label{sec:xer_decode}xer\_decode()} +\apisection{sec:uper_encode}{uper\_encode()} +\apisection{sec:uper_encode_to_buffer}{uper\_encode\_to\_buffer()} +\apisection{sec:uper_encode_to_new_buffer}{uper\_encode\_to\_new\_buffer()} +\apisection{sec:xer_decode}{xer\_decode()} \subsection*{Synopsis} @@ -1042,9 +1382,9 @@ \subsection*{Synopsis} \subsection*{Description} Decode the BASIC-XER and CANONICAL-XER (XML Encoding Rules) encoding, -as defined by ITU-T~X.693. +as defined by ITU-T~X.693.\newline -Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_BASIC_XER)}. +\noindent\emph{Consider using a more generic function \api{sec:asn_decode}{asn_decode(ATS_BASIC_XER)}.} \subsection*{Return values} \input{asn_dec_rval.inc} @@ -1062,8 +1402,66 @@ \subsection*{Restartability} it is available in the buffer, which means that you must be able to arrange the next buffer to contain the unprocessed part of the previous buffer. -\section{\label{sec:xer_encode}xer\_encode} -\section{\label{sec:xer_fprint}xer\_fprint()} +\apisection{sec:xer_encode}{xer\_encode()} + +\subsection*{Synopsis} + +\begin{signature} +enum xer_encoder_flags_e { + /* Mode of encoding */ + XER_F_BASIC = 0x01, /* BASIC-XER (pretty-printing) */ + XER_F_CANONICAL = 0x02 /* Canonical XER (strict rules) */ +}; +asn_enc_rval_t xer_encode( + const asn_TYPE_descriptor_t *type_descriptor, + const void *structure_to_encode, + enum xer_encoder_flags_e xer_flags, + asn_app_consume_bytes_f *callback, + void *callback_key); +\end{signature} + +\subsection*{Description} + +The \code{xer_encode()} function serializes the given \code{structure_to_encode} using the BASIC-XER or CANONICAL-XER transfer syntax (XML Encoding Rules, ITU-T~X.693). + +During serialization, a user-specified \code{callback} is invoked zero +or more times with bytes of data to add to the output stream (if any), and +the \code{callback_key}. The signature for the callback is as follows: + +\begin{signature} +typedef int(asn_app_consume_bytes_f)(const void *buffer, size_t size, void *callback_key); +\end{signature} + +\noindent\emph{Consider using a more generic function \api{sec:asn_encode}{asn_encode()} with \texttt{ATS\_BASIC\_XER} or \texttt{ATS\_CANONICAL\_XER} transfer syntax option.} + +\subsection*{Return values} +\input{asn_enc_rval.inc} + +The serialized output size is returned in \textbf{bytes}. + +\subsection*{Example} +\begin{example} +static int +save_to_file(const void *data, size_t size, void *key) { + FILE *fp = key; + return (fwrite(data, 1, size, fp) == size) ? 0 : -1; +} + +Rectangle_t *rect = ...; +FILE *fp = ...; +asn_enc_rval_t er; +er = xer_encode(&asn_DEF_Rectangle, rect, XER_F_CANONICAL, save_to_file, fp); +if(er.encoded == -1) { + fprintf(stderr, "Failed to encode %\%%s\n", asn_DEF_Rectangle.name); +} else { + fprintf(stderr, "%\%%s encoded in %\%%zd bytes\n", asn_DEF_Rectangle.name, er.encoded); +} +\end{example} + +\subsection*{See also} +\seealso{sec:xer_fprint}{xer_fprint()}. + +\apisection{sec:xer_fprint}{xer\_fprint()} \subsection*{Synopsis} \begin{signature} @@ -1079,7 +1477,7 @@ \subsection*{Description} of the given structure into the file stream specified by \code{stream} pointer. -The output conforms to BASIC-XER, as defined by ITU-T~X.693. +The output conforms to a BASIC-XER transfer syntax, as defined by ITU-T~X.693. \subsection*{Return values} @@ -1318,7 +1716,7 @@ \section{\label{sec:Encoding-DER}Encoding DER} It just invokes the custom function (possible, multiple times) which would save the data into appropriate storage. The optional argument \emph{app\_key} is opaque for the DER encoder code and just -used by \emph{\_write\_stream()} as the pointer to the appropriate +used by \emph{write\_stream()} as the pointer to the appropriate output stream to be used. If the custom write function is not given (passed as 0), then the @@ -1413,39 +1811,32 @@ \section{\label{sec:Validating-the-target}Validating the target structure} or when the data has just been decoded to ensure its validity according to some stricter rules. -The asn\_check\_constraints() function checks the type for various -implicit and explicit constraints. It is recommended to use asn\_check\_constraints() +The \api{sec:asn_check_constraints}{asn_check_constraints()} +function checks the type for various +implicit and explicit constraints. It is recommended to use the +\code{asn_check_constraints()} function after each decoding and before each encoding. -Look into constraints.h for the precise definition of asn\_check\_constraints() -and related types. - - \section{\label{sec:Printing-the-target}Printing the target structure} -There are two ways to print the target structure: either invoke the -print\_struct member of the ASN.1 type descriptor, or using the asn\_fprint() -function, which is a simpler wrapper of the former: +To print out the structure for debugging purposes, use the +\api{sec:asn_fprint}{asn_fprint()} function: \begin{codesample} asn_fprint(stdout, &asn_DEF_Rectangle, rect); \end{codesample} -Look into constr\_TYPE.h for the precise definition of asn\_fprint() -and related types. -Another practical alternative to this custom format printing would -be to invoke XER encoder. The default BASIC-XER encoder performs reasonable -formatting for the output to be useful and human readable. To invoke -the XER decoder in a manner similar to asn\_fprint(), use the xer\_fprint() -call: +A practical alternative to this custom format printing is to serialize +the structure into XML. The default BASIC-XER encoder performs reasonable +formatting for the output to be both useful and human readable. +Use the \api{sec:xer_fprint}{xer_fprint()} function: \begin{codesample} xer_fprint(stdout, &asn_DEF_Rectangle, rect); \end{codesample} See \fref{sec:Encoding-XER} for XML-related details. - \section{\label{sec:Freeing-the-target}Freeing the target structure} -Freeing the structure is slightly more complex than it may seem to. +Freeing the structure is slightly more complex than it may seem. When the ASN.1 structure is freed, all the members of the structure and their submembers are recursively freed as well. The ASN\_STRUCT\_FREE() macro helps with that. diff --git a/doc/docsrc/asn_dec_rval.inc b/doc/docsrc/asn_dec_rval.inc index 06ece1957..c5749652a 100644 --- a/doc/docsrc/asn_dec_rval.inc +++ b/doc/docsrc/asn_dec_rval.inc @@ -5,7 +5,7 @@ may contain partially decoded data. This data may be useful for debugging Don't forget to discard the unused partially decoded data by calling \code{ASN_STRUCT_FREE()} or \code{ASN_STRUCT_RESET()}. -The return value is returned in a compound structure: +The function returns a compound structure: \begin{codesample} typedef struct { enum { @@ -17,7 +17,7 @@ typedef struct { } asn_dec_rval_t; \end{codesample} -The \code{.code} member specifies the decoding outcome. +\noindent{}The \code{.code} member specifies the decoding outcome. \begin{tabular}[h!]{ll} \texttt{RC\_OK} & Decoded successfully and completely \\ @@ -25,6 +25,6 @@ The \code{.code} member specifies the decoding outcome. \texttt{RC\_FAIL} & Failed for good \end{tabular} -The \code{.consumed} member specifies the amount of \code{buffer} data +\noindent{}The \code{.consumed} member specifies the amount of \code{buffer} data that was used during parsing, irrespectively of the \code{.code}. diff --git a/doc/docsrc/asn_enc_rval.inc b/doc/docsrc/asn_enc_rval.inc new file mode 100644 index 000000000..654e45af8 --- /dev/null +++ b/doc/docsrc/asn_enc_rval.inc @@ -0,0 +1,17 @@ + +The function returns a compound structure: + +\begin{codesample} +typedef struct { + ssize_t encoded; + const asn_TYPE_descriptor_t *failed_type; + const void *structure_ptr; +} asn_enc_rval_t; +\end{codesample} + +\noindent{}In case of unsuccessful encoding, the \code{.encoded} member is set to -1 and +the other members of the compound structure point to where the encoding has +failed to proceed further. + +In case encoding is successful, the \code{.encoded} member specifies the +size of the serialized output.