From af7104877b9819f9e11f3ca6109eda961e971478 Mon Sep 17 00:00:00 2001 From: erititan Date: Mon, 16 Mar 2015 10:45:12 +0100 Subject: [PATCH] Sync with 5.2.0 --- Install/.gitignore | 2 +- README.cygwin | 8 + README.linux | 231 +-- README.md | 40 +- README.md~ | 79 + README.mingw | 48 + common/config_preproc_la.l | 1 + common/version.h | 4 +- compiler2/AST.cc | 23 +- compiler2/AST.hh | 35 +- compiler2/CompilerError.cc | 2 +- compiler2/Makefile | 2 +- compiler2/ProjectGenHelper.cc | 744 +++++++ compiler2/ProjectGenHelper.hh | 157 ++ compiler2/Setting.cc | 14 +- compiler2/Setting.hh | 7 +- compiler2/Type.cc | 16 +- compiler2/Type.hh | 13 + compiler2/Type_chk.cc | 41 +- compiler2/Type_codegen.cc | 119 +- compiler2/Value.cc | 29 +- compiler2/Value.hh | 5 - compiler2/asn1/AST_asn1.cc | 33 +- compiler2/asn1/AST_asn1.hh | 16 +- compiler2/asn1/Ref.cc | 6 +- compiler2/compiler.1 | 37 +- compiler2/encdec.c | 10 +- compiler2/enum.c | 4 +- compiler2/main.cc | 47 +- compiler2/main.hh | 3 +- compiler2/makefile.c | 1753 ++++++++++++----- compiler2/record.c | 310 +-- compiler2/record_of.c | 458 ++--- compiler2/subtype.cc | 24 + compiler2/subtype.hh | 2 + compiler2/subtypestuff.cc | 10 + compiler2/subtypestuff.hh | 19 + compiler2/ttcn3/AST_ttcn3.cc | 57 +- compiler2/ttcn3/AST_ttcn3.hh | 21 +- compiler2/ttcn3/Statement.cc | 13 +- compiler2/ttcn3/Statement.hh | 7 +- compiler2/ttcn3/Ttcn2Json.cc | 43 +- compiler2/ttcn3/TtcnTemplate.cc | 9 +- compiler2/ttcn3/compiler.c | 4 + compiler2/union.c | 24 +- compiler2/xpather.cc | 643 +++++- compiler2/xpather.h | 117 +- core/ASN_Any.cc | 22 + core/ASN_CharacterString.cc | 71 +- core/ASN_CharacterString.hh | 16 +- core/ASN_EmbeddedPDV.cc | 72 +- core/ASN_EmbeddedPDV.hh | 16 +- core/ASN_External.cc | 57 +- core/ASN_External.hh | 4 +- core/ASN_Null.cc | 58 +- core/ASN_Null.hh | 12 +- core/Array.hh | 18 +- core/Basetype.cc | 18 +- core/Basetype.hh | 51 +- core/Bitstring.cc | 12 +- core/Bitstring.hh | 4 +- core/Boolean.cc | 10 +- core/Boolean.hh | 4 +- core/Charstring.cc | 10 +- core/Charstring.hh | 4 +- core/Float.cc | 10 +- core/Float.hh | 4 +- core/Hexstring.cc | 12 +- core/Hexstring.hh | 4 +- core/Integer.cc | 8 +- core/Integer.hh | 4 +- core/JSON.cc | 10 + core/JSON.hh | 5 + core/Makefile | 5 +- core/Objid.cc | 143 +- core/Objid.hh | 16 +- core/Octetstring.cc | 10 +- core/Octetstring.hh | 4 +- core/Optional.hh | 317 ++- core/Profiler.cc | 839 ++++++++ core/Profiler.hh | 193 ++ core/Template.hh | 4 +- core/Universal_charstring.cc | 8 +- core/Universal_charstring.hh | 4 +- core/Verdicttype.cc | 8 +- core/Verdicttype.hh | 4 +- core/XER.hh | 53 +- core/config_process.l | 21 +- core/config_process.y | 68 + core2/Basetype2.cc | 568 +++--- doc/License_handling_in_TITAN.doc | Bin 147968 -> 120832 bytes etc/Makefile | 1 + etc/scripts/ttcn3_archive.pl | 159 ++ etc/xsd/TPD.xsd | 25 +- .../Semantic_Analyser/TTCN3_SA_13_TD.script | 43 - .../TTCN3_SA_ttcn3adhoc_TD.script | 31 + .../doc/TTCN3_Executor_TestReport.doc | Bin 1476608 -> 1091072 bytes mctr2/cli/config_read.l | 21 +- mctr2/cli/config_read.y | 54 + .../XML/EXER-whitepaper/EmbedValues.ttcnpp | 67 + regression_test/XML/Makefile | 2 +- regression_test/XML/tpdValidTest/Makefile | 12 + .../XML/tpdValidTest/tpdValidTest.sh | 22 + regression_test/compileonly/HT48786/Makefile | 45 + .../compileonly/HT48786/Test1.ttcn | 36 + .../compileonly/HT48786/Test2.ttcn | 21 + regression_test/compileonly/Makefile | 2 +- .../invalid_buildconfig_param/Makefile | 3 +- .../compileonly/mfgen-tpd/library/Makefile | 34 +- regression_test/json/Functions.ttcn | 18 + regression_test/json/JsonData.asn | 98 + regression_test/json/Testcases.ttcn | 36 + regression_test/json/Types.ttcn | 7 + regression_test/recofOper/Makefile | 11 +- regression_test/recofOper/config.cfg | 1 - regression_test/recofOper/config_rt2.cfg | 15 + regression_test/ttcn2json/CompareSchemas.ttcn | 117 ++ .../ttcn2json/General_Types_e.json | 722 +++++++ regression_test/ttcn2json/Main.ttcn | 37 + regression_test/ttcn2json/Main_e.json | 279 +++ regression_test/ttcn2json/Makefile | 6 +- regression_test/ttcn2json/MiniRanap.asn | 80 + regression_test/ttcn2json/MiniRanap_e.json | 94 + regression_test/ttcn2json/PDU_Definitions.asn | 93 + regression_test/ttcn2json/Testcases.ttcn | 31 +- .../ttcn2json/f_ext_import_schema.cc | 456 +++++ .../ttcn2json/f_ext_import_schema.hh | 27 + regression_test/ttcn2json/one_e.json | 287 +-- regression_test/ttcn2json/three_e.json | 866 ++++++++ regression_test/ttcn2json/two.ttcn | 4 +- regression_test/ttcn2json/two_e.json | 794 ++++++++ regression_test/ttcn2json/zero.asn | 7 +- .../doc/Titan_Executor_API_User_Guide.doc | Bin 64512 -> 64512 bytes usrguide/Makefile | 40 +- usrguide/PRI.doc | Bin 0 -> 83456 bytes usrguide/apiguide.doc | Bin 566784 -> 564224 bytes usrguide/installationguide.doc | Bin 117760 -> 118272 bytes usrguide/referenceguide.doc | Bin 1490944 -> 1541120 bytes usrguide/releasenotes.doc | Bin 577536 -> 572416 bytes usrguide/userguide.doc | Bin 850432 -> 849408 bytes 140 files changed, 10583 insertions(+), 2192 deletions(-) create mode 100644 README.md~ create mode 100644 README.mingw create mode 100644 compiler2/ProjectGenHelper.cc create mode 100644 compiler2/ProjectGenHelper.hh create mode 100644 core/Profiler.cc create mode 100644 core/Profiler.hh create mode 100644 etc/scripts/ttcn3_archive.pl create mode 100644 regression_test/XML/tpdValidTest/Makefile create mode 100755 regression_test/XML/tpdValidTest/tpdValidTest.sh create mode 100644 regression_test/compileonly/HT48786/Makefile create mode 100644 regression_test/compileonly/HT48786/Test1.ttcn create mode 100644 regression_test/compileonly/HT48786/Test2.ttcn create mode 100644 regression_test/recofOper/config_rt2.cfg create mode 100644 regression_test/ttcn2json/CompareSchemas.ttcn create mode 100644 regression_test/ttcn2json/Main.ttcn create mode 100644 regression_test/ttcn2json/Main_e.json create mode 100644 regression_test/ttcn2json/MiniRanap.asn create mode 100644 regression_test/ttcn2json/MiniRanap_e.json create mode 100644 regression_test/ttcn2json/PDU_Definitions.asn create mode 100644 regression_test/ttcn2json/f_ext_import_schema.cc create mode 100644 regression_test/ttcn2json/f_ext_import_schema.hh create mode 100644 regression_test/ttcn2json/three_e.json create mode 100644 regression_test/ttcn2json/two_e.json create mode 100644 usrguide/PRI.doc diff --git a/Install/.gitignore b/Install/.gitignore index 2460008..3d75889 100644 --- a/Install/.gitignore +++ b/Install/.gitignore @@ -1 +1 @@ -!Makefile +!Makefile \ No newline at end of file diff --git a/README.cygwin b/README.cygwin index 43be04a..4b683ee 100644 --- a/README.cygwin +++ b/README.cygwin @@ -1,3 +1,11 @@ +****************************************************************************** +* Copyright (c) 2000-2015 Ericsson Telecom AB +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +****************************************************************************** + Cygwin setup - If Cygwin is installed already, refresh your Cygwin installation Titan is always build for the newest Cygwin version available. diff --git a/README.linux b/README.linux index 0666677..9becb31 100644 --- a/README.linux +++ b/README.linux @@ -1,113 +1,118 @@ -Build and install Titan on Linux - -1.Install required libraries: -(examples are given for Ubuntu 12.04/14.04; for other Linuxes, pls. use the relevant library installation method) - -sudo apt-get install g++ expect libssl-dev libxml2-dev libncurses5-dev flex bison -xutils-dev is needed by makedepend: -sudo apt-get install xutils-dev -The following packages may be needed for titan_eclipse/automatic_build: -sudo apt-get install ant xsltproc - -2.Clone the titan directory from git into /home//titan - -git clone https://github.com/eclipse/titan.core titan - -3. Configure the build - -cd titan -check that MakefileFOSS.cfg is present and has the following content: -cat MakefileFOSS.cfg - -# Configurations for the Free Open Source Software version -LICENSING := no -USAGE_STATS := no - - -Several build options are possible; for details on options , please read through the Makefile.cfg. -Options can be overridden by the content of a file named Makefile.personal which can be used to -adapt to local installation directories, change config options etc. -Below, a small number of typical scenarios are presented. - -1) JNI disabled - -The JNI interface is used by the Eclipse Titan Executor or by the Java Executor API. -If you don't need them , Titan can be compiled without JNI. - -Create ~/titan/Makefile.personal to override settings in Makefile.cfg with the following content: -(replace paths with values relevant to your installation) - -TTCN3_DIR := /home//titan/Install -OPENSSL_DIR := /usr -#JDKDIR := /usr/lib/jvm/java-7-openjdk-amd64 -XMLDIR := /usr -JNI := no -GEN_PDF := no - - - - -2) JNI enabled - -install JDK into /home//jdk - -Create ~/titan/Makefile.personal to override settings in Makefile.cfg with the following content: -(replace paths with values relevant to your installation) - -TTCN3_DIR := /home//titan/Install -OPENSSL_DIR := /usr -JDKDIR := /usr/lib/jvm/java-7-openjdk-amd64 -XMLDIR := /usr -JNI := yes -GEN_PDF := no - - - -3. Run make - -make - -4. Run make install - -make install - -This will install Titan into /home//titan/Install - -5. Optionally , run function/regression tests - -set environment variable TTCN3_DIR to /home//titan/Install - -(setenv TTCN3_DIR /home//titan/Install for csh, -export TTCN3_DIR=/home//titan/Install for bash ) - - - -cd /home//titan/function_test - -in the following Makefiles - -XER_EncDec/Makefile -Text_EncDec/Makefile -RAW_EncDec/Makefile - -edit the value of XMLDIR to match your installation values - -run the tests - -make - -( or make |& tee outputfile if you want to save the output for verification) - -cd /home//titan/regression_test -make run - -( or make run |& tee outputfile if you want to save the output for verification) - -These tests might run for half an hour (regr.tests) to two hours (func.tests) - -6. Optionally , copy Titan into its' final directory. -From here on, you can continue with the Titan installation guide, see /Install/docs, to set environment variables etc. - - - - +****************************************************************************** +* Copyright (c) 2000-2015 Ericsson Telecom AB +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +****************************************************************************** + +Build and install Titan on Linux + +1.Install required libraries: +(examples are given for Ubuntu 12.04/14.04; for other Linuxes, pls. use the relevant library installation method) + +sudo apt-get install g++ expect libssl-dev libxml2-dev libncurses5-dev flex bison +xutils-dev is needed by makedepend: +sudo apt-get install xutils-dev +The following packages may be needed for titan_eclipse/automatic_build: +sudo apt-get install ant xsltproc + +2.Clone the titan directory from git into /home//titan + +git clone https://github.com/eclipse/titan.core titan + +3. Configure the build + +cd titan +check that MakefileFOSS.cfg is present and has the following content: +cat MakefileFOSS.cfg + +# Configurations for the Free Open Source Software version +LICENSING := no +USAGE_STATS := no + + +Several build options are possible; for details on options , please read through the Makefile.cfg. +Options can be overridden by the content of a file named Makefile.personal which can be used to +adapt to local installation directories, change config options etc. +Below, a small number of typical scenarios are presented. + +1) JNI disabled + +The JNI interface is used by the Eclipse Titan Executor or by the Java Executor API. +If you don't need them , Titan can be compiled without JNI. + +Create ~/titan/Makefile.personal to override settings in Makefile.cfg with the following content: +(replace paths with values relevant to your installation) + +TTCN3_DIR := /home//titan/Install +OPENSSL_DIR := /usr +#JDKDIR := /usr/lib/jvm/java-7-openjdk-amd64 +XMLDIR := /usr +JNI := no +GEN_PDF := no + + + + +2) JNI enabled + +install JDK into /home//jdk + +Create ~/titan/Makefile.personal to override settings in Makefile.cfg with the following content: +(replace paths with values relevant to your installation) + +TTCN3_DIR := /home//titan/Install +OPENSSL_DIR := /usr +JDKDIR := /usr/lib/jvm/java-7-openjdk-amd64 +XMLDIR := /usr +JNI := yes +GEN_PDF := no + + + +3. Run make + +make + +4. Run make install + +make install + +This will install Titan into /home//titan/Install + +5. Optionally , run function/regression tests + +set environment variable TTCN3_DIR to /home//titan/Install + +(setenv TTCN3_DIR /home//titan/Install for csh, +export TTCN3_DIR=/home//titan/Install for bash ) + + + +cd /home//titan/function_test + +in the following Makefiles + +XER_EncDec/Makefile +Text_EncDec/Makefile +RAW_EncDec/Makefile + +edit the value of XMLDIR to match your installation values + +run the tests + +make + +( or make |& tee outputfile if you want to save the output for verification) + +cd /home//titan/regression_test +make run + +( or make run |& tee outputfile if you want to save the output for verification) + +These tests might run for half an hour (regr.tests) to two hours (func.tests) + +6. Optionally , copy Titan into its' final directory. +From here on, you can continue with the Titan installation guide, see /Install/docs, to set environment variables etc. + diff --git a/README.md b/README.md index b920dec..8dfedb8 100644 --- a/README.md +++ b/README.md @@ -20,26 +20,26 @@ http://polarsys.org/sites/default/files/custom_uploads/TITAN%20Datasheet%20A4%20 ##Binaries and SHA512 checksums for a number of Linux platforms can be downloaded from: -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux32-gcc4.1.0-sles10.tgz -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux32-gcc4.1.0-sles10.tgz.sha512 -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux32-gcc4.1.2-sled10.2.tgz -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux32-gcc4.1.2-sled10.2.tgz.sha512 -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux32-gcc4.3-SLED11.1.tgz -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux32-gcc4.3-SLED11.1.tgz.sha512 -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.1.2-rhel5.tgz -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.1.2-rhel5.tgz.sha512 -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.3-SLED11.1.tgz -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.3-SLED11.1.tgz.sha512 -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.3-sled11.0.tgz -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.3-sled11.0.tgz.sha512 -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.3-sles11.1.tgz -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.3-sles11.1.tgz.sha512 -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.4.5-rhel6.tgz -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.4.5-rhel6.tgz.sha512 -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.6-ubuntu12.04.tgz -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.6-ubuntu12.04.tgz.sha512 -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.8-ubuntu14.04.tgz -* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.8-ubuntu14.04.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux32-gcc4.1.0-sles10.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux32-gcc4.1.0-sles10.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux32-gcc4.1.2-sled10.2.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux32-gcc4.1.2-sled10.2.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux32-gcc4.3-SLED11.1.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux32-gcc4.3-SLED11.1.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.1.2-rhel5.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.1.2-rhel5.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.3-SLED11.1.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.3-SLED11.1.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.3-sled11.0.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.3-sled11.0.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.3-sles11.1.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.3-sles11.1.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.4.5-rhel6.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.4.5-rhel6.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.6-ubuntu12.04.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.6-ubuntu12.04.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.8-ubuntu14.04.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.2.pl0-linux64-gcc4.8-ubuntu14.04.tgz.sha512 # Related products: diff --git a/README.md~ b/README.md~ new file mode 100644 index 0000000..b920dec --- /dev/null +++ b/README.md~ @@ -0,0 +1,79 @@ +# titan.core + +TTCN-3 is a standardized, modular language specifically designed for testing. +Eclipse Titan offers a free and open source (FOSS) compiler both for TTCN-3 and for +ASN.1 (Abstract Syntax Notation One). + +# Standards page (also including downloadable code): + +* http://www.ttcn-3.org/ + +# Main project page: + +* https://projects.eclipse.org/projects/tools.titan + +##Introductory video of a presentation about Titan held at EclipseCon 2014: +* https://www.youtube.com/watch?v=2knzZuwzn-Y. + +##Titan Datasheet on polarsys.org: +http://polarsys.org/sites/default/files/custom_uploads/TITAN%20Datasheet%20A4%202.1.pdf + +##Binaries and SHA512 checksums for a number of Linux platforms can be downloaded from: + +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux32-gcc4.1.0-sles10.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux32-gcc4.1.0-sles10.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux32-gcc4.1.2-sled10.2.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux32-gcc4.1.2-sled10.2.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux32-gcc4.3-SLED11.1.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux32-gcc4.3-SLED11.1.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.1.2-rhel5.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.1.2-rhel5.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.3-SLED11.1.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.3-SLED11.1.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.3-sled11.0.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.3-sled11.0.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.3-sles11.1.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.3-sles11.1.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.4.5-rhel6.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.4.5-rhel6.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.6-ubuntu12.04.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.6-ubuntu12.04.tgz.sha512 +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.8-ubuntu14.04.tgz +* https://www.eclipse.org/downloads/download.php?file=/titan/ttcn3-5.1.pl0-linux64-gcc4.8-ubuntu14.04.tgz.sha512 + + +# Related products: + +## Test Ports: + +* https://github.com/eclipse/titan.TestPorts.Common_Components.Abstract_Socket +* https://github.com/eclipse/titan.TestPorts.HTTPmsg +* https://github.com/eclipse/titan.TestPorts.LANL2asp +* https://github.com/eclipse/titan.TestPorts.PCAPasp +* https://github.com/eclipse/titan.TestPorts.PIPEasp +* https://github.com/eclipse/titan.TestPorts.SCTPasp +* https://github.com/eclipse/titan.TestPorts.SIPmsg +* https://github.com/eclipse/titan.TestPorts.SQLasp +* https://github.com/eclipse/titan.TestPorts.TCPasp +* https://github.com/eclipse/titan.TestPorts.TELNETasp +* https://github.com/eclipse/titan.TestPorts.UDPasp + + +## Protocol Modules: + +* https://github.com/eclipse/titan.ProtocolModules.COMMON +* https://github.com/eclipse/titan.ProtocolModules.DHCP +* https://github.com/eclipse/titan.ProtocolModules.DHCPv6 +* https://github.com/eclipse/titan.ProtocolModules.DIAMETER_ProtocolModule_Generator +* https://github.com/eclipse/titan.ProtocolModules.DNS +* https://github.com/eclipse/titan.ProtocolModules.ICMP +* https://github.com/eclipse/titan.ProtocolModules.ICMPv6 +* https://github.com/eclipse/titan.ProtocolModules.IP +* https://github.com/eclipse/titan.ProtocolModules.RTP +* https://github.com/eclipse/titan.ProtocolModules.RTSP +* https://github.com/eclipse/titan.ProtocolModules.SMPP +* https://github.com/eclipse/titan.ProtocolModules.SMTP +* https://github.com/eclipse/titan.ProtocolModules.SNMP +* https://github.com/eclipse/titan.ProtocolModules.TCP +* https://github.com/eclipse/titan.ProtocolModules.UDP +* https://github.com/eclipse/titan.ProtocolModules.XMPP diff --git a/README.mingw b/README.mingw new file mode 100644 index 0000000..6169d87 --- /dev/null +++ b/README.mingw @@ -0,0 +1,48 @@ +****************************************************************************** +* Copyright (c) 2000-2015 Ericsson Telecom AB +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +****************************************************************************** + +MinGW setup + + (A) Download the MinGW installer from the MinGW site: + http://www.mingw.org/ + + (B) Follow the install steps found on the MinGW getting started page: + http://www.mingw.org/wiki/getting_started + Select the mingw-gcc-v3 packages because Titan only compiles + with older gcc. If you select the gcc4 packages, then the make process + stops immediately with some error messages. Select the msys packages too. + + (C) Check the PATH system variable: + System -> Advanced system settings -> Environment Variables -> Path + The MinGW installation path must be present to use the installed + executables and files. For example: + echo %PATH% + C:\MinGW\bin;C:\MinGW\usr\bin... + + (D) Working environment: + Use the \msys\\msys.bat file to start a shell. + Download and extract the Titan source files and folders to a directory, + and create a Makefile.personal in the top directory. Please check the + installation guide and set all the needed variables like TTCN3_DIR. The + MinGW compilation needs a few extra changes in the Makefile.cfg also. Set + the PLATFORM and MINGW values: + PLATFORM := WIN32 + MINGW := -DMINGW -mno-cygwin + + (E) Compile Titan: + cd titan + make -j + make install + The compiled files will be placed into the ./Install directory. + + (F) If the build process stops with a Windows error message saying that some files + are missing, search for the indicated Cygwin package and download it from the Cygwin page. + You can search fast and easily with the Cygwin Package Search tool: + https://cygwin.com/cgi-bin2/package-grep.cgi + Extract the downloaded package into the MinGW installation directory, and + restart the build process. diff --git a/common/config_preproc_la.l b/common/config_preproc_la.l index 316b634..1699f33 100644 --- a/common/config_preproc_la.l +++ b/common/config_preproc_la.l @@ -142,6 +142,7 @@ MACRO_REFERENCE_INT \$"{"{WS}{TTCN3IDENTIFIER}{WS}(","{WS}integer{WS})?"}" } "["{WS}LOGGING{WS}"]" BEGIN(INITIAL); +"["{WS}PROFILER{WS}"]" BEGIN(INITIAL); "["{WS}EXECUTE{WS}"]" BEGIN(INITIAL); "["{WS}EXTERNAL_COMMANDS{WS}"]" BEGIN(INITIAL); "["{WS}GROUPS{WS}"]" BEGIN(INITIAL); diff --git a/common/version.h b/common/version.h index b6472c0..a72a783 100644 --- a/common/version.h +++ b/common/version.h @@ -10,7 +10,7 @@ /* Version numbers */ #define TTCN3_MAJOR 5 -#define TTCN3_MINOR 1 +#define TTCN3_MINOR 2 #define TTCN3_PATCHLEVEL 0 //#define TTCN3_BUILDNUMBER 0 @@ -22,7 +22,7 @@ * TTCN3_VERSION = TTCN3_MAJOR * 1000000 + TTCN3_MINOR * 10000 + * TTCN3_PATCHLEVEL * 100 + TTCN3_BUILDNUMBER */ -#define TTCN3_VERSION 50100 +#define TTCN3_VERSION 50200 /* A monotonically increasing version number. * An official release is deemed to have the highest possible build number (99) diff --git a/compiler2/AST.cc b/compiler2/AST.cc index 3f45141..4cfcad2 100644 --- a/compiler2/AST.cc +++ b/compiler2/AST.cc @@ -263,17 +263,10 @@ namespace Common { return versions; } - void Modules::add_types_to_json_schema(JSON_Tokenizer& json) + void Modules::generate_json_schema(JSON_Tokenizer& json, map& json_refs) { for(size_t i = 0; i < mods_v.size(); ++i) { - mods_v[i]->add_types_to_json_schema(json); - } - } - - void Modules::add_func_to_json_schema(map& json_refs) - { - for(size_t i = 0; i < mods_v.size(); ++i) { - mods_v[i]->add_func_to_json_schema(json_refs); + mods_v[i]->generate_json_schema(json, json_refs); } } @@ -807,6 +800,12 @@ namespace Common { mputprintf(effective_module_functions, "%s\"%s\"", (effective_module_functions ? ", " : ""), get_modid().get_dispname().c_str()); } + if (profiler_enabled && MOD_TTCN == get_moduletype()) { + output->source.static_function_bodies = mputprintf(output->source.static_function_bodies, + "TTCN3_Stack_Depth stack_depth;\n" + "ttcn3_prof.enter_function(\"%s\", 0, \"%s\");\n", + get_filename(), get_modid().get_dispname().c_str()); + } } output->source.static_function_bodies = mputstr(output->source.static_function_bodies, output->functions.pre_init); @@ -844,6 +843,12 @@ namespace Common { mputprintf(effective_module_functions, "%s\"%s\"", (effective_module_functions ? ", " : ""), get_modid().get_dispname().c_str()); } + if (profiler_enabled && MOD_TTCN == get_moduletype()) { + output->source.static_function_bodies = mputprintf(output->source.static_function_bodies, + "TTCN3_Stack_Depth stack_depth;\n" + "ttcn3_prof.enter_function(\"%s\", 0, \"%s\");\n", + get_filename(), get_modid().get_dispname().c_str()); + } } output->source.static_function_bodies = mputstr(output->source.static_function_bodies, output->functions.post_init); diff --git a/compiler2/AST.hh b/compiler2/AST.hh index 693559c..ddb99c2 100644 --- a/compiler2/AST.hh +++ b/compiler2/AST.hh @@ -116,14 +116,15 @@ namespace Common { void generate_code(CodeGenHelper& cgh); void dump(unsigned level=1) const; - /** Generates JSON schema segments for the types defined in the modules - * and adds them to the JSON schema parameter. */ - void add_types_to_json_schema(JSON_Tokenizer& json); - - /** Generates JSON schemas containing references to the types defined in the - * modules. Information related to the types' JSON encoding and decoding - * functions is also inserted after the references. */ - void add_func_to_json_schema(map& json_refs); + /** Generates JSON schema segments for the types defined in the modules, + * and references to these types. Information related to the types' + * JSON encoding and decoding functions is also inserted after the references. + * + * @param json JSON document containing the main schema, schema segments for + * the types will be inserted here + * @param json_refs map of JSON documents containing the references and function + * info related to each type */ + void generate_json_schema(JSON_Tokenizer& json, map& json_refs); }; /** @@ -391,15 +392,15 @@ namespace Common { void generate_code(CodeGenHelper& cgh); virtual void dump(unsigned level) const; - /** Generates JSON schema segments for the types defined in the module - * and adds them to the JSON schema parameter. */ - virtual void add_types_to_json_schema(JSON_Tokenizer&) = 0; - - /** Generates JSON schemas containing references to the types that have JSON - * encoding and/or decoding functions declared in the module. Information - * related to these functions is also inserted after the references - * (only for TTCN-3 modules). */ - virtual void add_func_to_json_schema(map&) = 0; + /** Generates JSON schema segments for the types defined in the modules, + * and references to these types. Information related to the types' + * JSON encoding and decoding functions is also inserted after the references. + * + * @param json JSON document containing the main schema, schema segments for + * the types will be inserted here + * @param json_refs map of JSON documents containing the references and function + * info related to each type */ + virtual void generate_json_schema(JSON_Tokenizer& json, map& json_refs) = 0; }; /** diff --git a/compiler2/CompilerError.cc b/compiler2/CompilerError.cc index 88b5acc..2b438fa 100644 --- a/compiler2/CompilerError.cc +++ b/compiler2/CompilerError.cc @@ -298,7 +298,7 @@ namespace Common { if (++error_count >= max_errors) { fputs("Maximum number of errors reached, aborting.\n", stderr); fflush(stderr); - abort(); + exit(EXIT_FAILURE); } } diff --git a/compiler2/Makefile b/compiler2/Makefile index e5a1833..61ef64f 100644 --- a/compiler2/Makefile +++ b/compiler2/Makefile @@ -68,7 +68,7 @@ main.cc Real.cc Setting.cc SigParam.cc string.cc subtype.cc Stopwatch.cc \ Type.cc Type_chk.cc Type_codegen.cc TypeCompat.cc \ Typestuff.cc ustring.cc Value.cc Valuestuff.cc XerAttributes.cc subtypestuff.cc CodeGenHelper.cc -MFGEN_SOURCES := makefile.c xpather.cc +MFGEN_SOURCES := makefile.c xpather.cc ProjectGenHelper.cc TCOV2LCOV_SOURCES := tcov2lcov.cc diff --git a/compiler2/ProjectGenHelper.cc b/compiler2/ProjectGenHelper.cc new file mode 100644 index 0000000..991449e --- /dev/null +++ b/compiler2/ProjectGenHelper.cc @@ -0,0 +1,744 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "ProjectGenHelper.hh" +#include "../common/memory.h" + +#include "error.h" +#include +#include +#include +#include + +const std::string ProjectDescriptor::emptyString = std::string(); + +ProjectDescriptor::ProjectDescriptor(const char * name) : + projectName(std::string(name)), + tpdFileName(), + targetExecutableName(), + projectAbsTpdDir(), + projectAbsWorkingDir(), + projectWorkingDir(), + library(false), + dynamicLinked(false), + referencedProjects(), + refProjWorkingDirs(), + libSearchPaths(), + linkerLibraries(), + ttcn3ModuleNames(), + asn1ModuleNames(), + userSources(), + userHeaders(), + ttcnPP(), + initialized(false) +{} + +void ProjectDescriptor::cleanUp() +{ + referencedProjects.clear(); + refProjWorkingDirs.clear(), + libSearchPaths.clear(); + linkerLibraries.clear(); + ttcn3ModuleNames.clear(); + asn1ModuleNames.clear(); + userSources.clear(); + userHeaders.clear(); + ttcnPP.clear(); +} + +bool ProjectDescriptor::isInitialized() +{ + if (!projectName.empty() && + !targetExecutableName.empty() && + !projectAbsTpdDir.empty() && + !projectAbsWorkingDir.empty() && + !projectWorkingDir.empty()) + initialized = true; + return initialized; +} + +void ProjectDescriptor::setTPDFileName(const char* name) +{ + const char SEPARATOR = '/'; + std::string fileName(name); + size_t refProjPos = fileName.find_last_of(SEPARATOR); + if (std::string::npos == refProjPos) { + tpdFileName = fileName; + } + else { + tpdFileName = fileName.substr(refProjPos + 1); + } +} + +void ProjectDescriptor::setProjectAbsWorkingDir(const char* name) +{ + if (!name) { + ERROR("No path was given to the working directory. Check if 'r' flag is set "); + return; + } + projectAbsWorkingDir = std::string(name); + ProjectGenHelper::Instance().setRootDirOS(name); +} + +void ProjectDescriptor::addToReferencedProjects(const char* refProjName) +{ + std::vector::iterator it; + for (it = referencedProjects.begin(); it != referencedProjects.end(); ++it) { + if (*it == std::string(refProjName)) return; + } + referencedProjects.push_back(std::string(refProjName)); +} + +void ProjectDescriptor::addToRefProjWorkingDirs(const std::string& subProjDir) +{ + std::vector::iterator it; + for (it = refProjWorkingDirs.begin(); it != refProjWorkingDirs.end(); ++it) { + if (*it == subProjDir) return; + } + refProjWorkingDirs.push_back(subProjDir); +} + +bool ProjectDescriptor::hasLinkerLibTo(const std::string& refProjName) const +{ + ProjectDescriptor* refProj = ProjectGenHelper::Instance().getTargetOfProject(refProjName.c_str()); + for (size_t i = 0; i < referencedProjects.size(); ++i){ + if (refProj && refProj->library) return true; + } + return false; +} + +bool ProjectDescriptor::hasLinkerLib(const char* libName) const +{ + std::string linkerLibName(libName); + std::vector::const_iterator it; + for (it = linkerLibraries.begin(); it != linkerLibraries.end(); ++it) { + if (*it == linkerLibName) return true; + } + return false; +} + +void ProjectDescriptor::addToLibSearchPaths(const char* libSearchPath) +{ + std::string searchPath(libSearchPath); + std::vector::iterator it; + for (it = libSearchPaths.begin(); it != libSearchPaths.end(); ++it) { + if (*it == searchPath) return; + } + libSearchPaths.push_back(libSearchPath); +} + +void ProjectDescriptor::addToLinkerLibs(const char* linkerLibs) +{ + std::string llibs(linkerLibs); + std::vector::iterator it; + for (it = linkerLibraries.begin(); it != linkerLibraries.end(); ++it) { + if (*it == llibs) return; + } + linkerLibraries.push_back(linkerLibs); +} + +size_t ProjectDescriptor::getLibSearchPathIndex(const std::string& subProjName) const +{ + + for (size_t i = 0; i < libSearchPaths.size(); ++i) { + if (std::string::npos != libSearchPaths[i].find(subProjName)) + return i; + } + return std::numeric_limits::max(); +} + +const char* ProjectDescriptor::getLibSearchPath(const std::string& subProjName) const +{ + for (size_t i = 0; i < libSearchPaths.size(); ++i) { + if (std::string::npos != libSearchPaths[i].find(subProjName)) + return libSearchPaths[i].c_str(); + } + return NULL; +} + +bool ProjectDescriptor::hasTtcn3ModuleName(const char* moduleName) const +{ + std::string modName(moduleName); + std::vector::const_iterator it; + for (it = ttcn3ModuleNames.begin(); it != ttcn3ModuleNames.end(); ++it) { + if (*it == modName) return true; + } + return false; +} + +bool ProjectDescriptor::hasAsn1ModuleName(const char* moduleName) const +{ + std::string modName(moduleName); + std::vector::const_iterator it; + for (it = asn1ModuleNames.begin(); it != asn1ModuleNames.end(); ++it) { + if (*it == modName) return true; + } + return false; +} + +bool ProjectDescriptor::hasUserSource(const char* userSourceName) const +{ + std::string sourceName(userSourceName); + std::vector::const_iterator it; + for (it = userSources.begin(); it != userSources.end(); ++it) { + if (*it == sourceName) return true; + } + return false; +} + +bool ProjectDescriptor::hasUserHeader(const char* userHeaderName) const +{ + std::string headerName(userHeaderName); + std::vector::const_iterator it; + for (it = userHeaders.begin(); it != userHeaders.end(); ++it) { + if (*it == headerName) return true; + } + return false; +} + +bool ProjectDescriptor::hasTtcn3PP(const char* ttcnPPName) const +{ + std::string ttcnPPFile(ttcnPPName); + std::vector::const_iterator it; + for (it = ttcnPP.begin(); it != ttcnPP.end(); ++it) { + if (*it == ttcnPPFile) return true; + } + return false; +} + +std::string ProjectDescriptor::setRelativePathTo(const std::string& absPathTo) +{ + if (projectAbsWorkingDir.empty()) return std::string(); + const char SEPARATOR = '/'; + if (projectAbsWorkingDir.at(0) != SEPARATOR || absPathTo.at(0) != SEPARATOR) + ERROR("Expecting absolute path to generate LinkerLibSearchPath "); + size_t length = projectAbsWorkingDir.size() > absPathTo.size() ? absPathTo.size() : projectAbsWorkingDir.size(); + size_t lastSlash = 0; + size_t i; + for(i = 0; i < length && projectAbsWorkingDir.at(i) == absPathTo.at(i); ++i) { + if (projectAbsWorkingDir.at(i) == SEPARATOR && absPathTo.at(i) == SEPARATOR) { + lastSlash = i; // the same path until now... + } + } + if (length == i) { // got subdirectory + if (projectAbsWorkingDir == absPathTo) { + return std::string("."); // the same pathes were given + } + else if ((projectAbsWorkingDir.size() > absPathTo.size() && projectAbsWorkingDir.at(length) == SEPARATOR) || + (projectAbsWorkingDir.size() < absPathTo.size() && absPathTo.at(length) == SEPARATOR)) + lastSlash = length; + } + + size_t slashCount = 0; + for (size_t i = lastSlash; i < projectAbsWorkingDir.size(); ++i) { + if (projectAbsWorkingDir.at(i) == SEPARATOR) + ++slashCount; + } + + std::string relPath; + const std::string upDir("../"); + for (size_t i = 0; i < slashCount; ++i) + relPath.append(upDir); + + std::string pathTo = absPathTo.substr(lastSlash+1); // we left the heading slash + relPath.append(pathTo); + return std::string(relPath); +} + +void ProjectDescriptor::print() +{ + fprintf( stderr, "project name %s and it is %s initialized\n", projectName.c_str(), isInitialized() ? "" : "not"); + fprintf( stderr, " target executable name %s\n",targetExecutableName.c_str()); + fprintf( stderr, " project abs TPD dir %s\n", projectAbsTpdDir.c_str()); + fprintf( stderr, " project abs working dir %s\n", projectAbsWorkingDir.c_str()); + fprintf( stderr, " project working dir %s\n", projectWorkingDir.c_str()); + fprintf( stderr, " project is %s\n", library ? "Library" : "Executable"); + fprintf( stderr, " project linking is %s\n", dynamicLinked ? "dynamic" : "static"); + std::vector::iterator it; + for (it = referencedProjects.begin(); it != referencedProjects.end(); ++it) { + fprintf( stderr, " Referenced project %s\n",(*it).c_str()); + } + for (it = refProjWorkingDirs.begin(); it != refProjWorkingDirs.end(); ++it) { + fprintf( stderr, " Working dir of referenced project %s\n",(*it).c_str()); + } + for (it = linkerLibraries.begin(); it != linkerLibraries.end(); ++it) { + fprintf( stderr, " Linker library %s\n", (*it).c_str()); + } + for (it = libSearchPaths.begin(); it != libSearchPaths.end(); ++it) { + fprintf( stderr, " Linker lib search path %s\n", (*it).c_str()); + } + for (it = ttcn3ModuleNames.begin(); it != ttcn3ModuleNames.end(); ++it) { + fprintf( stderr, " TTCN3 Module Name: %s\n", (*it).c_str()); + } + for (it = asn1ModuleNames.begin(); it != asn1ModuleNames.end(); ++it) { + fprintf( stderr, " ASN1 Module Name: %s\n", (*it).c_str()); + } + for (it = userSources.begin(); it != userSources.end(); ++it) { + fprintf( stderr, " Source Name: %s\n", (*it).c_str()); + } + for (it = userHeaders.begin(); it != userHeaders.end(); ++it) { + fprintf( stderr, " Header Name: %s\n", (*it).c_str()); + } + for (it = ttcnPP.begin(); it != ttcnPP.end(); ++it) { + fprintf( stderr, " TTCN PP Name: %s\n", (*it).c_str()); + } + fprintf( stderr, "\n"); +} + +ProjectGenHelper& ProjectGenHelper::Instance() +{ + static ProjectGenHelper singleton; + return singleton; +} + +const std::string ProjectGenHelper::emptyString = std::string(); + +ProjectGenHelper::ProjectGenHelper() : + nameOfTopLevelProject(), + rootDirOS(), + relPathToRootDirOS(), + Zflag(false), + Wflag(false), + Hflag(false), + projs(), + checkedProjs() +{} + +void ProjectGenHelper::addTarget(const char* projName) +{ + if (!Zflag) return; + if (projs.end() != projs.find(std::string(projName))) return; // we have it + ProjectDescriptor newLib(projName); + projs.insert(std::pair (std::string(projName), newLib)); +} + +void ProjectGenHelper::setToplevelProjectName(const char* name) +{ + if (!nameOfTopLevelProject.empty()) return; + nameOfTopLevelProject = std::string(name); +} + +void ProjectGenHelper::setRootDirOS( const char* name) +{ + if (rootDirOS.empty()) { + rootDirOS = std::string(name); + } + else { //compare the 2 string and get the common part + const char* root = rootDirOS.c_str(); + const char* head = root; + for (; *root++ == *name++; ) ; + size_t length = root - head - 1; //minus the non-matching + if (rootDirOS.size() > length) { + rootDirOS.resize(length); + } + } +} + +const std::string& ProjectGenHelper::getRootDirOS(const char* name) +{ + ProjectDescriptor* proj = getProject(name); + if (!proj) return emptyString; + relPathToRootDirOS = proj->setRelativePathTo(rootDirOS); + return relPathToRootDirOS; +} + +ProjectDescriptor* ProjectGenHelper::getTargetOfProject(const char* projName) +{ + if (!Zflag) return NULL; + if (projs.end() == projs.find(std::string(projName))) return NULL; + return getProject(projName); +} + +const ProjectDescriptor* ProjectGenHelper::getTargetOfProject(const char* projName) const +{ + if (!Zflag) return NULL; + if (projs.end() == projs.find(std::string(projName))) return NULL; + return getProject(projName); +} + +ProjectDescriptor* ProjectGenHelper::getProjectDescriptor(const char* targetName) +{ + if (!Zflag) return NULL; + for (std::map::iterator it = projs.begin(); it != projs.end(); ++it) { + if ((it->second).getTargetExecName() == std::string(targetName)) + return &(it->second); + } + return NULL; +} + +std::map::const_iterator ProjectGenHelper::getHead() const +{ + return projs.begin(); +} + +std::map::const_iterator ProjectGenHelper::getEnd() const +{ + return projs.end(); +} + +void ProjectGenHelper::addTtcn3ModuleToProject(const char* projName, const char* moduleName) +{ + if (!Zflag) return; + if (projs.end() == projs.find(std::string(projName))) return; + ProjectDescriptor* proj = getProject(projName); + if (proj && !proj->hasTtcn3ModuleName(moduleName)) { + proj->addTtcn3ModuleName(moduleName); + } +} + +void ProjectGenHelper::addAsn1ModuleToProject(const char* projName, const char* moduleName) +{ + if (!Zflag) return; + if (projs.end() == projs.find(std::string(projName))) return; + ProjectDescriptor* proj = getProject(projName); + if (proj &&!proj->hasAsn1ModuleName(moduleName)) { + proj->addAsn1ModuleName(moduleName); + } +} + +void ProjectGenHelper::addUserSourceToProject(const char* projName, const char* userSourceName) +{ + if (!Zflag) return; + if (projs.end() == projs.find(std::string(projName))) return; + ProjectDescriptor* proj = getProject(projName); + if (proj && !proj->hasUserSource(userSourceName)) { + proj->addUserSource(userSourceName); + } +} + +void ProjectGenHelper::addUserHeaderToProject(const char* projName, const char* userHeaderName) +{ + if (!Zflag) return; + if (projs.end() == projs.find(std::string(projName))) return; + ProjectDescriptor* proj = getProject(projName); + if (proj && !proj->hasUserHeader(userHeaderName)) { + proj->addUserHeader(userHeaderName); + } +} + +void ProjectGenHelper::addTtcnPPToProject(const char* projName, const char* ttcnPPName) +{ + if (!Zflag) return; + if (projs.end() == projs.find(std::string(projName))) return; + ProjectDescriptor* proj = getProject(projName); + if (proj && !proj->hasTtcn3PP(ttcnPPName)) { + proj->addTtcn3PP(ttcnPPName); + } +} + +void ProjectGenHelper::generateRefProjectWorkingDirsTo(const char* projName) +{ + if (!Zflag) return; + std::map::iterator iter = projs.find(projName); + if (projs.end() == iter) { + ERROR("Project \"%s\" is not found in the project hierarchy ", projName); + return; + } + if (nameOfTopLevelProject != (iter->second).getProjectName()) { + ERROR("Project \"%s\" is not the on the top-level ", projName); + return; + } + ProjectDescriptor* proj = &(iter->second); // the Top level project + + for (size_t i = 0; i < proj->numOfReferencedProjects(); ++i) { + const std::string& refProjName = proj->getReferencedProject(i); + ProjectDescriptor* refProj = getTargetOfProject(refProjName.c_str()); + if (!refProj) return; // for sure... + const std::string& absWorkingDir = refProj->getProjectAbsWorkingDir(); + if (!absWorkingDir.empty()) { + std::string relPath = proj->setRelativePathTo(absWorkingDir); + proj->addToRefProjWorkingDirs(relPath); + } + } +} + +size_t ProjectGenHelper::numOfLibs() const +{ + if (!Zflag) return 0; + size_t num = 0; + for (std::map::const_iterator it = projs.begin(); it != projs.end(); ++it) { + if ((it->second).isLibrary()) { + ++num; + } + } + return num; +} + +struct CompareStr +{ + bool operator () (const char* lhs, const char* rhs) { + int ret = strcmp(lhs, rhs); + return (0 > ret); + } +}; + +void ProjectGenHelper::getExternalLibs(std::vector& extLibs) +{ + if (!Zflag) return; + std::map libs; + for (std::map::iterator it = projs.begin(); it != projs.end(); ++it) { + if ((it->second).numOfLinkerLibs() > 0) { + for (size_t i = 0; i < (it->second).numOfLinkerLibs(); ++i) { + const char* key = (it->second).getLinkerLib(i); + const char* value = (it->second).getProjectName().c_str(); + libs.insert(std::pair(key,value)); // filter duplicates + } + } + } + std::map::iterator it; + for (it = libs.begin(); it != libs.end(); ++it) { + extLibs.push_back(it->first); + } +} + +void ProjectGenHelper::getExternalLibSearchPathes(std::vector& extLibPathes) +{ + if (!Zflag) return; + std::map libPathes; + for (std::map::iterator it = projs.begin(); it != projs.end(); ++it) { + if ((it->second).numOfLibSearchPaths() > 0) { + for (size_t i = 0; i < (it->second).numOfLibSearchPaths(); ++i) { + const char* key = (it->second).getLibSearchPath(i); + const char* value = (it->second).getProjectName().c_str(); + libPathes.insert(std::pair(key,value)); // filter duplicates + } + } + } + std::map::iterator it; + for (it = libPathes.begin(); it != libPathes.end(); ++it) { + extLibPathes.push_back(it->first); + } +} + +bool ProjectGenHelper::hasReferencedProject() +{ + if (!Zflag) return false; + ProjectDescriptor* topLevel = getTargetOfProject(nameOfTopLevelProject.c_str()); + if (topLevel && topLevel->numOfReferencedProjects()) return true; + return false; +} + +bool ProjectGenHelper::isTtcn3ModuleInLibrary(const char* moduleName) const +{ + if (!Zflag) return false; + for (std::map::const_iterator it = projs.begin(); it != projs.end(); ++it) { + if ((it->second).hasTtcn3ModuleName(moduleName) && (it->second).isLibrary()) return true; + } + return false; +} + +bool ProjectGenHelper::isAsn1ModuleInLibrary(const char* moduleName) const +{ + if (!Zflag) return false; + for (std::map::const_iterator it = projs.begin(); it != projs.end(); ++it) { + if ((it->second).hasAsn1ModuleName(moduleName) && (it->second).isLibrary()) return true; + } + return false; +} + +bool ProjectGenHelper::isSourceFileInLibrary(const char* fileName) const +{ + if (!Zflag || NULL == fileName) return false; + for (std::map::const_iterator it = projs.begin(); it != projs.end(); ++it) { + if ((it->second).hasUserSource(fileName) && (it->second).isLibrary()) return true; + } + return false; +} + +bool ProjectGenHelper::isHeaderFileInLibrary(const char* fileName) const +{ + if (!Zflag || NULL == fileName) return false; + + for (std::map::const_iterator it = projs.begin(); it != projs.end(); ++it) { + if ((it->second).hasUserHeader(fileName) && (it->second).isLibrary()) return true; + } + return false; +} + +bool ProjectGenHelper::isTtcnPPFileInLibrary(const char* fileName) const +{ + if (!Zflag || NULL == fileName) return false; + + for (std::map::const_iterator it = projs.begin(); it != projs.end(); ++it) { + if ((it->second).hasTtcn3PP(fileName) && (it->second).isLibrary()) return true; + } + return false; +} + +bool ProjectGenHelper::isCPPSourceFile(const char* fileName) const +{ + std::string fnStr(fileName); + size_t pos = fnStr.find_last_of('.'); + if (std::string::npos == pos) return false; + const std::string EXT_CC("cc"); + const std::string EXT_CPP("cpp"); + int length = 0; + if (std::string::npos != fnStr.find (EXT_CC, pos + 1)) + length = EXT_CC.size(); + else if (std::string::npos != fnStr.find (EXT_CPP, pos + 1)) + length = EXT_CPP.size(); + + if (length && fnStr.size() == pos + length + 1) + return true; + else + return false; +} + +bool ProjectGenHelper::isCPPHeaderFile(const char* fileName) const +{ + std::string fnStr(fileName); + size_t pos = fnStr.find_last_of('.'); + if (std::string::npos == pos) return false; + const std::string EXT_HPP("hpp"); + const std::string EXT_HH("hh"); + const std::string EXT_H("h"); + int length = 0; + if (std::string::npos != fnStr.find (EXT_HH, pos + 1)) + length = EXT_HH.size(); + else if (std::string::npos != fnStr.find (EXT_HPP, pos + 1)) + length = EXT_HPP.size(); + else if (std::string::npos != fnStr.find (EXT_H, pos + 1)) + length = EXT_H.size(); + + if (length && fnStr.size() == pos + length + 1) + return true; + else + return false; +} + +bool ProjectGenHelper::isTtcnPPFile(const char* fileName) const +{ + std::string fnStr(fileName); + size_t pos = fnStr.find_last_of('.'); + if (std::string::npos == pos) return false; + const std::string EXT_TTCNPP("ttcnpp"); + int length = 0; + if (std::string::npos != fnStr.find (EXT_TTCNPP, pos + 1)) + length = EXT_TTCNPP.size(); + + if (length && fnStr.size() == pos + length + 1) + return true; + else + return false; +} + +void ProjectGenHelper::print() +{ + if (!Zflag) return; + fprintf(stderr, "Top Level project : %s\n", nameOfTopLevelProject.c_str()); + for (std::map::iterator it = projs.begin(); it != projs.end(); ++it) { + (it->second).print(); + } +} + +bool ProjectGenHelper::sanityCheck() +{ + if (!Zflag) return true; + bool ret = true; +// if toplevel is a dynamic linked executable (not library) all executable shall set to the same linking method + { + ProjectDescriptor* topLevel = getTargetOfProject(nameOfTopLevelProject.c_str()); + bool isDynamicLinked = topLevel->getLinkingStrategy(); + if (!topLevel->isLibrary() && isDynamicLinked) { // dynamic linked executable + for (std::map::iterator it = projs.begin(); it != projs.end(); ++it) { + if (!(it->second).isLibrary()) { //if exectubale + if (isDynamicLinked != (it->second).getLinkingStrategy()) { + ERROR("project \"%s\" is set to %s linking. Sub project \"%s\" is set to %s linking. " + "All sub-level executable shall be set to the %s's type.", + nameOfTopLevelProject.c_str(), + isDynamicLinked ? "dynamic" : "static", + ((it->second).getProjectName()).c_str(), + isDynamicLinked ? "static" : "dynamic", + nameOfTopLevelProject.c_str()); + ret = false; + } + } + } + } + } + +// under a dynamic linked library every project shall be linked dynamic library too. + { + checkedProjs.clear(); + bool found = false; // search for executable under dynamic linked library + char* execName = NULL; + for (std::map::reverse_iterator rit = projs.rbegin(); rit != projs.rend(); ++rit) { + if ((rit->second).isLibrary() && (rit->second).getLinkingStrategy()) { //dynamic library + ProjectDescriptor& proj = rit->second; + found = DynamicLibraryChecker(&proj, found, &execName); + if (found) { + ERROR("Project \"%s\" is dynamic linked library. Sub project \"%s\" is executable.\n" + "in TPD file, %s's all sub-level defaultTarget shall be set library too.", + proj.getProjectName().c_str(), execName, proj.getProjectName().c_str()); + ret = false; + break; + } + } + } + } + + return ret; +} + +ProjectDescriptor* ProjectGenHelper::getProject(const char* projName) +{ + if (!projName) return NULL; + for (std::map::iterator it = projs.begin(); it != projs.end(); ++it) { + if (it->first == std::string(projName)) { + return &(it->second); + } + } + return NULL; +} + +const ProjectDescriptor* ProjectGenHelper::getProject(const char* projName) const +{ + if (!projName) return NULL; + for (std::map::const_iterator it = projs.begin(); it != projs.end(); ++it) { + if (it->first == std::string(projName)) { + return &(it->second); + } + } + return NULL; +} + + +void ProjectGenHelper::cleanUp() +{ + if (!Zflag) return; + checkedProjs.clear(); + for (std::map::iterator it = projs.begin(); it != projs.end(); ++it) { + (it->second).cleanUp(); + } +} + +bool ProjectGenHelper::DynamicLibraryChecker(const ProjectDescriptor* desc, + bool& found, + char** executableName) +{ + if (found || !desc) return true; + for (size_t i = 0; i < desc->numOfReferencedProjects(); ++i) { + char* refProjName = const_cast (desc->getReferencedProject(i).c_str()); + const ProjectDescriptor* subProj = getTargetOfProject(refProjName); + if (0 == checkedProjs.count(subProj->getProjectName())) { + if (subProj->isLibrary()) { + found = DynamicLibraryChecker(subProj, found, executableName); + } + else { // search for executable under dynamic linked library + found = true; + *executableName = refProjName; + break; + } + } + } + // it is checked, no such executable was found. Store it not to iterate again + if (!found) + checkedProjs.insert(std::pair + (desc->getProjectName(), desc)); + return found; +} + diff --git a/compiler2/ProjectGenHelper.hh b/compiler2/ProjectGenHelper.hh new file mode 100644 index 0000000..638633b --- /dev/null +++ b/compiler2/ProjectGenHelper.hh @@ -0,0 +1,157 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _LIB_GEN_HELPER_HH +#define _LIB_GEN_HELPER_HH +#include +#include +#include +#include +class ProjectGenHelper; +class ProjectDescriptor { +public: + explicit ProjectDescriptor(const char* name); + ~ProjectDescriptor() { cleanUp(); }; + + const std::string& getProjectName() const { return projectName; } + void setTPDFileName( const char* name); + const std::string& getTPDFileName() const { return tpdFileName; } + void setTargetExecName(const char* name) { targetExecutableName = std::string(name); } + const std::string& getTargetExecName() const { return targetExecutableName; } + void setProjectAbsTpdDir(const char* name) { projectAbsTpdDir = std::string(name); } + const std::string& getProjectAbsTpdDir() const { return projectAbsTpdDir; } + void setProjectAbsWorkingDir(const char* name); + void setProjectWorkingDir(const char* name) { projectWorkingDir = std::string(name); } + const std::string& getProjectAbsWorkingDir() const { return projectAbsWorkingDir; } + const std::string& getProjectWorkingDir() const { return projectWorkingDir; } + void setLinkingStrategy(bool strategy) { dynamicLinked = strategy; } + bool getLinkingStrategy() const { return dynamicLinked; } + void setLibrary(bool isLib) { library = isLib; } + bool isLibrary() const { return library; } + bool isInitialized(); + void addToReferencedProjects(const char* refProjName); + void addToRefProjWorkingDirs(const std::string& subProjDir); + bool hasLinkerLibTo(const std::string& refProjName) const; + bool hasLinkerLib(const char* libName) const; // Linker Lib got from TPD + void addToLibSearchPaths(const char* libSearchPath); + void addToLinkerLibs(const char* linkerLibs); + void print(); + void cleanUp(); + size_t numOfReferencedProjects() const { return referencedProjects.size(); }; + size_t numOfRefProjWorkingDirs() const { return refProjWorkingDirs.size(); }; + size_t numOfLibSearchPaths() const { return libSearchPaths.size(); }; + size_t numOfLinkerLibs() const { return linkerLibraries.size(); }; + const std::string& getReferencedProject(size_t index) const + { return index < referencedProjects.size() ? referencedProjects[index] : emptyString; }; + const std::string& getRefProjWorkingDir(size_t index) const + { return index < refProjWorkingDirs.size() ? refProjWorkingDirs[index] : emptyString; }; + const char* getLibSearchPath(const std::string& subProjName) const; + const char* getLibSearchPath(size_t index) const { return libSearchPaths[index].c_str(); }; + const char* getLinkerLib(const std::string& subProjName) const; + const char* getLinkerLib(size_t index) const { return linkerLibraries[index].c_str(); }; + size_t getLibSearchPathIndex(const std::string& subProjName) const; + void setLibSearchPath(size_t index, const std::string& relPath) { libSearchPaths[index] = relPath; }; + void addTtcn3ModuleName(const char* name) { ttcn3ModuleNames.push_back(name); }; + bool hasTtcn3ModuleName(const char* moduleName) const; + void addAsn1ModuleName(const char* name) { asn1ModuleNames.push_back(name); }; + bool hasAsn1ModuleName(const char* moduleName) const; + void addUserSource(const char* name) { userSources.push_back(name); }; + bool hasUserSource(const char* userSourceName) const; + void addUserHeader(const char* name) { userHeaders.push_back(name); }; + bool hasUserHeader(const char* userHeaderName) const; + void addTtcn3PP(const char* name) { ttcnPP.push_back(name); }; + bool hasTtcn3PP(const char* ttcnPPName) const; + std::string setRelativePathTo(const std::string& absPathTo); + +private: + static const std::string emptyString; + std::string projectName; + std::string tpdFileName; + std::string targetExecutableName; //Library or Executable(only the top level) + std::string projectAbsTpdDir; + std::string projectAbsWorkingDir; + std::string projectWorkingDir; + bool library; + bool dynamicLinked; + std::vector referencedProjects; + std::vector refProjWorkingDirs; + std::vector libSearchPaths; + std::vector linkerLibraries; + std::vector ttcn3ModuleNames; + std::vector asn1ModuleNames; + std::vector userSources; // *.cc ; *.cpp + std::vector userHeaders; // *.hh ; *.h ; *.hpp + std::vector ttcnPP; // *.ttcnpp + bool initialized; +}; + +class ProjectGenHelper { +public: + static ProjectGenHelper &Instance(); + ~ProjectGenHelper() { cleanUp(); }; + void setZflag(bool flag) { Zflag = flag; }; + bool getZflag() const { return Zflag; }; + void setWflag(bool flag) { Wflag = flag; }; + bool getWflag() const { return Wflag; }; + void setHflag(bool flag) { Hflag = flag; }; + bool getHflag() const { return Hflag; }; + void setToplevelProjectName(const char* name); + const std::string& getToplevelProjectName() const { return nameOfTopLevelProject; }; + void setRootDirOS(const char* name); + const std::string& getRootDirOS(const char* name); + void addTarget(const char* projName); + void generateRefProjectWorkingDirsTo(const char* projName); + void addTtcn3ModuleToProject(const char* projName, const char* moduleName); + void addAsn1ModuleToProject(const char* projName, const char* moduleName); + void addUserSourceToProject(const char* projName, const char* userSourceName); + void addUserHeaderToProject(const char* projName, const char* userHeaderName); + void addTtcnPPToProject(const char* projName, const char* ttcnPPName); + bool isTtcn3ModuleInLibrary(const char* moduleName) const; + bool isAsn1ModuleInLibrary(const char* moduleName) const; + bool isSourceFileInLibrary(const char* fileName) const; + bool isHeaderFileInLibrary(const char* fileName) const; + bool isTtcnPPFileInLibrary(const char* fileName) const; + ProjectDescriptor* getTargetOfProject(const char* projName); + const ProjectDescriptor* getTargetOfProject(const char* projName) const; + ProjectDescriptor* getProjectDescriptor(const char* targetName); //target_executable_name + std::map::const_iterator getHead() const; + std::map::const_iterator getEnd() const; + size_t numOfLibs() const; + void getExternalLibs(std::vector& extLibs); + void getExternalLibSearchPathes(std::vector& extLibPathes); + bool hasReferencedProject(); + size_t numOfProjects() const { return projs.size();}; + bool isCPPSourceFile(const char* fileName) const; + bool isCPPHeaderFile(const char* fileName) const; + bool isTtcnPPFile(const char* fileName) const; + void print(); + bool sanityCheck(); // tests if the structure generated from TPDs is consistent + void cleanUp(); + +private: + ProjectGenHelper(); + ProjectGenHelper(const ProjectGenHelper &rhs); + ProjectGenHelper &operator=(const ProjectGenHelper &rhs); + ProjectDescriptor* getProject(const char* projName); + const ProjectDescriptor* getProject(const char* projName) const; + bool DynamicLibraryChecker(const ProjectDescriptor* desc, + bool& found, + char** executableName); +private: + static ProjectGenHelper& intance; + static const std::string emptyString; + std::string nameOfTopLevelProject; + std::string rootDirOS; // make archive needs the top dir on OS level + std::string relPathToRootDirOS; + bool Zflag; // the makefilegen switch wether to use this option at all + bool Wflag; // prefix woring directory + bool Hflag; // hierarchical make structure + std::map projs; + std::map checkedProjs; +}; + +#endif // _LIB_GEN_HELPER_HH diff --git a/compiler2/Setting.cc b/compiler2/Setting.cc index 64c02b6..1dae00b 100644 --- a/compiler2/Setting.cc +++ b/compiler2/Setting.cc @@ -232,6 +232,12 @@ namespace Common { mputprintf(effective_module_functions, "%s\"%s\"", (effective_module_functions ? ", " : ""), entityname); } + if (profiler_enabled) { + str = mputprintf(str, + "TTCN3_Stack_Depth stack_depth;\n" + "ttcn3_prof.enter_function(\"%s\", %d, \"%s\");\n", + filename, yyloc.first_line, entityname); + } } return str; } @@ -242,6 +248,10 @@ namespace Common { if (include_location_info && !transparency) { str = mputprintf(str, "current_location.update_lineno(%d);\n", yyloc.first_line); + if (profiler_enabled) { + str = mputprintf(str, "ttcn3_prof.execute_line(\"%s\", %d);\n", + get_filename(), yyloc.first_line); + } if (tcov_file_name && in_tcov_files(get_filename())) { effective_module_lines = mputprintf(effective_module_lines, "%s%d", @@ -544,9 +554,9 @@ namespace Common { else return false; } - Type *Scope::get_mtc_system_comptype(bool is_system, bool is_connecting) + Type *Scope::get_mtc_system_comptype(bool is_system) { - if (parent_scope) return parent_scope->get_mtc_system_comptype(is_system, is_connecting); + if (parent_scope) return parent_scope->get_mtc_system_comptype(is_system); else return 0; } diff --git a/compiler2/Setting.hh b/compiler2/Setting.hh index 7ddf074..82f1bfc 100644 --- a/compiler2/Setting.hh +++ b/compiler2/Setting.hh @@ -592,10 +592,9 @@ public: virtual bool has_ass_withId(const Identifier& p_id); virtual bool is_valid_moduleid(const Identifier& p_id); /** Returns the TTCN-3 component type that is associated with - * keywords 'mtc' or 'system'. Returns NULL outside testcase definitions - * (unless it's a 'map' or 'connect' statement block) or if the component type - * cannot be determined. */ - virtual Type *get_mtc_system_comptype(bool is_system, bool is_connecting); + * keywords 'mtc' or 'system'. Returns NULL if the component type + * cannot be determined (i.e. outside testcase definitions). */ + virtual Type *get_mtc_system_comptype(bool is_system); /** Checks the 'runs on' clause of definition \a p_ass that it can * be called from this scope unit. Parameters \a p_loc and \a * p_what are used in error messages. \a p_what contains "call" or diff --git a/compiler2/Type.cc b/compiler2/Type.cc index 2f59ba7..2a9683d 100644 --- a/compiler2/Type.cc +++ b/compiler2/Type.cc @@ -573,6 +573,7 @@ namespace Common { ownertype = OT_UNKNOWN; owner = 0; chk_finished = false; + pard_type_instance = false; } void Type::clean_up() @@ -5204,8 +5205,8 @@ end_ext: bool Type::hasEncodeAttr(const MessageEncodingType_t encoding_type) { - if (CT_JSON == encoding_type && - (is_asn1() || (is_ref() && get_type_refd()->is_asn1()))) { + if (CT_JSON == encoding_type && (implicit_json_encoding + || is_asn1() || (is_ref() && get_type_refd()->is_asn1()))) { // ASN.1 types automatically support JSON encoding return true; } @@ -5573,10 +5574,15 @@ end_ext: case T_UNIVERSALSTRING: case T_BMPSTRING: case T_VERDICT: + case T_NULL: + case T_OID: + case T_ROID: + case T_ANY: // these basic types support JSON encoding by default return json_mem.remember(t, ANSWER_YES); case T_SEQ_T: case T_SEQ_A: + case T_OPENTYPE: case T_SET_T: case T_SET_A: case T_CHOICE_T: @@ -5645,7 +5651,7 @@ end_ext: case T_ENUM_T: case T_ENUM_A: break; // check for an encode attribute - default: + default: return json_mem.remember(t, ANSWER_NO); } // switch return json_mem.remember(t, hasEncodeAttr(CT_JSON) ? ANSWER_YES : ANSWER_NO); @@ -6815,10 +6821,6 @@ end_ext: string Type::get_dispname() const { - if (T_REFD == typetype) { - // cannot calculate the display name for referenced types this way - FATAL_ERROR("Type::get_dispname()"); - } string dispname = genname; size_t pos = 0; while(pos < dispname.size()) { diff --git a/compiler2/Type.hh b/compiler2/Type.hh index f15b4e5..55737c9 100644 --- a/compiler2/Type.hh +++ b/compiler2/Type.hh @@ -380,6 +380,11 @@ namespace Common { /** True if chk() has finished running. * Prevents force_raw() from running chk_raw(), chk_text() or chk_json() on unchecked types. */ bool chk_finished; + + /** Signifies that this type is an instance of an ASN.1 parameterized type. + * It will not have its own segment and reference generated in the JSON schema, + * its schema segment will be generated as an embedded type's would. */ + bool pard_type_instance; /** Copy constructor, for the use of Type::clone() only. */ Type(const Type& p); @@ -786,6 +791,7 @@ namespace Common { * If \a v is correct and it is or refers to a constant the constant value * is returned for further checking. Otherwise the return value is NULL. */ Value *chk_range_boundary(Value *v, const char *which, const Location& loc); + void chk_range_boundary_infinity(Value *v, bool is_upper); void chk_this_template_builtin(Template *t); void chk_this_template_Int_Real(Template *t); void chk_this_template_Enum(Template *t); @@ -1128,6 +1134,9 @@ namespace Common { bool is_untagged() const; + inline boolean is_pard_type_instance() { return pard_type_instance; } + inline void set_pard_type_instance() { pard_type_instance = true; } + /** Calculates the type's display name from the genname (replaces double * underscore characters with single ones) */ string get_dispname() const; @@ -1152,6 +1161,10 @@ namespace Common { /** Generates the JSON schema segment that would validate a union type or * an anytype and inserts it into the main schema. */ void generate_json_schema_union(JSON_Tokenizer& json); + + /** Generates a reference to this type's schema segment and inserts it into + * the given schema. */ + void generate_json_schema_ref(JSON_Tokenizer& json); }; /** @} end of AST_Type group */ diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc index 7aee9f7..d3861eb 100644 --- a/compiler2/Type_chk.cc +++ b/compiler2/Type_chk.cc @@ -639,8 +639,8 @@ void Type::chk_xer_any_attributes() for (size_t x = 0; x < parent_type->get_nof_comps(); ++x) { CompField * cf = parent_type->get_comp_byIndex(x); if (cf->get_type() != this) continue; - if (cf->has_default() || cf->get_is_optional()) { - error("The field with ANY-ATTRIBUTES cannot be OPTIONAL or DEFAULT"); + if (cf->has_default()) { + error("The field with ANY-ATTRIBUTES cannot have DEFAULT"); } } break; @@ -5613,6 +5613,37 @@ void Type::chk_this_template_Str(Template *t) } } +void Type::chk_range_boundary_infinity(Value *v, bool is_upper) +{ + if (v) { + v->set_my_governor(this); + { + Error_Context cntxt2(v, "In %s boundary", is_upper ? "upper" : "lower"); + chk_this_value_ref(v); + Value *v_last = v->get_value_refd_last(0, EXPECTED_STATIC_VALUE); + if (v_last->get_valuetype() == Value::V_OMIT) { + v->error("`omit' value is not allowed in this context"); + v->set_valuetype(Value::V_ERROR); + return; + } + if (sub_type != NULL) { + if (is_upper) { + if (!sub_type->get_root()->is_upper_limit_infinity()) { + v->error("Infinity is not a valid value for type '%s' which has subtype %s", + asString(), sub_type->to_string().c_str()); + } + } + else { + if (!sub_type->get_root()->is_lower_limit_infinity()) { + v->error("Infinity is not a valid value for type '%s' which has subtype %s", + asString(), sub_type->to_string().c_str()); + } + } + } + } + } +} + Value *Type::chk_range_boundary(Value *v, const char *which, const Location& loc) { @@ -5693,6 +5724,12 @@ void Type::chk_this_template_Int_Real(Template *t) FATAL_ERROR("Type::chk_this_template_Int_Real()"); } } + if (v_lower && !v_upper) { + chk_range_boundary_infinity(v_lower, true); + } + if (!v_lower && v_upper) { + chk_range_boundary_infinity(v_upper, false); + } break;} default: t->error("%s cannot be used for type `%s'", t->get_templatetype_str(), diff --git a/compiler2/Type_codegen.cc b/compiler2/Type_codegen.cc index 6e9679c..b6baffb 100644 --- a/compiler2/Type_codegen.cc +++ b/compiler2/Type_codegen.cc @@ -243,6 +243,7 @@ void Type::generate_code_typedescriptor(output_struct *target) case OT_TYPE_DEF: case OT_COMP_FIELD: case OT_RECORD_OF: + case OT_REF_SPEC: force_xer = has_encoding(CT_XER); // && (is_ref() || (xerattrib && !xerattrib->empty())); break; default: @@ -362,10 +363,20 @@ void Type::generate_code_typedescriptor(output_struct *target) case T_UNIVERSALSTRING: case T_BMPSTRING: case T_VERDICT: + case T_NULL: + case T_OID: + case T_ROID: + case T_ANY: // use predefined JSON descriptors instead of null pointers for basic types target->source.global_vars = mputprintf(target->source.global_vars, "&%s_json_, ", gennamejsondescriptor.c_str()); break; + case T_ENUM_T: + case T_ENUM_A: + // use a predefined JSON descriptor for enumerated types + target->source.global_vars = mputstr(target->source.global_vars, + "&ENUMERATED_json_, "); + break; default: target->source.global_vars = mputstr(target->source.global_vars, "NULL, "); @@ -389,24 +400,14 @@ void Type::generate_code_typedescriptor(output_struct *target) "const TTCN_Typedescriptor_t& %s_descr_ = %s_descr_;\n", gennameown_str, gennametypedescriptor.c_str()); } - else { - /* In general, we avoid generating a XER descriptor for - * "artificial" types. */ - - if (ownertype==OT_REF_SPEC) { - // A XER descriptor without a TTCN descriptor to own it - generate_code_xerdescriptor(target); - } #ifndef NDEBUG - else - target->source.global_vars = mputprintf(target->source.global_vars, - "// %s_xer_ elided\n", gennameown_str); - + else { target->source.global_vars = mputprintf( target->source.global_vars, "// %s_descr_ not needed, use %s_descr_\n", gennameown_str, gennametypedescriptor.c_str()); -#endif } // if(needs_alias()) +#endif + } // if (gennameown == gennametypedescriptor) } @@ -2617,10 +2618,10 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val // stored if this is a field of a union with the "as value" coding instruction if (ownertype == OT_COMP_FIELD) { CompField* cf = static_cast(owner); - if(as_value || (cf->get_type()->jsonattrib != NULL - && cf->get_type()->jsonattrib->alias != NULL)) { + if (as_value || (cf->get_type()->jsonattrib != NULL + && cf->get_type()->jsonattrib->alias != NULL)) { json.put_next_token(JSON_TOKEN_NAME, "originalName"); - char* field_str = mprintf("\"%s\"", cf->get_name().get_dispname().c_str()); + char* field_str = mprintf("\"%s\"", cf->get_name().get_ttcnname().c_str()); json.put_next_token(JSON_TOKEN_STRING, field_str); Free(field_str); } @@ -2635,18 +2636,20 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val Free(alias_str); } } - + // get the type at the end of the reference chain Type* last = get_type_refd_last(); // if the type has its own definition and it's embedded in another type, then // its schema already exists, only add a reference to it - if (embedded && (last->ownertype == OT_TYPE_DEF /* TTCN-3 type definition */ + // exception: instances of ASN.1 parameterized types, always embed their schemas + if (embedded && (!is_ref() || !get_type_refd()->pard_type_instance) && + (last->ownertype == OT_TYPE_DEF /* TTCN-3 type definition */ || last->ownertype == OT_TYPE_ASS /* ASN.1 type assignment */ )) { json.put_next_token(JSON_TOKEN_NAME, "$ref"); char* ref_str = mprintf("\"#/definitions/%s/%s\"", - last->my_scope->get_scope_mod()->get_modid().get_dispname().c_str(), - last->get_dispname().c_str()); + last->my_scope->get_scope_mod()->get_modid().get_ttcnname().c_str(), + (is_ref() && last->pard_type_instance) ? get_type_refd()->get_dispname().c_str() : last->get_dispname().c_str()); json.put_next_token(JSON_TOKEN_STRING, ref_str); Free(ref_str); } else { @@ -2685,15 +2688,17 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val case T_BSTR_A: case T_HSTR: case T_OSTR: + case T_ANY: // use the JSON string type and add a pattern to only allow bits or hex digits json.put_next_token(JSON_TOKEN_NAME, "type"); json.put_next_token(JSON_TOKEN_STRING, "\"string\""); json.put_next_token(JSON_TOKEN_NAME, "subType"); - json.put_next_token(JSON_TOKEN_STRING, (last->typetype == T_OSTR) ? "\"octetstring\"" : + json.put_next_token(JSON_TOKEN_STRING, + (last->typetype == T_OSTR || last->typetype == T_ANY) ? "\"octetstring\"" : ((last->typetype == T_HSTR) ? "\"hexstring\"" : "\"bitstring\"")); json.put_next_token(JSON_TOKEN_NAME, "pattern"); json.put_next_token(JSON_TOKEN_STRING, - (last->typetype == T_OSTR) ? "\"^([0-9A-Fa-f][0-9A-Fa-f])*$\"" : + (last->typetype == T_OSTR || last->typetype == T_ANY) ? "\"^([0-9A-Fa-f][0-9A-Fa-f])*$\"" : ((last->typetype == T_HSTR) ? "\"^[0-9A-Fa-f]*$\"" : "\"^[01]*$\"")); break; case T_CSTR: @@ -2723,6 +2728,15 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val json.put_next_token(JSON_TOKEN_NAME, "subType"); json.put_next_token(JSON_TOKEN_STRING, "\"universal charstring\""); break; + case T_OID: + case T_ROID: + json.put_next_token(JSON_TOKEN_NAME, "type"); + json.put_next_token(JSON_TOKEN_STRING, "\"string\""); + json.put_next_token(JSON_TOKEN_NAME, "subType"); + json.put_next_token(JSON_TOKEN_STRING, "\"objid\""); + json.put_next_token(JSON_TOKEN_NAME, "pattern"); + json.put_next_token(JSON_TOKEN_STRING, "\"^[0-2][.][1-3]?[0-9]([.][0-9]|([1-9][0-9]+))*$\""); + break; case T_VERDICT: // enumerate the possible values json.put_next_token(JSON_TOKEN_NAME, "enum"); @@ -2739,8 +2753,8 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val // enumerate the possible values json.put_next_token(JSON_TOKEN_NAME, "enum"); json.put_next_token(JSON_TOKEN_ARRAY_START); - for (size_t i = 0; i < u.enums.eis->get_nof_eis(); ++i) { - char* enum_str = mprintf("\"%s\"", get_ei_byIndex(i)->get_name().get_dispname().c_str()); + for (size_t i = 0; i < last->u.enums.eis->get_nof_eis(); ++i) { + char* enum_str = mprintf("\"%s\"", last->get_ei_byIndex(i)->get_name().get_ttcnname().c_str()); json.put_next_token(JSON_TOKEN_STRING, enum_str); Free(enum_str); } @@ -2748,13 +2762,18 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val // list the numeric values for the enumerated items json.put_next_token(JSON_TOKEN_NAME, "numericValues"); json.put_next_token(JSON_TOKEN_ARRAY_START); - for (size_t i = 0; i < u.enums.eis->get_nof_eis(); ++i) { - char* num_val_str = mprintf("%lli", get_ei_byIndex(i)->get_value()->get_val_Int()->get_val()); + for (size_t i = 0; i < last->u.enums.eis->get_nof_eis(); ++i) { + char* num_val_str = mprintf("%lli", last->get_ei_byIndex(i)->get_value()->get_val_Int()->get_val()); json.put_next_token(JSON_TOKEN_NUMBER, num_val_str); Free(num_val_str); } json.put_next_token(JSON_TOKEN_ARRAY_END); break; + case T_NULL: + // use the JSON null value for the ASN.1 NULL type + json.put_next_token(JSON_TOKEN_NAME, "type"); + json.put_next_token(JSON_TOKEN_STRING, "\"null\""); + break; case T_SEQOF: case T_SETOF: case T_ARRAY: @@ -2769,6 +2788,7 @@ void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_val case T_CHOICE_T: case T_CHOICE_A: case T_ANYTYPE: + case T_OPENTYPE: last->generate_json_schema_union(json); break; default: @@ -2862,17 +2882,20 @@ void Type::generate_json_schema_record(JSON_Tokenizer& json) // use the field's alias if it has one json.put_next_token(JSON_TOKEN_NAME, (field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ? - field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_dispname().c_str()); + field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str()); // optional fields can also get the JSON null value if (get_comp_byIndex(i)->get_is_optional()) { - json.put_next_token(JSON_TOKEN_OBJECT_START); - json.put_next_token(JSON_TOKEN_NAME, "anyOf"); - json.put_next_token(JSON_TOKEN_ARRAY_START); - json.put_next_token(JSON_TOKEN_OBJECT_START); - json.put_next_token(JSON_TOKEN_NAME, "type"); - json.put_next_token(JSON_TOKEN_STRING, "\"null\""); - json.put_next_token(JSON_TOKEN_OBJECT_END); + // special case: ASN NULL type, since it uses the JSON literal "null" as a value + if (T_NULL != field->get_type_refd_last()->typetype) { + json.put_next_token(JSON_TOKEN_OBJECT_START); + json.put_next_token(JSON_TOKEN_NAME, "anyOf"); + json.put_next_token(JSON_TOKEN_ARRAY_START); + json.put_next_token(JSON_TOKEN_OBJECT_START); + json.put_next_token(JSON_TOKEN_NAME, "type"); + json.put_next_token(JSON_TOKEN_STRING, "\"null\""); + json.put_next_token(JSON_TOKEN_OBJECT_END); + } } else if (!has_non_optional) { has_non_optional = true; } @@ -2882,7 +2905,8 @@ void Type::generate_json_schema_record(JSON_Tokenizer& json) // for optional fields: specify the presence of the "omit as null" coding instruction // and close structures - if (get_comp_byIndex(i)->get_is_optional()) { + if (get_comp_byIndex(i)->get_is_optional() && + T_NULL != field->get_type_refd_last()->typetype) { json.put_next_token(JSON_TOKEN_ARRAY_END); json.put_next_token(JSON_TOKEN_NAME, "omitAsNull"); json.put_next_token((field->jsonattrib != NULL && field->jsonattrib->omit_as_null) ? @@ -2907,7 +2931,7 @@ void Type::generate_json_schema_record(JSON_Tokenizer& json) // use the field's alias if it has one char* field_str = mprintf("\"%s\"", (field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ? - field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_dispname().c_str()); + field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str()); json.put_next_token(JSON_TOKEN_STRING, field_str); Free(field_str); } @@ -2924,7 +2948,7 @@ void Type::generate_json_schema_record(JSON_Tokenizer& json) // use the field's alias if it has one char* field_str = mprintf("\"%s\"", (field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ? - field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_dispname().c_str()); + field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str()); json.put_next_token(JSON_TOKEN_STRING, field_str); Free(field_str); } @@ -2959,7 +2983,7 @@ void Type::generate_json_schema_union(JSON_Tokenizer& json) // use the alternative's alias if it has one json.put_next_token(JSON_TOKEN_NAME, (field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ? - field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_dispname().c_str()); + field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str()); // let the alternative's type insert its schema field->generate_json_schema(json, true, false); @@ -2977,7 +3001,7 @@ void Type::generate_json_schema_union(JSON_Tokenizer& json) // use the alternative's alias here as well char* field_str = mprintf("\"%s\"", (field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ? - field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_dispname().c_str()); + field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str()); json.put_next_token(JSON_TOKEN_STRING, field_str); Free(field_str); @@ -2991,6 +3015,23 @@ void Type::generate_json_schema_union(JSON_Tokenizer& json) json.put_next_token(JSON_TOKEN_ARRAY_END); } +void Type::generate_json_schema_ref(JSON_Tokenizer& json) +{ + // start the object containing the reference + json.put_next_token(JSON_TOKEN_OBJECT_START); + + // insert the reference + json.put_next_token(JSON_TOKEN_NAME, "$ref"); + char* ref_str = mprintf("\"#/definitions/%s/%s\"", + my_scope->get_scope_mod()->get_modid().get_ttcnname().c_str(), + get_dispname().c_str()); + json.put_next_token(JSON_TOKEN_STRING, ref_str); + Free(ref_str); + + // the object will be closed later, as it may contain other properties +} + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ } // namespace Common diff --git a/compiler2/Value.cc b/compiler2/Value.cc index 4f51aa3..a1c1c8a 100644 --- a/compiler2/Value.cc +++ b/compiler2/Value.cc @@ -3178,10 +3178,10 @@ namespace Common { case OPTYPE_CONCAT: return get_expr_governor_v1v2(exp_val); case OPTYPE_COMP_MTC: - if (my_scope) return my_scope->get_mtc_system_comptype(false, false); + if (my_scope) return my_scope->get_mtc_system_comptype(false); else return 0; case OPTYPE_COMP_SYSTEM: - if (my_scope) return my_scope->get_mtc_system_comptype(true, false); + if (my_scope) return my_scope->get_mtc_system_comptype(true); else return 0; case OPTYPE_COMP_SELF: if (my_scope) { @@ -3234,18 +3234,6 @@ namespace Common { if(valuetype != V_INVOKE) FATAL_ERROR("Value::get_invoked_type()"); return u.invoke.v->get_expr_governor(exp_val); } - - Type* Value::get_component_governor() - { - if (V_EXPR == valuetype && OPTYPE_COMP_MTC == u.expr.v_optype) { - if (my_scope) { - return my_scope->get_mtc_system_comptype(false, true); - } else { - return 0; - } - } - return get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE); - } const char* Value::get_opname() const { @@ -4048,10 +4036,10 @@ namespace Common { Type *t_comptype; switch (u.expr.v_optype) { case OPTYPE_COMP_MTC: - t_comptype = my_scope->get_mtc_system_comptype(false, false); + t_comptype = my_scope->get_mtc_system_comptype(false); break; case OPTYPE_COMP_SYSTEM: - t_comptype = my_scope->get_mtc_system_comptype(true, false); + t_comptype = my_scope->get_mtc_system_comptype(true); break; case OPTYPE_COMP_SELF: { Ttcn::RunsOnScope *t_ros = my_scope->get_scope_runs_on(); @@ -10009,13 +9997,14 @@ error: string Value::create_stringRepr() { + // note: cannot call is_asn1() when only parsing (scopes are not properly set) switch (valuetype) { case V_ERROR: return string(""); case V_NULL: return string("NULL"); case V_BOOL: - if (is_asn1()) { + if (!parse_only && is_asn1()) { if (u.val_bool) return string("TRUE"); else return string("FALSE"); } @@ -10066,7 +10055,7 @@ error: case V_OID: case V_ROID: { string ret_val; - if (!is_asn1()) ret_val += "objid "; + if (parse_only || !is_asn1()) ret_val += "objid "; ret_val += "{ "; for (size_t i = 0; i < u.oid_comps->size(); i++) { if (i>0) ret_val += ' '; @@ -10075,7 +10064,7 @@ error: ret_val += " }"; return ret_val; } case V_CHOICE: - if (is_asn1()) { + if (!parse_only && is_asn1()) { string ret_val(u.choice.alt_name->get_dispname()); ret_val += " : "; ret_val += u.choice.alt_value->get_stringRepr(); @@ -10109,7 +10098,7 @@ error: case V_SEQ: case V_SET: { string ret_val("{ "); - bool asn1_flag = is_asn1(); + bool asn1_flag = !parse_only && is_asn1(); for (size_t i = 0; i < u.val_nvs->get_nof_nvs(); i++) { if (i > 0) ret_val += ", "; NamedValue *nv = u.val_nvs->get_nv_byIndex(i); diff --git a/compiler2/Value.hh b/compiler2/Value.hh index 47eedeb..cfd3f79 100644 --- a/compiler2/Value.hh +++ b/compiler2/Value.hh @@ -479,11 +479,6 @@ namespace Common { Type* get_expr_governor_last(); /** get the type invoked */ Type *get_invoked_type(Type::expected_value_t exp_val); - - /** An alternative version of get_expr_governor for components. This will - * return the MTC component type in function and altstep scopes as well. - * Calls get_expr_governor in all other cases. */ - Type* get_component_governor(); private: const char* get_opname() const; /** Used to determine whether the reference points to value or diff --git a/compiler2/asn1/AST_asn1.cc b/compiler2/asn1/AST_asn1.cc index d286ad3..6e83b0b 100644 --- a/compiler2/asn1/AST_asn1.cc +++ b/compiler2/asn1/AST_asn1.cc @@ -513,21 +513,34 @@ namespace Asn { asss->add_ass(p_ass); } - void Module::add_types_to_json_schema(JSON_Tokenizer& json) + void Module::generate_json_schema(JSON_Tokenizer& json, map& json_refs) { // add a new property for this module - json.put_next_token(JSON_TOKEN_NAME, modid->get_dispname().c_str()); + json.put_next_token(JSON_TOKEN_NAME, modid->get_ttcnname().c_str()); // add type definitions into an object json.put_next_token(JSON_TOKEN_OBJECT_START); - // pass the JSON tokenizer onto each type definition + // cycle through all type assignments, insert schema segments and references + // when needed for (size_t i = 0; i < asss->get_nof_asss(); ++i) { Common::Assignment* ass = asss->get_ass_byIndex(i); if (Common::Assignment::A_TYPE == ass->get_asstype()) { - Type* t = ass->get_Type(); - if (t->has_encoding(Type::CT_JSON)) { - t->generate_json_schema(json, false, false); + Asn::Assignment* asn_ass = dynamic_cast(ass); + // skip parameterized types and their instances + if (NULL == asn_ass || NULL == asn_ass->get_ass_pard()) { + Type* t = ass->get_Type(); + if (!t->is_pard_type_instance() && t->has_encoding(Type::CT_JSON)) { + // insert type's schema segment + t->generate_json_schema(json, false, false); + + if (json_refs_for_all_types && !json_refs.has_key(t)) { + // create JSON schema reference for the type + JSON_Tokenizer* json_ref = new JSON_Tokenizer; + json_refs.add(t, json_ref); + t->generate_json_schema_ref(*json_ref); + } + } } } } @@ -1193,6 +1206,14 @@ namespace Asn { classify_ass(refch); return asstype != A_ERROR ? ass->is_asstype(p_asstype, refch) : false; } + + Ass_pard* Ass_Undef::get_ass_pard() const + { + if (NULL != ass) { + return ass->get_ass_pard(); + } + return ass_pard; + } bool Ass_Undef::_error_if_pard() { diff --git a/compiler2/asn1/AST_asn1.hh b/compiler2/asn1/AST_asn1.hh index 180d0d1..43eba03 100644 --- a/compiler2/asn1/AST_asn1.hh +++ b/compiler2/asn1/AST_asn1.hh @@ -129,7 +129,7 @@ namespace Asn { virtual void set_right_scope(Scope *p_scope) =0; void set_dontgen() {dontgen=true;} /** Returns 0 if assignment is not parameterized! */ - Ass_pard* get_ass_pard() const { return ass_pard; } + virtual Ass_pard* get_ass_pard() const { return ass_pard; } /** Returns 0 if this assignment is not parameterized! */ Assignment* new_instance(Common::Module *p_mod); virtual Type* get_Type(); @@ -244,12 +244,13 @@ namespace Asn { void add_ass(Assignment *p_ass); TagDefault::tagdef_t get_tagdef() const { return tagdef; } - /** Generates JSON schema segments for the types defined in the module - * and adds them to the JSON schema parameter. */ - virtual void add_types_to_json_schema(JSON_Tokenizer&); - - /** Does nothing. ASN.1 modules can't contain functions. */ - virtual void add_func_to_json_schema(map&) {} + /** Generates JSON schema segments for the types defined in the modules, + * and references to these types. + * + * @param json JSON document containing the main schema, schema segments for + * the types will be inserted here + * @param json_refs map of JSON documents containing the references to each type */ + virtual void generate_json_schema(JSON_Tokenizer& json, map& json_refs); }; /** @@ -442,6 +443,7 @@ namespace Asn { virtual void set_my_scope(Scope *p_scope); virtual void set_right_scope(Scope *p_scope); virtual bool is_asstype(asstype_t p_asstype, ReferenceChain* refch=0); + virtual Ass_pard* get_ass_pard() const; virtual Setting* get_Setting(); virtual Type* get_Type(); virtual Value* get_Value(); diff --git a/compiler2/asn1/Ref.cc b/compiler2/asn1/Ref.cc index b933ea1..0c7b52f 100644 --- a/compiler2/asn1/Ref.cc +++ b/compiler2/asn1/Ref.cc @@ -190,7 +190,11 @@ namespace Asn { new_ass->set_location(*this); new_ass->set_dontgen(); new_ass->chk(); - + + if (Common::Assignment::A_TYPE == new_ass->get_asstype()) { + new_ass->get_Type()->set_pard_type_instance(); + } + ref_ds=new Ref_defd_simple(new Identifier(my_mod->get_modid()), new Identifier(new_ass_id)); ref_ds->set_fullname(get_fullname()); diff --git a/compiler2/compiler.1 b/compiler2/compiler.1 index 762b4f0..a3416e4 100644 --- a/compiler2/compiler.1 +++ b/compiler2/compiler.1 @@ -26,8 +26,20 @@ or .br .B compiler .B \-v +.br +or +.br +.B compiler \-\-ttcn2json +.RB "[\| " \-jf " \|]" +.RB "[\| " \-T " \|]" +module.ttcn ... +.RB "[\| " \-A " \|]" +module.asn ... +.RB "[\| " \- +schema.json +.RB " \|]" .SH DESCRIPTION -This manual page is a quick reference for the TTCN-3 and ASN.1 to C++ +This manual page is a quick reference for the TTCN-3 and ASN.1 to C++ (or JSON schema) compiler of the TTCN-3 Test Executor. It only summarizes the meaning of all command line options. For more details please consult the .B Programmer's Technical Reference for TITAN TTCN-3 Test Executor. @@ -298,6 +310,29 @@ in the list before the dash. If the single dash is not present in the command line the compiler will generate code for .I all modules. +.TP +.B \-\-ttcn2json +Generates a JSON schema from the types defined in the specified TTCN-3 and ASN.1 modules. +Must always be the first compiler option. From the previously listed options only +.B \-T +and +.B \-A +can be used, instead the JSON schema generator has options of its own: +.TP +.B \-j +Only types that have JSON coding enabled are included in the schema. +.TP +.B \-f +The schema only validates types that have a JSON encoding or decoding method declared. +.TP +.BI \- " file" +The single dash character as command line argument specifies the name of the generated +JSON schema file. If it is not present, then the schema file name is generated from +the name of the first input file (by replacing its suffix with +.I \.json +or appending +.I \.json +to the end of the file). .SH EXIT STATUS The compiler exits with a status of zero when no errors were encountered during its operation. A status of one will be returned if syntax or diff --git a/compiler2/encdec.c b/compiler2/encdec.c index 2dc6e66..4d5362d 100644 --- a/compiler2/encdec.c +++ b/compiler2/encdec.c @@ -50,8 +50,10 @@ void def_encdec(const char *p_classname, #ifndef NDEBUG "// written by %s in " __FILE__ " at %d\n" #endif - "int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int) const;\n" - "int XER_decode(const XERdescriptor_t&, XmlReaderWrap&, unsigned int);\n" + "int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int, " + "embed_values_enc_struct_t*) const;\n" + "int XER_decode(const XERdescriptor_t&, XmlReaderWrap&, unsigned int, " + "embed_values_dec_struct_t*);\n" "static boolean can_start(const char *name, const char *uri, " "XERdescriptor_t const& xd, unsigned int);\n" "%s" @@ -114,7 +116,7 @@ void def_encdec(const char *p_classname, /* Do not use %s_xer_ here. It supplies the XER descriptor of oldtype * even if encoding newtype for: * type newtype oldtype; */ - " XER_encode(*(p_td.xer),p_buf, XER_coding, 0);\n" + " XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0);\n" " p_buf.put_c('\\n');\n" /* make sure it has a newline */ " break;}\n" " case TTCN_EncDec::CT_JSON: {\n" @@ -215,7 +217,7 @@ void def_encdec(const char *p_classname, " for (int rd_ok=reader.Read(); rd_ok==1; rd_ok=reader.Read()) {\n" " if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break;\n" " }\n" - " XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL);\n" + " XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, 0);\n" " size_t bytes = reader.ByteConsumed();\n" " p_buf.set_pos(bytes);\n" " break;}\n" diff --git a/compiler2/enum.c b/compiler2/enum.c index 67133e2..15ad0b5 100644 --- a/compiler2/enum.c +++ b/compiler2/enum.c @@ -605,7 +605,7 @@ void defEnumClass(const enum_def *edef, output_struct *output) src = mputprintf(src, "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf," - " unsigned int p_flavor, int p_indent) const\n" + " unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n" "{\n" " int encoded_length=(int)p_buf.get_len();\n" " const boolean e_xer = is_exer(p_flavor);\n" @@ -643,7 +643,7 @@ void defEnumClass(const enum_def *edef, output_struct *output) "// written by %s in " __FILE__ " at %d\n" #endif "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader," - " unsigned int p_flavor)\n" + " unsigned int p_flavor, embed_values_dec_struct_t*)\n" "{\n" " int rd_ok = 1, type;\n" diff --git a/compiler2/main.cc b/compiler2/main.cc index 9f50d8e..fd58f1a 100644 --- a/compiler2/main.cc +++ b/compiler2/main.cc @@ -66,7 +66,9 @@ boolean generate_skeleton = FALSE, force_overwrite = FALSE, semantic_check_only = FALSE, output_only_linenum = FALSE, default_as_optional = FALSE, enable_set_bound_out_param = FALSE, use_runtime_2 = FALSE, gcc_compat = FALSE, asn1_xer = FALSE, - check_subtype = TRUE, suppress_context = FALSE, display_up_to_date = FALSE; + check_subtype = TRUE, suppress_context = FALSE, display_up_to_date = FALSE, + implicit_json_encoding = FALSE, json_refs_for_all_types = TRUE, + profiler_enabled = FALSE; // Default code splitting mode is set to 'no splitting'. CodeGenHelper::split_type code_splitting_mode = CodeGenHelper::SPLIT_NONE; @@ -356,7 +358,7 @@ static void usage() " [-U none|type] [-P modulename.top_level_pdu_name] [-Q number] ...\n" " [-T] module.ttcn [-A] module.asn ...\n" " or %s -v\n" - " or %s --ttcn2json [-T] module.ttcn [-A] module.asn ... - schema.json\n" + " or %s --ttcn2json [-jf] ... [-T] module.ttcn [-A] module.asn ... [- schema.json]\n" "\n" "OPTIONS:\n" " -a: force XER in ASN.1 files\n" @@ -366,10 +368,13 @@ static void usage() " -f: force overwriting of output files\n" " -g: emulate GCC error/warning message format\n" " -i: use only line numbers in error/warning messages\n" + " -j: disable JSON encoder/decoder functions\n" " -l: include source line info in C++ code\n" " -L: add source line info for logging\n" " -K file: enable selective code coverage\n" + " -o dir: output files will be placed into dir\n" " -p: parse only (no semantic check or code generation)\n" + " -P pduname: define top-level pdu\n" " -q: suppress all messages (quiet mode)\n" " -Qn: quit after n errors\n" " -r: disable RAW encoder/decoder functions\n" @@ -379,19 +384,20 @@ static void usage() " -t: generate Test Port skeleton\n" " -u: duplicate underscores in file names\n" " -U none|type: select code splitting mode for the generated C++ code\n" + " -V verb_level: set verbosity level bitmask (decimal)\n" " -w: suppress warnings\n" " -x: disable TEXT encoder/decoder functions\n" " -X: disable XER encoder/decoder functions\n" - " -j: disable JSON encoder/decoder functions\n" " -y: disable subtype checking\n" - " -V verb_level: set verbosity level bitmask (decimal)\n" - " -o dir: output files will be placed into dir\n" " -Y: Enforces legacy behaviour of the \"out\" function parameters (see refguide)\n" - " -P pduname: define top-level pdu\n" + //" -z: enable profiling and code coverage for TTCN-3 files\n" - not open to the public yet " -T file: force interpretation of file as TTCN-3 module\n" " -A file: force interpretation of file as ASN.1 module\n" " -v: show version\n" - " --ttcn2json: generate JSON schema from input modules\n", argv0, argv0, argv0); + " --ttcn2json: generate JSON schema from input modules\n" + "JSON schema generator options:\n" + " -j: only include types with JSON encoding\n" + " -f: only generate references to types with JSON encoding/decoding functions\n", argv0, argv0, argv0); } #define SET_FLAG(x) if (x##flag) {\ @@ -441,7 +447,7 @@ int main(int argc, char *argv[]) tflag = false, uflag = false, vflag = false, wflag = false, xflag = false, dflag = false, Xflag = false, Rflag = false, gflag = false, aflag = false, s0flag = false, Cflag = false, yflag = false, Uflag = false, Qflag = false, - Sflag = false, Kflag = false, jflag = false, + Sflag = false, Kflag = false, jflag = false, zflag = false, errflag = false, print_usage = false, ttcn2json = false; CodeGenHelper cgh; @@ -457,6 +463,7 @@ int main(int argc, char *argv[]) if (0 == strcmp(argv[1], "--ttcn2json")) { ttcn2json = true; display_up_to_date = TRUE; + implicit_json_encoding = TRUE; for (int i = 2; i < argc; ++i) { // A dash (-) is used to separate the schema file name from the input files if (0 == strcmp(argv[i], "-")) { @@ -487,6 +494,16 @@ int main(int argc, char *argv[]) } add_module(n_modules, module_list, argv[i], Module::MOD_TTCN); } + else if (0 == strcmp(argv[i], "-j")) { + implicit_json_encoding = FALSE; + } + else if (0 == strcmp(argv[i], "-f")) { + json_refs_for_all_types = FALSE; + } + else if (0 == strcmp(argv[i], "-fj") || 0 == strcmp(argv[i], "-jf")) { + implicit_json_encoding = FALSE; + json_refs_for_all_types = FALSE; + } else if (argv[i][0] == '-') { ERROR("Invalid option `%s' after option `--ttcn2json'", argv[i]); print_usage = true; @@ -523,7 +540,7 @@ int main(int argc, char *argv[]) if (!ttcn2json) { for ( ; ; ) { - int c = getopt(argc, argv, "aA:C:K:LP:T:V:bcdfgilo:YpqQ:rRs0StuU:vwxXjy-"); + int c = getopt(argc, argv, "aA:C:K:LP:T:V:bcdfgilo:YpqQ:rRs0StuU:vwxXjyz-"); if (c == -1) break; switch (c) { case 'a': @@ -678,6 +695,10 @@ int main(int argc, char *argv[]) SET_FLAG(y); check_subtype = FALSE; break; + case 'z': + SET_FLAG(z); + profiler_enabled = TRUE; + break; case 'Q': { long max_errs; @@ -704,7 +725,7 @@ int main(int argc, char *argv[]) case '-': if (!strcmp(argv[optind], "--ttcn2json")) { - ERROR("Option `--ttcn2json' does not allow the use of other options"); + ERROR("Option `--ttcn2json' is only allowed as the first option"); } else { ERROR("Invalid option: `%s'", argv[optind]); } @@ -722,7 +743,7 @@ int main(int argc, char *argv[]) if (Aflag || Lflag || Pflag || Tflag || Vflag || Yflag || bflag || fflag || iflag || lflag || oflag || pflag || qflag || rflag || sflag || tflag || uflag || wflag || xflag || Xflag || Rflag || - Uflag || yflag || Kflag || jflag) { + Uflag || yflag || Kflag || jflag || zflag) { errflag = true; print_usage = true; } @@ -738,6 +759,10 @@ int main(int argc, char *argv[]) ERROR("Source line information `-L' is necessary for code coverage `-K'."); errflag = true; } + if (zflag && !Lflag) { + ERROR("Source line information `-L' is necessary for profiling `-z'."); + errflag = true; + } if (iflag && gflag) { WARNING("Option `-g' overrides `-i'."); iflag = false; // -g gives more information diff --git a/compiler2/main.hh b/compiler2/main.hh index 0beb371..18ec896 100644 --- a/compiler2/main.hh +++ b/compiler2/main.hh @@ -33,7 +33,8 @@ extern unsigned int nof_notupdated_files; extern boolean generate_skeleton, force_overwrite, include_line_info, include_location_info, duplicate_underscores, parse_only, semantic_check_only, output_only_linenum, default_as_optional, use_runtime_2, gcc_compat, asn1_xer, - check_subtype, suppress_context, enable_set_bound_out_param, display_up_to_date; + check_subtype, suppress_context, enable_set_bound_out_param, display_up_to_date, + implicit_json_encoding, json_refs_for_all_types, profiler_enabled; extern const char *expected_platform; diff --git a/compiler2/makefile.c b/compiler2/makefile.c index 746d126..4252d22 100644 --- a/compiler2/makefile.c +++ b/compiler2/makefile.c @@ -13,7 +13,7 @@ #include #include #if defined SOLARIS || defined SOLARIS8 -# include +#include #endif #include "../common/memory.h" @@ -32,7 +32,8 @@ static const char *program_name = NULL; static unsigned int error_count = 0; static boolean suppress_warnings = FALSE; - +void free_string2_list(struct string2_list* act_elem); +void free_string_list(struct string_list* act_elem); void ERROR(const char *fmt, ...) { va_list parameters; @@ -163,6 +164,7 @@ struct base_dir_struct { /** data structure that describes the information needed for the Makefile */ struct makefile_struct { + char *project_name; size_t nTTCN3Modules; struct module_struct *TTCN3Modules; @@ -206,11 +208,15 @@ struct makefile_struct { boolean coverage; char *tcov_file_name; boolean library; + boolean linkingStrategy; + boolean hierarchical; struct string_list* sub_project_dirs; /* not owned */ struct string_list* ttcn3_prep_includes; /* not owned */ struct string_list* ttcn3_prep_defines; /* not owned */ + struct string_list* ttcn3_prep_undefines; /* not owned */ struct string_list* prep_includes; /* not owned */ struct string_list* prep_defines; /* not owned */ + struct string_list* prep_undefines; /* not owned */ boolean codesplittpd; boolean quietly; boolean disablesubtypecheck; @@ -246,6 +252,7 @@ struct makefile_struct { /** Initializes structure \a makefile with empty lists and default settings. */ static void init_makefile_struct(struct makefile_struct *makefile) { + makefile->project_name = NULL; makefile->nTTCN3Modules = 0; makefile->TTCN3Modules = NULL; makefile->preprocess = FALSE; @@ -283,6 +290,8 @@ static void init_makefile_struct(struct makefile_struct *makefile) makefile->coverage = FALSE; makefile->tcov_file_name = NULL; makefile->library = FALSE; + makefile->linkingStrategy = FALSE; + makefile->hierarchical = FALSE; makefile->sub_project_dirs = NULL; makefile->ttcn3_prep_includes = NULL; makefile->prep_includes = NULL; @@ -303,6 +312,7 @@ static void init_makefile_struct(struct makefile_struct *makefile) /** Deallocates all memory associated with structure \a makefile. */ static void free_makefile_struct(const struct makefile_struct *makefile) { + Free(makefile->project_name); size_t i; for (i = 0; i < makefile->nTTCN3Modules; i++) { Free(makefile->TTCN3Modules[i].dir_name); @@ -348,6 +358,7 @@ static void dump_makefile_struct(const struct makefile_struct *makefile, { size_t i; DEBUG(level, "Data used for Makefile generation:"); + DEBUG(level + 1, "TTCN-3 project name: %s", makefile->project_name); DEBUG(level + 1, "TTCN-3 modules: (%u pcs.)", makefile->nTTCN3Modules); for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; @@ -406,12 +417,12 @@ static void dump_makefile_struct(const struct makefile_struct *makefile, if (user->header_name != NULL) { DEBUG(level + 3, "Header file: %s", user->header_name); DEBUG(level + 3, "Header file has .hh or .hpp suffix: %s", - user->has_hh_suffix ? "yes" : "no"); + user->has_hh_suffix ? "yes" : "no"); } if (user->source_name != NULL) { DEBUG(level + 3, "Source file: %s", user->source_name); DEBUG(level + 3, "Source file has .cc or .cpp suffix: %s", - user->has_cc_suffix ? "yes" : "no"); + user->has_cc_suffix ? "yes" : "no"); DEBUG(level + 3, "Object file: %s.o", user->file_prefix); } } @@ -437,7 +448,7 @@ static void dump_makefile_struct(const struct makefile_struct *makefile, const struct base_dir_struct *base_dir = makefile->BaseDirs + i; DEBUG(level + 2, "Directory: %s", base_dir->dir_name); DEBUG(level + 3, "Has TTCN-3/ASN.1 modules: %s", - base_dir->has_modules ? "yes" : "no"); + base_dir->has_modules ? "yes" : "no"); } } DEBUG(level + 1, "Working directory: %s", @@ -914,7 +925,7 @@ static void add_path_to_list(size_t *list_size, char ***list_ptr, for (i = 0; i < *list_size; i++) { if (!strcmp(canonized_path_name, (*list_ptr)[i])) { if (report_warning) WARNING("File `%s' was given more than once for the " - "Makefile.", path_name); + "Makefile.", path_name); Free(canonized_path_name); return; } @@ -934,28 +945,32 @@ static void add_user_file(struct makefile_struct *makefile, const char *suffix = get_suffix(path_name); if (suffix != NULL) { if (!strcmp(suffix, "ttcn") || !strcmp(suffix, "ttcn3") || - !strcmp(suffix, "3mp") || !strcmp(suffix, "ttcnpp")) { + !strcmp(suffix, "3mp") || !strcmp(suffix, "ttcnpp")) { /* The file content was already checked. Since it doesn't look like * a valid TTCN-3 file, these suffixes are suspect */ WARNING("File `%s' does not contain a valid TTCN-3 module. " - "It will be added to the Makefile as other file.", path_name); - } else if (!strcmp(suffix, "ttcnin")) { + "It will be added to the Makefile as other file.", path_name); + } + else if (!strcmp(suffix, "ttcnin")) { /* this is a TTCN-3 include file */ if (makefile->preprocess) { - add_path_to_list(&makefile->nTTCN3IncludeFiles, - &makefile->TTCN3IncludeFiles, path_name, makefile->working_dir, TRUE); - return; - } else { - WARNING("The suffix of file `%s' indicates that it is a TTCN-3 " - "include file, but TTCN-3 preprocessing is not enabled. The file " - "will be added to the Makefile as other file.", path_name); + add_path_to_list(&makefile->nTTCN3IncludeFiles, + &makefile->TTCN3IncludeFiles, path_name, makefile->working_dir, TRUE); + return; + } + else { + WARNING("The suffix of file `%s' indicates that it is a TTCN-3 " + "include file, but TTCN-3 preprocessing is not enabled. The file " + "will be added to the Makefile as other file.", path_name); } - } else if (!strcmp(suffix, "asn") || !strcmp(suffix, "asn1")) { + } + else if (!strcmp(suffix, "asn") || !strcmp(suffix, "asn1")) { /* The file content was already checked. Since it doesn't look like * a valid ASN.1 file, these suffixes are suspect */ WARNING("File `%s' does not contain a valid ASN.1 module. " - "It will be added to the Makefile as other file.", path_name); - } else if (!strcmp(suffix, "cc") || !strcmp(suffix, "c") || !strcmp(suffix, "cpp")) { + "It will be added to the Makefile as other file.", path_name); + } + else if (!strcmp(suffix, "cc") || !strcmp(suffix, "c") || !strcmp(suffix, "cpp")) { /* this is a source file */ char *dir_name = get_dir_name(path_name, makefile->working_dir); char *file_name = get_file_from_path(path_name); @@ -963,48 +978,49 @@ static void add_user_file(struct makefile_struct *makefile, struct user_struct *user; size_t i; for (i = 0; i < makefile->nUserFiles; i++) { - user = makefile->UserFiles + i; - if (!strcmp(file_prefix, user->file_prefix)) { - if (user->source_name != NULL) { - /* the source file is already present */ - if (is_same_file(dir_name, file_name, - user->dir_name, user->source_name)) { - WARNING("File `%s' was given more than once for the Makefile.", - path_name); - } else { - char *path_name1 = compose_path_name(user->dir_name, - user->source_name); - char *path_name2 = compose_path_name(dir_name, file_name); - ERROR("C/C++ source files `%s' and `%s' cannot be used together " - "in the same Makefile.", path_name1, path_name2); - Free(path_name1); - Free(path_name2); - } - } else { - /* a header file with the same prefix is already present */ - if (is_same_directory(dir_name, user->dir_name)) { - user->source_name = file_name; - file_name = NULL; - if (!strcmp(suffix, "cc") || !strcmp(suffix, "cpp")) user->has_cc_suffix = TRUE; - } else { - char *path_name1 = compose_path_name(dir_name, file_name); - char *path_name2 = compose_path_name(user->dir_name, - user->header_name); - ERROR("C/C++ source file `%s' cannot be used together with " - "header file `%s' in the same Makefile.", path_name1, - path_name2); - Free(path_name1); - Free(path_name2); - } - } - Free(dir_name); - Free(file_name); - Free(file_prefix); - return; - } + user = makefile->UserFiles + i; + if (!strcmp(file_prefix, user->file_prefix)) { + if (user->source_name != NULL) { + /* the source file is already present */ + if (is_same_file(dir_name, file_name, + user->dir_name, user->source_name)) { + WARNING("File `%s' was given more than once for the Makefile.", path_name); + } + else { + char *path_name1 = compose_path_name(user->dir_name, user->source_name); + char *path_name2 = compose_path_name(dir_name, file_name); + ERROR("C/C++ source files `%s' and `%s' cannot be used together " + "in the same Makefile.", path_name1, path_name2); + Free(path_name1); + Free(path_name2); + } + } + else { + /* a header file with the same prefix is already present */ + if (is_same_directory(dir_name, user->dir_name)) { + user->source_name = file_name; + file_name = NULL; + if (!strcmp(suffix, "cc") || !strcmp(suffix, "cpp")) + user->has_cc_suffix = TRUE; + } + else { + char *path_name1 = compose_path_name(dir_name, file_name); + char *path_name2 = compose_path_name(user->dir_name, user->header_name); + ERROR("C/C++ source file `%s' cannot be used together with " + "header file `%s' in the same Makefile.", path_name1, + path_name2); + Free(path_name1); + Free(path_name2); + } + } + Free(dir_name); + Free(file_name); + Free(file_prefix); + return; + } } makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles, - (makefile->nUserFiles + 1) * sizeof(*makefile->UserFiles)); + (makefile->nUserFiles + 1) * sizeof(*makefile->UserFiles)); user = makefile->UserFiles + makefile->nUserFiles; makefile->nUserFiles++; user->dir_name = dir_name; @@ -1015,7 +1031,8 @@ static void add_user_file(struct makefile_struct *makefile, if (!strcmp(suffix, "cc") || !strcmp(suffix, "cpp")) user->has_cc_suffix = TRUE; else user->has_cc_suffix = FALSE; return; - } else if (!strcmp(suffix, "hh") || !strcmp(suffix, "h")) { + } + else if (!strcmp(suffix, "hh") || !strcmp(suffix, "h")) { /* this is a header file */ char *dir_name = get_dir_name(path_name, makefile->working_dir); char *file_name = get_file_from_path(path_name); @@ -1023,48 +1040,47 @@ static void add_user_file(struct makefile_struct *makefile, struct user_struct *user; size_t i; for (i = 0; i < makefile->nUserFiles; i++) { - user = makefile->UserFiles + i; - if (!strcmp(file_prefix, user->file_prefix)) { - if (user->header_name != NULL) { - /* the header file is already present */ - if (is_same_file(dir_name, file_name, - user->dir_name, user->header_name)) { - WARNING("File `%s' was given more than once for the Makefile.", - path_name); - } else { - char *path_name1 = compose_path_name(user->dir_name, - user->header_name); - char *path_name2 = compose_path_name(dir_name, file_name); - ERROR("C/C++ header files `%s' and `%s' cannot be used together " - "in the same Makefile.", path_name1, path_name2); - Free(path_name1); - Free(path_name2); - } - } else { - /* a source file with the same prefix is already present */ - if (is_same_directory(dir_name, user->dir_name)) { - user->header_name = file_name; - file_name = NULL; - if (!strcmp(suffix, "hh") || !strcmp(suffix, "hpp")) user->has_hh_suffix = TRUE; - } else { - char *path_name1 = compose_path_name(dir_name, file_name); - char *path_name2 = compose_path_name(user->dir_name, - user->source_name); - ERROR("C/C++ header file `%s' cannot be used together with " - "source file `%s' in the same Makefile.", path_name1, - path_name2); - Free(path_name1); - Free(path_name2); - } - } - Free(dir_name); - Free(file_name); - Free(file_prefix); - return; - } + user = makefile->UserFiles + i; + if (!strcmp(file_prefix, user->file_prefix)) { + if (user->header_name != NULL) { + /* the header file is already present */ + if (is_same_file(dir_name, file_name, user->dir_name, user->header_name)) { + WARNING("File `%s' was given more than once for the Makefile.", path_name); + } + else { + char *path_name1 = compose_path_name(user->dir_name, user->header_name); + char *path_name2 = compose_path_name(dir_name, file_name); + ERROR("C/C++ header files `%s' and `%s' cannot be used together " + "in the same Makefile.", path_name1, path_name2); + Free(path_name1); + Free(path_name2); + } + } + else { + /* a source file with the same prefix is already present */ + if (is_same_directory(dir_name, user->dir_name)) { + user->header_name = file_name; + file_name = NULL; + if (!strcmp(suffix, "hh") || !strcmp(suffix, "hpp")) + user->has_hh_suffix = TRUE; + } + else { + char *path_name1 = compose_path_name(dir_name, file_name); + char *path_name2 = compose_path_name(user->dir_name, user->source_name); + ERROR("C/C++ header file `%s' cannot be used together with " + "source file `%s' in the same Makefile.", path_name1, path_name2); + Free(path_name1); + Free(path_name2); + } + } + Free(dir_name); + Free(file_name); + Free(file_prefix); + return; + } } makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles, - (makefile->nUserFiles + 1) * sizeof(*makefile->UserFiles)); + (makefile->nUserFiles + 1) * sizeof(*makefile->UserFiles)); user = makefile->UserFiles + makefile->nUserFiles; makefile->nUserFiles++; user->dir_name = dir_name; @@ -1176,31 +1192,34 @@ static void complete_user_files(const struct makefile_struct *makefile) static const char * const suffix_list[] = { "hh", "h", "hpp", NULL }; const char * const *suffix_ptr; for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) { - char *file_name = mprintf("%s.%s", user->file_prefix, *suffix_ptr); - char *path_name = compose_path_name(user->dir_name, file_name); - if (get_path_status(path_name) == PS_FILE) { - Free(path_name); - user->header_name = file_name; - if (!strcmp(*suffix_ptr, "hh") || !strcmp(*suffix_ptr, "hpp")) user->has_hh_suffix = TRUE; - break; - } - Free(file_name); - Free(path_name); + char *file_name = mprintf("%s.%s", user->file_prefix, *suffix_ptr); + char *path_name = compose_path_name(user->dir_name, file_name); + if (get_path_status(path_name) == PS_FILE) { + Free(path_name); + user->header_name = file_name; + if (!strcmp(*suffix_ptr, "hh") || !strcmp(*suffix_ptr, "hpp")) + user->has_hh_suffix = TRUE; + break; + } + Free(file_name); + Free(path_name); } - } else if (user->source_name == NULL) { + } + else if (user->source_name == NULL) { static const char * const suffix_list[] = { "cc", "c", "cpp", NULL }; const char * const *suffix_ptr; for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) { - char *file_name = mprintf("%s.%s", user->file_prefix, *suffix_ptr); - char *path_name = compose_path_name(user->dir_name, file_name); - if (get_path_status(path_name) == PS_FILE) { - Free(path_name); - user->source_name = file_name; - if (!strcmp(*suffix_ptr, "cc") || !strcmp(*suffix_ptr, "cpp")) user->has_cc_suffix = TRUE; - break; - } - Free(file_name); - Free(path_name); + char *file_name = mprintf("%s.%s", user->file_prefix, *suffix_ptr); + char *path_name = compose_path_name(user->dir_name, file_name); + if (get_path_status(path_name) == PS_FILE) { + Free(path_name); + user->source_name = file_name; + if (!strcmp(*suffix_ptr, "cc") || !strcmp(*suffix_ptr, "cpp")) + user->has_cc_suffix = TRUE; + break; + } + Free(file_name); + Free(path_name); } } } @@ -1434,16 +1453,17 @@ static void check_naming_convention(struct makefile_struct *makefile) for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name != NULL) { - if (!module->is_regular) makefile->BaseTTCN3ModulesRegular = FALSE; - } else { - if (!module->is_regular) makefile->TTCN3ModulesRegular = FALSE; + if (!module->is_regular) makefile->BaseTTCN3ModulesRegular = FALSE; + } + else { + if (!module->is_regular) makefile->TTCN3ModulesRegular = FALSE; } if (!makefile->TTCN3ModulesRegular && !makefile->BaseTTCN3ModulesRegular) - break; + break; } /* ttcnpp files are ttcn files */ if ((makefile->TTCN3ModulesRegular || makefile->BaseTTCN3ModulesRegular) && - makefile->preprocess) { + makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL) { @@ -1458,29 +1478,31 @@ static void check_naming_convention(struct makefile_struct *makefile) for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name != NULL) { - if (!module->is_regular) makefile->BaseASN1ModulesRegular = FALSE; - } else { - if (!module->is_regular) makefile->ASN1ModulesRegular = FALSE; + if (!module->is_regular) makefile->BaseASN1ModulesRegular = FALSE; + } + else { + if (!module->is_regular) makefile->ASN1ModulesRegular = FALSE; } if (!makefile->ASN1ModulesRegular && !makefile->BaseASN1ModulesRegular) - break; + break; } for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL) { - if (!user->has_cc_suffix) - makefile->BaseUserSourcesRegular = FALSE; - if (!user->has_cc_suffix || !user->has_hh_suffix) - makefile->BaseUserHeadersRegular = FALSE; - } else { - if (!user->has_cc_suffix) - makefile->UserSourcesRegular = FALSE; - if (!user->has_cc_suffix || !user->has_hh_suffix) - makefile->UserHeadersRegular = FALSE; + if (!user->has_cc_suffix) + makefile->BaseUserSourcesRegular = FALSE; + if (!user->has_cc_suffix || !user->has_hh_suffix) + makefile->BaseUserHeadersRegular = FALSE; + } + else { + if (!user->has_cc_suffix) + makefile->UserSourcesRegular = FALSE; + if (!user->has_cc_suffix || !user->has_hh_suffix) + makefile->UserHeadersRegular = FALSE; } if (!makefile->UserHeadersRegular && !makefile->UserSourcesRegular && - !makefile->BaseUserHeadersRegular && - !makefile->BaseUserSourcesRegular) break; + !makefile->BaseUserHeadersRegular && + !makefile->BaseUserSourcesRegular) break; } } else { /* this project (Makefile) will-be stand-alone */ @@ -1488,8 +1510,8 @@ static void check_naming_convention(struct makefile_struct *makefile) for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (!module->is_regular || module->dir_name != NULL) { - makefile->TTCN3ModulesRegular = FALSE; - break; + makefile->TTCN3ModulesRegular = FALSE; + break; } } if (makefile->TTCN3ModulesRegular && makefile->preprocess) { @@ -1504,18 +1526,18 @@ static void check_naming_convention(struct makefile_struct *makefile) for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (!module->is_regular || module->dir_name != NULL) { - makefile->ASN1ModulesRegular = FALSE; - break; + makefile->ASN1ModulesRegular = FALSE; + break; } } for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (!user->has_cc_suffix) - makefile->UserSourcesRegular = FALSE; + makefile->UserSourcesRegular = FALSE; if (!user->has_cc_suffix || !user->has_hh_suffix) - makefile->UserHeadersRegular = FALSE; + makefile->UserHeadersRegular = FALSE; if (!makefile->UserHeadersRegular && !makefile->UserSourcesRegular) - break; + break; } } } @@ -1639,8 +1661,13 @@ static void fprint_extra_targets(FILE* fp, struct string2_list* target_placement /** Prints the Makefile based on structure \a makefile. */ static void print_makefile(struct makefile_struct *makefile) { - boolean add_refd_prjs = makefile->sub_project_dirs && makefile->sub_project_dirs->str; - + boolean add_refd_prjs = FALSE; + if (makefile->linkingStrategy && makefile->hierarchical) { + add_refd_prjs = hasSubProject(makefile->project_name); + } + else { + add_refd_prjs = makefile->sub_project_dirs && makefile->sub_project_dirs->str; + } NOTIFY("Generating Makefile skeleton..."); if (makefile->force_overwrite || @@ -1673,7 +1700,7 @@ static void print_makefile(struct makefile_struct *makefile) fp = fopen(makefile->output_file, "w"); if (fp == NULL){ ERROR("Cannot open output file `%s' for writing: %s", - makefile->output_file, strerror(errno)); + makefile->output_file, strerror(errno)); return; } user_info = get_user_info(); @@ -1685,15 +1712,21 @@ static void print_makefile(struct makefile_struct *makefile) "# - make, make all Builds the %s.\n" "# - make archive Archives all source files.\n" "# - make check Checks the semantics of TTCN-3 and ASN.1 " - "modules.\n" - "# - make clean Removes all generated files.\n" + "modules.\n" + "%s" // clean: + "%s" //clean-all "# - make compile Translates TTCN-3 and ASN.1 modules to C++.\n" "# - make dep Creates/updates dependency list.\n" "# - make executable Builds the executable test suite.\n" "# - make library Builds the library archive.\n" "# - make objects Builds the object files without linking the " "executable.\n", user_info, - makefile->library ? "library archive." : "executable test suite"); + makefile->library ? "library archive." : "executable test suite", + (makefile->linkingStrategy && makefile->hierarchical) ? + "# - make clean Removes generated files from project.\n" : + "# - make clean Removes all generated files.\n", + (makefile->linkingStrategy && makefile->hierarchical) ? + "# - make clean-all Removes all generated files from the project hierarchy.\n" : ""); Free(user_info); if (makefile->dynamic) fprintf(fp, "# - make shared_objects Builds the shared object files " @@ -1702,14 +1735,14 @@ static void print_makefile(struct makefile_struct *makefile) fputs("# - make preprocess Preprocess TTCN-3 files.\n", fp); if (makefile->central_storage) { fputs("# WARNING! This Makefile uses pre-compiled files from the " - "following directories:\n", fp); + "following directories:\n", fp); for (i = 0; i < makefile->nBaseDirs; i++) fprintf(fp, "# %s\n", makefile->BaseDirs[i].dir_name); fputs("# The executable tests will be consistent only if all directories " - "use\n" - "# the same platform and the same version of TTCN-3 Test Executor " - "and\n" - "# C++ compiler with the same command line switches.\n\n", fp); + "use\n" + "# the same platform and the same version of TTCN-3 Test Executor " + "and\n" + "# C++ compiler with the same command line switches.\n\n", fp); } if (makefile->gnu_make) { fputs("# WARNING! This Makefile can be used with GNU make only.\n" @@ -1720,8 +1753,10 @@ static void print_makefile(struct makefile_struct *makefile) ".PHONY: all shared_objects executable library objects check clean dep archive", fp); if (makefile->preprocess) fputs(" preprocess", fp); if (add_refd_prjs) { - fputs("\\\n referenced-all referenced-shared_objects referenced-executable referenced-library referenced-objects referenced-check" - "\\\n referenced-clean referenced-archive", fp); + fprintf(fp, "\\\n referenced-all referenced-shared_objects referenced-executable referenced-library referenced-objects referenced-check" + "\\\n referenced-clean%s", + (makefile->linkingStrategy && makefile->hierarchical) ? + "-all" : ""); } fprint_extra_targets(fp, makefile->target_placement_list, "PHONY"); @@ -1731,10 +1766,31 @@ static void print_makefile(struct makefile_struct *makefile) fputs("\n\n", fp); } + if (makefile->linkingStrategy) { + const char* tpd_name = getTPDFileName(makefile->project_name); + if (tpd_name) { + fputs("# Titan Project Descriptor file what this Makefile is generated from.\n", fp); + fprintf(fp, "TPD = %s\n\n", tpd_name); + } + const char* root_dir = getPathToRootDir(makefile->project_name); + if (root_dir) { + fputs("# Relative path to top directory at OS level.\n", fp); + fprintf(fp, "ROOT_DIR = %s\n\n", root_dir); + } + } + if (add_refd_prjs) { - struct string_list* act_elem = makefile->sub_project_dirs; - fputs("# This is the top level makefile of a Makefile hierarchy generated from\n" - "# a Titan Project Descriptor hierarchy. List of referenced project\n" + struct string_list* act_elem = NULL; + struct string_list* head = NULL; + if (makefile->linkingStrategy && makefile->hierarchical) {// pair with free_string_list + head = act_elem = getRefWorkingDirs(makefile->project_name); + } + else { + act_elem = makefile->sub_project_dirs; + } + if (!makefile->linkingStrategy) + fputs("# This is the top level makefile of a Makefile hierarchy generated from\n", fp); + fputs("# Titan Project Descriptor hierarchy. List of referenced project\n" "# working directories (ordered by dependencies):\n", fp); while (act_elem) { if (act_elem->str) { @@ -1742,8 +1798,16 @@ static void print_makefile(struct makefile_struct *makefile) } act_elem = act_elem->next; } + if (makefile->linkingStrategy && makefile->hierarchical) { // pair with getRefWorkingDirs + free_string_list(head); + } fputs("REFERENCED_PROJECT_DIRS = ", fp); - act_elem = makefile->sub_project_dirs; + if (makefile->linkingStrategy && makefile->hierarchical) { + head = act_elem = getRefWorkingDirs(makefile->project_name); // pair with free_string_list + } + else { + act_elem = makefile->sub_project_dirs; + } while (act_elem) { if (act_elem->str) { fprintf(fp, "%s ", act_elem->str); @@ -1751,6 +1815,9 @@ static void print_makefile(struct makefile_struct *makefile) act_elem = act_elem->next; } fputs("\n\n", fp); + if (makefile->linkingStrategy && makefile->hierarchical) {// pair with getRefWorkingDirs + free_string_list(head); + } } fprintf(fp, "#\n" @@ -1819,6 +1886,16 @@ static void print_makefile(struct makefile_struct *makefile) } } + if (makefile->prep_undefines) { + struct string_list* act_elem = makefile->prep_undefines; + while (act_elem) { + if (act_elem->str) { + fprintf(fp, " -U%s", act_elem->str); + } + act_elem = act_elem->next; + } + } + fputs("\n\n", fp); if (makefile->gcc_dep) { @@ -1853,6 +1930,15 @@ static void print_makefile(struct makefile_struct *makefile) act_elem = act_elem->next; } } + if (makefile->ttcn3_prep_undefines) { + struct string_list* act_elem = makefile->ttcn3_prep_undefines; + while (act_elem) { + if (act_elem->str) { + fprintf(fp, " -U%s", act_elem->str); + } + act_elem = act_elem->next; + } + } fputs("\n\n", fp); } @@ -1937,7 +2023,7 @@ static void print_makefile(struct makefile_struct *makefile) fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_MODULES"); if (makefile->preprocess) { fputs("\n\n" - "# TTCN-3 modules to preprocess:\n" + "# TTCN-3 modules to preprocess:\n" "TTCN3_PP_MODULES =", fp); for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; @@ -1948,21 +2034,58 @@ static void print_makefile(struct makefile_struct *makefile) } if (makefile->central_storage) { fputs("\n\n" - "# TTCN-3 modules used from central project(s):\n" - "BASE_TTCN3_MODULES =", fp); - for (i = 0; i < makefile->nTTCN3Modules; i++) { - const struct module_struct *module = makefile->TTCN3Modules + i; - /* Central storage used AND file is not in the current directory => - * it goes into BASE_TTCN3_MODULES */ - if (module->dir_name != NULL) print_file_name(fp, module); + "# TTCN-3 modules used from central project(s):\n" + "BASE_TTCN3_MODULES =", fp); + if (!makefile->linkingStrategy) { + for (i = 0; i < makefile->nTTCN3Modules; i++) { + const struct module_struct *module = makefile->TTCN3Modules + i; + /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */ + if (module->dir_name != NULL) print_file_name(fp, module); + } + if (makefile->preprocess) { + fputs("\n\n" + "# TTCN-3 modules to preprocess used from central project(s):\n" + "BASE_TTCN3_PP_MODULES =", fp); + for (i = 0; i < makefile->nTTCN3PPModules; i++) { + const struct module_struct *module = makefile->TTCN3PPModules + i; + if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name)) + print_file_name(fp, module); + } + } } - if (makefile->preprocess) { + else { // new linking strategy + for (i = 0; i < makefile->nTTCN3Modules; i++) { + const struct module_struct *module = makefile->TTCN3Modules + i; + /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */ + if (module->dir_name != NULL && !isTtcn3ModuleInLibrary(module->module_name)) + print_file_name(fp, module); + } fputs("\n\n" - "# TTCN-3 modules to preprocess used from central project(s):\n" - "BASE_TTCN3_PP_MODULES =", fp); - for (i = 0; i < makefile->nTTCN3PPModules; i++) { - const struct module_struct *module = makefile->TTCN3PPModules + i; - if (module->dir_name != NULL) print_file_name(fp, module); + "# TTCN-3 library linked modules used from central project(s):\n" + "BASE2_TTCN3_MODULES =", fp); + for (i = 0; i < makefile->nTTCN3Modules; i++) { + const struct module_struct *module = makefile->TTCN3Modules + i; + /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */ + if (module->dir_name != NULL && isTtcn3ModuleInLibrary(module->module_name)) + print_file_name(fp, module); + } + if (makefile->preprocess) { + fputs("\n\n" + "# TTCN-3 modules to preprocess used from central project(s):\n" + "BASE_TTCN3_PP_MODULES =", fp); + for (i = 0; i < makefile->nTTCN3PPModules; i++) { + const struct module_struct *module = makefile->TTCN3PPModules + i; + if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name)) + print_file_name(fp, module); + } + fputs("\n\n" + "# TTCN-3 library linked modules to preprocess used from central project(s):\n" + "BASE2_TTCN3_PP_MODULES =", fp); + for (i = 0; i < makefile->nTTCN3PPModules; i++) { + const struct module_struct *module = makefile->TTCN3PPModules + i; + if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name)) + print_file_name(fp, module); + } } } } @@ -1971,7 +2094,7 @@ static void print_makefile(struct makefile_struct *makefile) "# Files to include in TTCN-3 preprocessed modules:\n" "TTCN3_INCLUDES =", fp); for (i = 0; i < makefile->nTTCN3IncludeFiles; i++) - fprintf(fp, " %s", makefile->TTCN3IncludeFiles[i]); + fprintf(fp, " %s", makefile->TTCN3IncludeFiles[i]); fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_INCLUDES"); } fputs("\n\n" @@ -1980,16 +2103,33 @@ static void print_makefile(struct makefile_struct *makefile) for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name == NULL || !makefile->central_storage) - print_file_name(fp, module); + print_file_name(fp, module); } fprint_extra_targets(fp, makefile->target_placement_list, "ASN1_MODULES"); if (makefile->central_storage) { fputs("\n\n" - "# ASN.1 modules used from central project(s):\n" - "BASE_ASN1_MODULES =", fp); - for (i = 0; i < makefile->nASN1Modules; i++) { - const struct module_struct *module = makefile->ASN1Modules + i; - if (module->dir_name != NULL) print_file_name(fp, module); + "# ASN.1 modules used from central project(s):\n" + "BASE_ASN1_MODULES =", fp); + if (!makefile->linkingStrategy) { + for (i = 0; i < makefile->nASN1Modules; i++) { + const struct module_struct *module = makefile->ASN1Modules + i; + if (module->dir_name != NULL) print_file_name(fp, module); + } + } + else { + for (i = 0; i < makefile->nASN1Modules; i++) { + const struct module_struct *module = makefile->ASN1Modules + i; + if (module->dir_name != NULL && !isAsn1ModuleInLibrary(module->module_name)) + print_file_name(fp, module); + } + fputs("\n\n" + "# ASN.1 library linked modules used from central project(s):\n" + "BASE2_ASN1_MODULES =", fp); + for (i = 0; i < makefile->nASN1Modules; i++) { + const struct module_struct *module = makefile->ASN1Modules + i; + if (module->dir_name != NULL && isAsn1ModuleInLibrary(module->module_name)) + print_file_name(fp, module); + } } } if (makefile->preprocess) { @@ -1998,17 +2138,34 @@ static void print_makefile(struct makefile_struct *makefile) "PREPROCESSED_TTCN3_MODULES =", fp); for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; - if (module->dir_name == NULL || !makefile->central_storage) - print_preprocessed_file_name(fp, module); + if (module->dir_name == NULL || !makefile->central_storage) + print_preprocessed_file_name(fp, module); } if (makefile->central_storage) { fputs("\n\n" "# TTCN-3 files generated by the CPP used from central project(s):\n" "BASE_PREPROCESSED_TTCN3_MODULES =", fp); - for (i = 0; i < makefile->nTTCN3PPModules; i++) { - const struct module_struct *module = makefile->TTCN3PPModules + i; - if (module->dir_name != NULL) - print_preprocessed_file_name(fp, module); + if (!makefile->linkingStrategy) { + for (i = 0; i < makefile->nTTCN3PPModules; i++) { + const struct module_struct *module = makefile->TTCN3PPModules + i; + if (module->dir_name != NULL) + print_preprocessed_file_name(fp, module); + } + } + else { // new linking strategy + for (i = 0; i < makefile->nTTCN3PPModules; i++) { + const struct module_struct *module = makefile->TTCN3PPModules + i; + if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name)) + print_preprocessed_file_name(fp, module); + } + fputs("\n\n" + "# TTCN-3 library linked files generated by the CPP used from central project(s):\n" + "BASE2_PREPROCESSED_TTCN3_MODULES =", fp); + for (i = 0; i < makefile->nTTCN3PPModules; i++) { + const struct module_struct *module = makefile->TTCN3PPModules + i; + if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name)) + print_preprocessed_file_name(fp, module); + } } } } @@ -2080,11 +2237,12 @@ static void print_makefile(struct makefile_struct *makefile) fputs("\nGENERATED_HEADERS =", fp); if (makefile->gnu_make) { fputs(" $(GENERATED_SOURCES:.cc=.hh)", fp); - } else { + } + else { for (i = 0; i < makefile->nTTCN3Modules; i++) { - const struct module_struct *module = makefile->TTCN3Modules + i; - if (module->dir_name == NULL || !makefile->central_storage) - print_generated_file_name(fp, module, FALSE, ".hh"); + const struct module_struct *module = makefile->TTCN3Modules + i; + if (module->dir_name == NULL || !makefile->central_storage) + print_generated_file_name(fp, module, FALSE, ".hh"); } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { @@ -2094,9 +2252,9 @@ static void print_makefile(struct makefile_struct *makefile) } } for (i = 0; i < makefile->nASN1Modules; i++) { - const struct module_struct *module = makefile->ASN1Modules + i; - if (module->dir_name == NULL || !makefile->central_storage) - print_generated_file_name(fp, module, FALSE, ".hh"); + const struct module_struct *module = makefile->ASN1Modules + i; + if (module->dir_name == NULL || !makefile->central_storage) + print_generated_file_name(fp, module, FALSE, ".hh"); } } if (makefile->central_storage) { @@ -2168,36 +2326,74 @@ static void print_makefile(struct makefile_struct *makefile) } fputs("\nBASE_GENERATED_HEADERS =", fp); if (makefile->gnu_make) { - fputs(" $(BASE_GENERATED_SOURCES:.cc=.hh)", fp); + fputs(" $(BASE_GENERATED_SOURCES:.cc=.hh)", fp); } else { - for (i = 0; i < makefile->nTTCN3Modules; i++) { - const struct module_struct *module = makefile->TTCN3Modules + i; - if (module->dir_name != NULL) - print_generated_file_name(fp, module, TRUE, ".hh"); - } - if (makefile->preprocess) { - for (i = 0; i < makefile->nTTCN3PPModules; i++) { - const struct module_struct *module = makefile->TTCN3PPModules + i; - if (module->dir_name != NULL) - print_generated_file_name(fp, module, TRUE, ".hh"); - } - } - for (i = 0; i < makefile->nASN1Modules; i++) { - const struct module_struct *module = makefile->ASN1Modules + i; - if (module->dir_name != NULL) - print_generated_file_name(fp, module, TRUE, ".hh"); - } + for (i = 0; i < makefile->nTTCN3Modules; i++) { + const struct module_struct *module = makefile->TTCN3Modules + i; + if (module->dir_name != NULL) + print_generated_file_name(fp, module, TRUE, ".hh"); + } + if (makefile->preprocess) { + for (i = 0; i < makefile->nTTCN3PPModules; i++) { + const struct module_struct *module = makefile->TTCN3PPModules + i; + if (module->dir_name != NULL) + print_generated_file_name(fp, module, TRUE, ".hh"); + } + } + for (i = 0; i < makefile->nASN1Modules; i++) { + const struct module_struct *module = makefile->ASN1Modules + i; + if (module->dir_name != NULL) + print_generated_file_name(fp, module, TRUE, ".hh"); + } + } + } + + if (makefile->linkingStrategy) { + fputs("\n\n" + "# C++ source & header files generated from the TTCN-3 " + " library linked modules of\n" + "# central project(s):\n" + "BASE2_GENERATED_SOURCES =", fp); + if (makefile->gnu_make && makefile->BaseTTCN3ModulesRegular) { + fputs(" $(BASE2_TTCN3_MODULES:.ttcn=.cc)", fp); + fputs(" $(BASE2_ASN1_MODULES:.asn=.cc)", fp); + if (makefile->preprocess) + fputs(" $(BASE2_TTCN3_PP_MODULES:.ttcnpp=.cc)", fp); + } + else { + for (i = 0; i < makefile->nTTCN3Modules; i++) { + const struct module_struct *module = makefile->TTCN3Modules + i; + if (module->dir_name != NULL && isTtcn3ModuleInLibrary(module->module_name)) { + print_generated_file_name(fp, module, TRUE, ".cc"); + } + } + if (makefile->preprocess) { + for (i = 0; i < makefile->nTTCN3PPModules; i++) { + const struct module_struct *module = makefile->TTCN3PPModules + i; + if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name)) { + print_generated_file_name(fp, module, TRUE, ".cc"); + } + } + } } + + fputs("\nBASE2_GENERATED_HEADERS =", fp); + if (makefile->gnu_make) { + fputs(" $(BASE2_GENERATED_SOURCES:.cc=.hh)", fp); + } + else + ERROR("the usage of 'Z' flag requires GNU make"); } + fputs("\n\n" "# C/C++ Source & header files of Test Ports, external functions " - "and\n" - "# other modules:\n" + "and\n" + "# other modules:\n" "USER_SOURCES =", fp); for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name == NULL || !makefile->central_storage) - print_source_name(fp, user); + print_source_name(fp, user); } fprint_extra_targets(fp, makefile->target_placement_list, "USER_SOURCES"); fputs("\nUSER_HEADERS =", fp); @@ -2205,35 +2401,80 @@ static void print_makefile(struct makefile_struct *makefile) fputs(" $(USER_SOURCES:.cc=.hh)", fp); } else { for (i = 0; i < makefile->nUserFiles; i++) { - const struct user_struct *user = makefile->UserFiles + i; - if (user->dir_name == NULL || !makefile->central_storage) - print_header_name(fp, user); + const struct user_struct *user = makefile->UserFiles + i; + if (user->dir_name == NULL || !makefile->central_storage) + print_header_name(fp, user); } } fprint_extra_targets(fp, makefile->target_placement_list, "USER_HEADERS"); if (makefile->central_storage) { fputs("\n\n" "# C/C++ Source & header files of Test Ports, external functions " - "and\n" - "# other modules used from central project(s):\n" + "and\n" + "# other modules used from central project(s):\n" "BASE_USER_SOURCES =", fp); - for (i = 0; i < makefile->nUserFiles; i++) { - const struct user_struct *user = makefile->UserFiles + i; - if (user->dir_name != NULL) - print_source_name(fp, user); + if (!makefile->linkingStrategy) { + for (i = 0; i < makefile->nUserFiles; i++) { + const struct user_struct *user = makefile->UserFiles + i; + if (user->dir_name != NULL) { + print_source_name(fp, user); + } + } + fputs("\nBASE_USER_HEADERS =", fp); + if (makefile->gnu_make && makefile->BaseUserHeadersRegular) { + fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp); + } + else { + for (i = 0; i < makefile->nUserFiles; i++) { + const struct user_struct *user = makefile->UserFiles + i; + if (user->dir_name != NULL) + print_header_name(fp, user); + } + } } - fputs("\nBASE_USER_HEADERS =", fp); - if (makefile->gnu_make && makefile->BaseUserHeadersRegular) { - fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp); - } else { - for (i = 0; i < makefile->nUserFiles; i++) { - const struct user_struct *user = makefile->UserFiles + i; - if (user->dir_name != NULL) - print_header_name(fp, user); - } + else { + for (i = 0; i < makefile->nUserFiles; i++) { + const struct user_struct *user = makefile->UserFiles + i; + if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name)) { + print_source_name(fp, user); + } + } + fputs("\nBASE_USER_HEADERS =", fp); + if (makefile->gnu_make && makefile->BaseUserHeadersRegular) { + fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp); + } + else { + for (i = 0; i < makefile->nUserFiles; i++) { + const struct user_struct *user = makefile->UserFiles + i; + if (user->dir_name != NULL && !isHeaderFileInLibrary(user->header_name)) + print_header_name(fp, user); + } + } + + fputs("\n\n" + "# C/C++ Source & header files of Test Ports, external functions " + "and\n" + "# other modules used from library linked central project(s):\n" + "BASE2_USER_SOURCES =", fp); + for (i = 0; i < makefile->nUserFiles; i++) { + const struct user_struct *user = makefile->UserFiles + i; + if (user->dir_name != NULL && isSourceFileInLibrary(user->source_name)) { + print_source_name(fp, user); + } + } + fputs("\nBASE2_USER_HEADERS =", fp); + if (makefile->gnu_make && makefile->BaseUserHeadersRegular) { + fputs(" $(BASE2_USER_SOURCES:.cc=.hh)", fp); + } + else { + for (i = 0; i < makefile->nUserFiles; i++) { + const struct user_struct *user = makefile->UserFiles + i; + if (user->dir_name != NULL && isHeaderFileInLibrary(user->header_name)) + print_header_name(fp, user); + } + } } } - if (makefile->dynamic) { fputs("\n\n" "# Shared object files of this project:\n" @@ -2299,7 +2540,7 @@ static void print_makefile(struct makefile_struct *makefile) fputs("\n\n" "# Object files of this project that are needed for the executable " - "test suite:\n" + "test suite:\n" "OBJECTS = $(GENERATED_OBJECTS) $(USER_OBJECTS)\n\n" /* never := */ "GENERATED_OBJECTS =", fp); if (makefile->gnu_make) { @@ -2376,77 +2617,170 @@ static void print_makefile(struct makefile_struct *makefile) fputs("\n\n" "# Shared object files of central project(s):\n" "BASE_SHARED_OBJECTS =", fp); + if (!makefile->linkingStrategy) { + if (makefile->gnu_make) { + fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp); + } + else { + for (i = 0; i < makefile->nTTCN3Modules; i++) { + const struct module_struct *module = makefile->TTCN3Modules + i; + if (module->dir_name != NULL) + print_generated_file_name(fp, module, TRUE, ".so"); + } + if (makefile->preprocess) { + for (i = 0; i < makefile->nTTCN3PPModules; i++) { + const struct module_struct *module = + makefile->TTCN3PPModules + i; + if (module->dir_name != NULL) + print_generated_file_name(fp, module, TRUE, ".so"); + } + } + for (i = 0; i < makefile->nASN1Modules; i++) { + const struct module_struct *module = makefile->ASN1Modules + i; + if (module->dir_name != NULL) + print_generated_file_name(fp, module, TRUE, ".so"); + } + } + if (makefile->gnu_make && makefile->BaseUserSourcesRegular) { + fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp); + } + else { + for (i = 0; i < makefile->nUserFiles; i++) { + const struct user_struct *user = makefile->UserFiles + i; + if (user->dir_name != NULL) + print_shared_object_name(fp, user); + } + } + } + else { // new linkingStrategy + if (makefile->gnu_make) { + fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp); + } + else + ERROR("the usage of 'Z' flag requires GNU make"); + + if (makefile->gnu_make && makefile->BaseUserSourcesRegular) { + fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp); + } + else { + for (i = 0; i < makefile->nUserFiles; i++) { + const struct user_struct *user = makefile->UserFiles + i; + if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name)) + print_shared_object_name(fp, user); + } + } + } + } /* if dynamic */ + fputs("\n\n" + "# Object files of central project(s) that are needed for the " + "executable test suite:\n" + "BASE_OBJECTS =", fp); + if (!makefile->linkingStrategy) { if (makefile->gnu_make) { - fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp); - } else { + fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp); + } + else { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name != NULL) - print_generated_file_name(fp, module, TRUE, ".so"); + print_generated_file_name(fp, module, TRUE, ".o"); } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { - const struct module_struct *module = - makefile->TTCN3PPModules + i; + const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL) - print_generated_file_name(fp, module, TRUE, ".so"); + print_generated_file_name(fp, module, TRUE, ".o"); } } for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name != NULL) - print_generated_file_name(fp, module, TRUE, ".so"); + print_generated_file_name(fp, module, TRUE, ".o"); } } if (makefile->gnu_make && makefile->BaseUserSourcesRegular) { - fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp); - } else { + fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp); + } + else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL) - print_shared_object_name(fp, user); + print_object_name(fp, user); } } - } /* if dynamic */ - fputs("\n\n" - "# Object files of central project(s) that are needed for the " - "executable test suite:\n" - "BASE_OBJECTS =", fp); - if (makefile->gnu_make) { - fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp); - } else { - for (i = 0; i < makefile->nTTCN3Modules; i++) { - const struct module_struct *module = makefile->TTCN3Modules + i; - if (module->dir_name != NULL) - print_generated_file_name(fp, module, TRUE, ".o"); + } + else { // new linkingStrategy + if (makefile->gnu_make) { + fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp); } - if (makefile->preprocess) { - for (i = 0; i < makefile->nTTCN3PPModules; i++) { - const struct module_struct *module = makefile->TTCN3PPModules + i; - if (module->dir_name != NULL) - print_generated_file_name(fp, module, TRUE, ".o"); - } + else + ERROR("the usage of 'Z' flag requires GNU make"); + + if (makefile->gnu_make && makefile->BaseUserSourcesRegular) { + fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp); } - for (i = 0; i < makefile->nASN1Modules; i++) { - const struct module_struct *module = makefile->ASN1Modules + i; - if (module->dir_name != NULL) - print_generated_file_name(fp, module, TRUE, ".o"); + else { + for (i = 0; i < makefile->nUserFiles; i++) { + const struct user_struct *user = makefile->UserFiles + i; + if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name)) + print_object_name(fp, user); + } } } + } + if (makefile->linkingStrategy) { + fputs("\n\n" + "# Object files of library linked central project(s) that are needed for the " + "executable test suite:\n" + "BASE2_OBJECTS =", fp); + if (makefile->gnu_make) { + if (makefile->dynamic) + fputs(" $(BASE2_GENERATED_SOURCES:.cc=.so)", fp); + else + fputs(" $(BASE2_GENERATED_SOURCES:.cc=.o)", fp); + } + else ERROR("the usage of 'Z' flag requires GNU make"); + if (makefile->gnu_make && makefile->BaseUserSourcesRegular) { - fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp); - } else { + if (makefile->dynamic) + fputs(" $(BASE2_USER_SOURCES:.cc=.so)", fp); + else + fputs(" $(BASE2_USER_SOURCES:.cc=.o)", fp); + } + else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; - if (user->dir_name != NULL) - print_object_name(fp, user); + if (user->dir_name != NULL && isSourceFileInLibrary(user->source_name)) { + if (makefile->dynamic) + print_shared_object_name(fp, user); + else + print_object_name(fp, user); + } + } + } + if (makefile->hierarchical) { + fputs("\n\n" + "#Libraries of referenced project(s) that are needed for the " + "executable or library target:\n" + "BASE2_LIBRARY =", fp); + struct string2_list* head = getLinkerLibs(makefile->project_name); + struct string2_list* act_elem = head; + while (act_elem) { + if (act_elem->str2) { + fputs(" ", fp); + fprintf(fp, "%s/lib%s.%s", act_elem->str1, act_elem->str2, + isDynamicLibrary(act_elem->str2) ? "so" : "a"); + } + act_elem = act_elem->next; } + free_string2_list(head); } } + fputs("\n\n" - "# Other files of the project (Makefile, configuration files, etc.)\n" - "# that will be added to the archived source files:\n" - "OTHER_FILES =", fp); + "# Other files of the project (Makefile, configuration files, etc.)\n" + "# that will be added to the archived source files:\n" + "OTHER_FILES =", fp); for (i = 0; i < makefile->nOtherFiles; i++) fprintf(fp, " %s", makefile->OtherFiles[i]); fprint_extra_targets(fp, makefile->target_placement_list, "OTHER_FILES"); @@ -2465,19 +2799,35 @@ static void print_makefile(struct makefile_struct *makefile) fputs(".exe", fp); } #endif - fputs("\n", fp); - + fputs("\n\n", fp); + if (makefile->linkingStrategy) { +#ifndef WIN32 + fputs("DYNAMIC_LIBRARY = lib$(EXECUTABLE).so\n", fp); + fputs("STATIC_LIBRARY = lib$(EXECUTABLE).a\n", fp); +#else + char* name_prefix = cut_suffix(makefile->ets_name); + fprintf(fp, "DYNAMIC_LIBRARY = lib%s.so\n", name_prefix); + fprintf(fp, "STATIC_LIBRARY = lib%s.a\n", name_prefix); + Free(name_prefix); +#endif + } /* LIBRARY variable */ ets_suffix = get_suffix(makefile->ets_name); if (ets_suffix != NULL && !strcmp(ets_suffix, "exe")) { char* name_prefix = cut_suffix(makefile->ets_name); - fprintf(fp, "\n\nLIBRARY = %s%s\n", name_prefix ? name_prefix : "library", - makefile->dynamic ? "_lib.so" : ".a"); - Free(name_prefix); - } else { - fprintf(fp, "\n\nLIBRARY = %s%s\n", makefile->ets_name, - makefile->dynamic ? "_lib.so" : ".a"); + fprintf(fp, "\n\nLIBRARY = %s%s%s\n", "lib", name_prefix ? name_prefix : "library", + makefile->dynamic ? ".so" : ".a"); + Free(name_prefix); } + else { +#ifndef WIN32 + fprintf(fp, "\n\nLIBRARY = lib$(EXECUTABLE)%s\n", + makefile->dynamic ? ".so" : ".a"); +#else + fprintf(fp, "\n\nLIBRARY = lib%s%s\n", + makefile->ets_name, makefile->dynamic ? ".so" : ".a"); +#endif + } } else { fputs("\n\n" @@ -2485,10 +2835,20 @@ static void print_makefile(struct makefile_struct *makefile) "EXECUTABLE =\n" "LIBRARY =\n", fp); } - - fprintf(fp, "\n" + if (!makefile->linkingStrategy || !buildObjects(makefile->project_name, add_refd_prjs)) { + fprintf(fp, "\n" "TARGET = $(%s)", makefile->library ? "LIBRARY" : "EXECUTABLE"); - + } + else { + if (makefile->dynamic) { + fputs("\n" + "TARGET = $(SHARED_OBJECTS)", fp); + } + else { + fputs("\n" + "TARGET = $(OBJECTS)", fp); + } + } fputs("\n\n" "#\n" "# Do not modify these unless you know what you are doing...\n" @@ -2583,8 +2943,10 @@ static void print_makefile(struct makefile_struct *makefile) /* There is no need to create the .so for all the source files */ fputs("$(EXECUTABLE): $(LIBRARY)\n" "\tif $(CXX) $(LDFLAGS) -o $@ $(LIBRARY)", fp); - } else { - fprintf(fp, "$(EXECUTABLE): %s", makefile->dynamic ? "$(SHARED_OBJECTS)" : "$(OBJECTS)"); + } + else { + fprintf(fp, "$(EXECUTABLE): %s", makefile->dynamic ? "$(SHARED_OBJECTS)" : "$(OBJECTS)"); + if (!makefile->linkingStrategy) { // use the old linking method if (makefile->central_storage) { if (makefile->dynamic) { fputs(" $(BASE_SHARED_OBJECTS)", fp); @@ -2592,19 +2954,39 @@ static void print_makefile(struct makefile_struct *makefile) fputs(" $(BASE_OBJECTS)", fp); } } - fputs("\n" - "\tif $(CXX) $(LDFLAGS) -o $@ ", fp); /* start writing the link step */ - if (makefile->gnu_make) fputs("$^", fp); - else { + } + else { + if (!makefile->library) { if (makefile->dynamic) { - fputs("$(SHARED_OBJECTS)", fp); + fputs(" $(BASE_SHARED_OBJECTS)", fp); + } + else { + fputs(" $(BASE_OBJECTS)", fp); + } + if (makefile->hierarchical) { + fputs(" $(BASE2_LIBRARY)", fp); + } + } + } + fprintf(fp, "\n" + "\tif $(CXX) $(LDFLAGS) -o $@ %s", +#if defined (SOLARIS) || defined (SOLARIS8) + ""); +#else + makefile->dynamic ? "-Wl,--no-as-needed " : ""); /* start writing the link step */ +#endif + if (makefile->gnu_make) fputs("$^", fp); + else { + if (makefile->dynamic) { + fputs("$(SHARED_OBJECTS)", fp); if (makefile->central_storage) - fputs(" $(BASE_SHARED_OBJECTS)", fp); - } else { - fputs("$(OBJECTS)", fp); + fputs(" $(BASE_SHARED_OBJECTS)", fp); + } + else { + fputs("$(OBJECTS)", fp); if (makefile->central_storage) - fputs(" $(BASE_OBJECTS)", fp); - } + fputs(" $(BASE_OBJECTS)", fp); + } } } @@ -2622,27 +3004,65 @@ static void print_makefile(struct makefile_struct *makefile) "\t-L$(TTCN3_DIR)/lib -l$(TTCN3_LIB)" " \\\n" "\t-L$(OPENSSL_DIR)/lib -lcrypto"); - if (makefile->linkerlibraries) { - struct string_list* act_elem = makefile->linkerlibraries; - while (act_elem) { - if (act_elem->str) { - fprintf(fp, " -l%s", act_elem->str); + if (!makefile->linkingStrategy) { + if (makefile->linkerlibraries) { + struct string_list* act_elem = makefile->linkerlibraries; + while (act_elem) { + if (act_elem->str) { + fprintf(fp, " -l%s", act_elem->str); + } + act_elem = act_elem->next; } - act_elem = act_elem->next; } - } - if (makefile->linkerlibsearchpath) { - struct string_list* act_elem = makefile->linkerlibsearchpath; - while (act_elem) { - if (act_elem->str) { - fprintf(fp, " -L%s", act_elem->str); + if (makefile->linkerlibsearchpath) { + struct string_list* act_elem = makefile->linkerlibsearchpath; + while (act_elem) { + if (act_elem->str) { + fprintf(fp, " -L%s", act_elem->str); + } + act_elem = act_elem->next; } - act_elem = act_elem->next; } + fprintf(fp, " \\\n" + "\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n" + "\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n"); + } + else { // new linking strategy + fputs (" \\\n", fp); + if (makefile->linkerlibraries && !makefile->library) { + struct string2_list* head = getLinkerLibs(makefile->project_name); + struct string2_list* act_elem = head; + while (act_elem) { + if (act_elem->str1 && act_elem->str2) { + fprintf(fp, "\t-L%s -Wl,-rpath=%s -l%s \\\n", act_elem->str1, act_elem->str1, act_elem->str2); + } + act_elem = act_elem->next; + } + free_string2_list(head); + + struct string_list* act_head = getExternalLibPathes(makefile->project_name); + struct string_list* act_ext_elem = act_head; + while (act_ext_elem) { + if (act_ext_elem->str) { + fprintf(fp, "\t-L%s \\\n", act_ext_elem->str); + } + act_ext_elem = act_ext_elem->next; + } + free_string_list(act_head); + act_head = getExternalLibs(makefile->project_name); + act_ext_elem = act_head; + while (act_ext_elem) { + if (act_ext_elem->str) { + fprintf(fp, "\t-l%s \\\n", act_ext_elem->str); + } + act_ext_elem = act_ext_elem->next; + } + free_string_list(act_head); + } + fprintf(fp, + "\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n" + "\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n"); } - fprintf(fp, " \\\n" - "\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n" - "\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n"); /* If the compiler will not be run because there are no TTCN(PP) or ASN.1 * files, create the "compile" marker file which is checked by the * superior makefile if using this project as central storage */ @@ -2651,21 +3071,115 @@ static void print_makefile(struct makefile_struct *makefile) /* target $(LIBRARY) */ if (makefile->dynamic) { - fputs("\n" - "$(LIBRARY): $(OBJECTS)\n" - "\t$(CXX) -shared -o $@ $(OBJECTS)", fp); - if (makefile->central_storage) { - fputs(" $(BASE_SHARED_OBJECTS)", fp); + fprintf(fp, "\n" + "$(LIBRARY): $(OBJECTS)%s\n" + "\t$(CXX) -shared -o $@ $(OBJECTS)", + makefile->hierarchical ? " $(BASE2_LIBRARY)" : ""); + if (makefile->central_storage && !makefile->linkingStrategy) { + fputs(" $(BASE_SHARED_OBJECTS) ;\n" + "\tln -s $@ $(subst lib, ,$@) > /dev/null 2>&1 ;", fp); } - } else { - fputs("\n" - "$(LIBRARY): $(OBJECTS)\n" - "\t$(AR) -r $(ARFLAGS) $(LIBRARY) $(OBJECTS)", fp); - if (makefile->central_storage) { + if (makefile->linkingStrategy) { + struct string2_list* head = getLinkerLibs(makefile->project_name); + struct string2_list* act_elem = head; + // If the project is Executable on Top Level the linker can link the *.a and *.so together + while (act_elem && !isTopLevelExecutable(makefile->project_name)) { + if (act_elem->str1 && act_elem->str2 && isDynamicLibrary(act_elem->str2)) { + fputs(" \\\n", fp); + fprintf(fp, "\t-L%s -Wl,-rpath=%s -l%s", act_elem->str1, act_elem->str1, act_elem->str2); + } + else { + const char* mainLibName = getLibFromProject(makefile->project_name); + ERROR("Library archive 'lib%s.a' cannot be linked to dynamic library 'lib%s.so' " + "in project '%s' ", + act_elem->str2, mainLibName ? mainLibName : "", makefile->project_name); + free_string2_list(head); + exit(EXIT_FAILURE); + } + act_elem = act_elem->next; + } + free_string2_list(head); + struct string_list* act_head = getExternalLibPathes(makefile->project_name); + struct string_list* act_ext_elem = act_head; + while (act_ext_elem) { + if (act_ext_elem->str) { + fputs(" \\\n", fp); + fprintf(fp, "\t-L%s", act_ext_elem->str); + } + act_ext_elem = act_ext_elem->next; + } + free_string_list(act_head); + act_head = getExternalLibs(makefile->project_name); + act_ext_elem = act_head; + while (act_ext_elem) { + if (act_ext_elem->str) { + fputs(" \\\n", fp); + fprintf(fp, "\t-l%s", act_ext_elem->str); + } + act_ext_elem = act_ext_elem->next; + } + free_string_list(act_head); + } + } + else { // static linking + fprintf(fp, "\n" + "$(LIBRARY): $(OBJECTS)%s\n" + "\t$(AR) -r%s $(ARFLAGS) $(LIBRARY) $(OBJECTS)", + makefile->hierarchical ? " $(BASE2_LIBRARY)" : "", + makefile->linkingStrategy ? "cT" : ""); + if (makefile->central_storage && !makefile->linkingStrategy) { fputs(" $(BASE_OBJECTS)", fp); } + if (makefile->linkingStrategy) { + if ( makefile->library) { + struct string2_list* head = getLinkerLibs(makefile->project_name); + struct string2_list* act_elem = head; + while (act_elem) { + if (act_elem->str2 && !isDynamicLibrary(act_elem->str2)) { + fputs(" \\\n", fp); + fprintf(fp, "\t%s/lib%s.a", act_elem->str1, act_elem->str2); + } + else { + const char* mainLibName = getLibFromProject(makefile->project_name); + if (act_elem->str2) { + ERROR("Dynamic library 'lib%s.so' cannot be linked to static library 'lib%s.a' " + "in project '%s' ", + act_elem->str2, mainLibName ? mainLibName : "", makefile->project_name); + exit(EXIT_FAILURE); + } + else { + struct string_list* ext_libs = getExternalLibs(makefile->project_name); + if (ext_libs && ext_libs->str) { + ERROR("Third party dynamic library '%s' cannot be linked to static library 'lib%s.a' " + "in project '%s' ", ext_libs->str, + mainLibName ? mainLibName : "", makefile->project_name); + free_string_list(ext_libs); + exit(EXIT_FAILURE); + } + free_string_list(ext_libs); + } + } + act_elem = act_elem->next; + } + free_string2_list(head); + + struct string_list* act_head = getExternalLibs(makefile->project_name); + struct string_list* act_ext_elem = act_head; + while (act_ext_elem) { + if (act_ext_elem->str && hasExternalLibrary(act_ext_elem->str, makefile->project_name)) { + fputs(" \\\n", fp); + fprintf(fp, "\tlib%s.a", act_ext_elem->str); + ERROR("linking static 3d party or sytem library 'lib%s.a' to " + "project library 'lib%s.a' is not supported ", + act_ext_elem->str, makefile->ets_name); + exit(EXIT_FAILURE); + } + act_ext_elem = act_ext_elem->next; + } + free_string_list(act_head); + } + } } - fputs("\n\n.cc.o .c.o:\n" "\t$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $<\n\n", fp); @@ -2698,7 +3212,9 @@ static void print_makefile(struct makefile_struct *makefile) if (makefile->central_storage) { boolean is_first = TRUE; - fputs("$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile-all compile ", fp); + fprintf(fp, "$(GENERATED_SOURCES) $(GENERATED_HEADERS):%s compile-all compile ", + makefile->hierarchical ? " update" : ""); + if (add_refd_prjs) fputs("referenced-dep", fp); /* These extra compile dependencies for the generated .cc are here to * check if all the referenced projects are up to date. @@ -2707,175 +3223,260 @@ static void print_makefile(struct makefile_struct *makefile) */ if (!add_refd_prjs) for (i = 0; i < makefile->nBaseDirs; i++) { const struct base_dir_struct *base_dir = makefile->BaseDirs + i; - if (base_dir->has_modules) { - if (is_first) { - fputs(" \\\n", fp); - is_first = FALSE; - } else putc(' ', fp); - fprintf(fp, "%s/compile", base_dir->dir_name); - } + if (base_dir->has_modules) { + if (is_first) { + fputs(" \\\n", fp); + is_first = FALSE; + } + else putc(' ', fp); + fprintf(fp, "%s/compile", base_dir->dir_name); + } } - if (makefile->preprocess) { - fprintf(fp, "\n" - "\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n" - "\n" - "check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" - "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) " - "\\\n" - "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)\n" - "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", rm_command, add_refd_prjs?" referenced-check":""); - if (makefile->gnu_make) { - if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul - fputs("$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" - "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) " - "\\\n" - "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)\n", fp); - else - fputs("$^", fp); - } - else { - fputs("\\\n" - "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" - "\t$(PREPROCESSED_TTCN3_MODULES) " - "$(BASE_PREPROCESSED_TTCN3_MODULES) \\\n" - "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp); - } - fputs("\n\n" - "compile: $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) " - "$(ASN1_MODULES)\n" - "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n" - "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" - "\t$(PREPROCESSED_TTCN3_MODULES) " - "$(BASE_PREPROCESSED_TTCN3_MODULES) \\\n" - "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) - $?\n" - "\ttouch $@\n" - "\n" - "compile-all: $(BASE_TTCN3_MODULES) " - "$(BASE_PREPROCESSED_TTCN3_MODULES) \\\n" - "$(BASE_ASN1_MODULES)\n" - "\t$(MAKE) preprocess\n" - "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n" - "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" - "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) " - "\\\n" - "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) \\\n" - "\t- $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)\n" - "\ttouch $@ compile\n\n", fp); - } else { - fprintf(fp, "\n" - "\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n" - "\n" - "check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" - "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)\n" - "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", rm_command, add_refd_prjs?" referenced-check":""); - if (makefile->gnu_make) { - if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul - fputs("$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" - "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)\n", fp); - else - fputs("$^", fp); - } - else { - fputs("\\\n" - "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" - "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp); - } - fputs("\n\n" - "compile: $(TTCN3_MODULES) $(ASN1_MODULES)\n" - "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n" - "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" - "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) \\\n" - "\t- $?\n" - "\ttouch $@\n" - "\n" - "compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES)\n" - "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n" - "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" - "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) \\\n" - "\t- $(TTCN3_MODULES) $(ASN1_MODULES)\n" - "\ttouch $@ compile\n\n", fp); - } - for (i = 0; i < makefile->nBaseDirs; i++) { - const struct base_dir_struct *base_dir = makefile->BaseDirs + i; - if (base_dir->has_modules) { - size_t j; - fprintf(fp, "%s/compile:", base_dir->dir_name); - for (j = 0; j < makefile->nTTCN3Modules; j++) { - const struct module_struct *module = makefile->TTCN3Modules + j; - if (module->dir_name != NULL && - !strcmp(base_dir->dir_name, module->dir_name)) - print_file_name(fp, module); - } - for (j = 0; j < makefile->nTTCN3PPModules; j++) { - const struct module_struct *module = makefile->TTCN3PPModules + j; - if (module->dir_name != NULL && - !strcmp(base_dir->dir_name, module->dir_name)) - print_file_name(fp, module); - } - for (j = 0; j < makefile->nASN1Modules; j++) { - const struct module_struct *module = makefile->ASN1Modules + j; - if (module->dir_name != NULL && - !strcmp(base_dir->dir_name, module->dir_name)) - print_file_name(fp, module); - } - fprintf(fp, "\n" - "\t@echo 'Central directory %s is not up-to-date!'\n" - "\t@exit 2\n\n", base_dir->dir_name); - } + fprintf(fp, "\n" + "\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n" + "\n" + "check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" + "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) " + "%s\\\n" + "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n" + "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", + rm_command, add_refd_prjs?" referenced-check":"", + makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", + makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"", + makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":""); + if (makefile->gnu_make) { + if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul + fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" + "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) " + "%s\\\n" + "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n", + makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", + makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"", + makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":""); + else + fputs("$^", fp); + } + else { + fputs("\\\n" + "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" + "\t$(PREPROCESSED_TTCN3_MODULES) " + "$(BASE_PREPROCESSED_TTCN3_MODULES) \\\n" + "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp); + } + if (makefile->linkingStrategy && makefile->hierarchical) { + fputs("\n\n" + "update: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) \\\n" + "\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) $(BASE2_PREPROCESSED_TTCN3_MODULES)\n" + "ifneq ($(wildcard $(GENERATED_SOURCES)), ) \n" + "ifeq ($(wildcard $?), ) \n" + "\ttouch compile-all; \n" + "\ttouch update; \n" + "endif\n" + "endif",fp); + } + fprintf(fp, "\n\n" + "compile: $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) " + "$(ASN1_MODULES)\n" + "\t@echo \"compiling \"'$(patsubst %%.tpd, %%, $(TPD))';\n" + "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n" + "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" + "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) %s\\\n" + "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s - $?\n" + "\ttouch $@\n\n", + makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", + makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"", + makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES)":""); + fprintf (fp, + "compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) " + "%s" + "\t$(MAKE) preprocess\n" + "\t@echo \"compiling all \"'$(patsubst %%.tpd, %%, $(TPD))';\n" + "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n" + "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" + "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) %s" + "\\\n" + "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n" + "\t- $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)\n" + "\ttouch $@ compile\n\n", + makefile->linkingStrategy ? "\\\n\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) " + "$(BASE2_PREPROCESSED_TTCN3_MODULES) \n":"\n", + makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", + makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"", + makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":""); + } + else { + fprintf(fp, "\n" + "\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n", rm_command); + fprintf(fp, "\n" + "check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" + "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n" + "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", + add_refd_prjs?" referenced-check":"", + makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", + makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":""); + if (makefile->gnu_make) { + if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul + fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" + "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n", + makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", + makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":""); + else + fputs("$^", fp); } - } else { /* not central storage */ + else { + fputs("\\\n" + "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" + "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp); + } + + if (makefile->linkingStrategy && makefile->hierarchical) { + fputs("\n\n" + "update: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) \\\n" + "\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) $(BASE2_PREPROCESSED_TTCN3_MODULES)\n" + "ifneq ($(wildcard $(GENERATED_SOURCES)), ) \n" + "ifeq ($(wildcard $?), ) \n" + "\ttouch compile-all; \n" + "\ttouch update; \n" + "endif\n" + "endif",fp); + } + + fprintf(fp, "\n\n" + "compile: $(TTCN3_MODULES) $(ASN1_MODULES)\n" + "\t@echo \"compiling \"'$(patsubst %%.tpd, %%, $(TPD))';\n" + "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n" + "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" + "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n" + "\t- $?\n" + "\ttouch $@\n\n", + makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "", + makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : ""); + fprintf(fp, + "compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) %s\n", + makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES)" : ""); + fputs("\t@echo \"compiling all \"'$(patsubst %.tpd, %, $(TPD))';\n", fp); + fprintf(fp,"\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n" + "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" + "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n" + "\t- $(TTCN3_MODULES) $(ASN1_MODULES)\n" + "\ttouch $@ compile\n\n", + makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "", + makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : ""); + } + if (!makefile->hierarchical) + for (i = 0; i < makefile->nBaseDirs; i++) { + const struct base_dir_struct *base_dir = makefile->BaseDirs + i; + if (base_dir->has_modules) { + size_t j; + fprintf(fp, "%s/compile:", base_dir->dir_name); + for (j = 0; j < makefile->nTTCN3Modules; j++) { + const struct module_struct *module = makefile->TTCN3Modules + j; + if (module->dir_name != NULL && + !strcmp(base_dir->dir_name, module->dir_name)) + print_file_name(fp, module); + } + for (j = 0; j < makefile->nTTCN3PPModules; j++) { + const struct module_struct *module = makefile->TTCN3PPModules + j; + if (module->dir_name != NULL && + !strcmp(base_dir->dir_name, module->dir_name)) + print_file_name(fp, module); + } + for (j = 0; j < makefile->nASN1Modules; j++) { + const struct module_struct *module = makefile->ASN1Modules + j; + if (module->dir_name != NULL && + !strcmp(base_dir->dir_name, module->dir_name)) + print_file_name(fp, module); + } + fprintf(fp, "\n" + "\t@echo 'Central directory %s is not up-to-date!'\n" + "\t@exit 2\n\n", base_dir->dir_name); + } + } + } + else { /* not central storage */ fprintf(fp, "$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile\n" - "\t@if [ ! -f $@ ]; then %s compile; $(MAKE) compile; fi\n\n" - "check: $(TTCN3_MODULES) ", rm_command); + "\t@if [ ! -f $@ ]; then %s compile; $(MAKE) compile; fi\n\n" + "check: $(TTCN3_MODULES) ", rm_command); if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); fputs("$(ASN1_MODULES)\n" - "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", fp); + "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", fp); if (makefile->gnu_make) fputs("$^", fp); else { - fputs("\\\n" - "\t$(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)", - fp); + fputs("\\\n" + "\t$(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)", + fp); } fputs("\n\n" - "compile: $(TTCN3_MODULES) ", fp); + "compile: $(TTCN3_MODULES) ", fp); if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); fputs("$(ASN1_MODULES)\n" - "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) ", fp); + "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) ", fp); if (makefile->gnu_make) fputs("$^", fp); else { - fputs("\\\n" - "\t$(TTCN3_MODULES) ", fp); - if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); - fputs("$(ASN1_MODULES)", fp); + fputs("\\\n" + "\t$(TTCN3_MODULES) ", fp); + if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); + fputs("$(ASN1_MODULES)", fp); } fputs(" - $?\n" - "\ttouch $@\n" - "\n", fp); - } - fprintf(fp, "clean:%s\n" - "\t-%s $(EXECUTABLE) $(LIBRARY) $(OBJECTS) $(GENERATED_HEADERS) \\\n" - "\t$(GENERATED_SOURCES) ", add_refd_prjs?" referenced-clean":"", rm_command); - if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp); - if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); - fputs("compile", fp); - if (makefile->central_storage) fputs(" compile-all", fp); - if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp); - fprintf(fp, " \\\n" - "\ttags *.log%s", - add_refd_prjs?" referenced*":""); - + "\ttouch $@\n" + "\n", fp); + } +// clean: + if (makefile->linkingStrategy) { + fprintf(fp, "clean:%s\n", (add_refd_prjs && !makefile->hierarchical) ? + " referenced-clean" : ""); + if (makefile->dynamic && (makefile->central_storage || makefile->linkingStrategy)) { + fprintf(fp,"\tfind . -type l -name \"*.so\" -exec unlink {} \\;\n"); + } + fprintf(fp, "\t%s $(EXECUTABLE) $(DYNAMIC_LIBRARY) $(STATIC_LIBRARY) " + "$(OBJECTS) $(GENERATED_HEADERS) \\\n" + "\t$(GENERATED_SOURCES) ", rm_command); + if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp); + if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); + fputs("compile", fp); + if (makefile->central_storage) fputs(" compile-all", fp); + if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp); + fprintf(fp, " \\\n" + "\ttags *.log%s%s\n\n", + add_refd_prjs?" referenced*":"", + makefile->hierarchical ? " update":""); + } + else { + fprintf(fp, "clean:%s\n" + "\t-%s $(EXECUTABLE) $(LIBRARY) $(OBJECTS) $(GENERATED_HEADERS) \\\n" + "\t$(GENERATED_SOURCES) ", add_refd_prjs?" referenced-clean":"", rm_command); + if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp); + if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); + fputs("compile", fp); + if (makefile->central_storage) fputs(" compile-all", fp); + if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp); + fprintf(fp, " \\\n" + "\ttags *.log%s", + add_refd_prjs?" referenced*":""); + } + +// clean-all: + if (makefile->linkingStrategy && makefile->hierarchical) + fprintf(fp, "clean-all: %s clean\n", add_refd_prjs ? "referenced-clean-all":""); + +// dep: fputs("\n\ndep: $(GENERATED_SOURCES) $(USER_SOURCES)",fp); - if (add_refd_prjs) fprintf(fp, "\n\t%s referenced-dep", rm_command); + if (add_refd_prjs) { + fprintf(fp, "\n\t%s referenced-dep", rm_command); + } else fputs(" ;",fp); - + if (makefile->gcc_dep) { fprintf(fp, " \n\n" "ifeq ($(findstring n,$(MAKEFLAGS)),)\n" - "ifeq ($(filter clean check compile archive diag%s,$(MAKECMDGOALS)),)\n" + "ifeq ($(filter clean%s check compile archive diag%s,$(MAKECMDGOALS)),)\n" "-include $(DEPFILES)\n" "endif\n" - "endif", (makefile->preprocess ? " preprocess" : "")); + "endif", + (makefile->linkingStrategy && makefile->hierarchical) ? " clean-all" : "", + (makefile->preprocess ? " preprocess" : "")); /* Don't include .d files when cleaning etc.; make will try to build them * and this involves running the Titan compiler. Same for preprocess. * The check target would be pointless if running the compiler @@ -2887,36 +3488,50 @@ static void print_makefile(struct makefile_struct *makefile) if (makefile->gnu_make) fputs("$^", fp); else fputs("$(GENERATED_SOURCES) $(USER_SOURCES)", fp); } - fprintf(fp, "\n\n" - "archive:%s\n" - "\tmkdir -p $(ARCHIVE_DIR)\n" - "\ttar -cvhf - ", add_refd_prjs?" referenced-archive":""); - if (makefile->central_storage) { - fputs("$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n", fp); - if (makefile->preprocess) { - fputs("\t$(TTCN3_PP_MODULES) $(BASE_TTCN3_PP_MODULES) " - "$(TTCN3_INCLUDES)\\\n", fp); + + if (makefile->linkingStrategy) { + fputs("\n\n" + "archive:\n" + "\t@perl $(TTCN3_DIR)/bin/ttcn3_archive.pl\n\n", fp); + } + else { + fputs("\n\n" + "archive:\n" + "\tmkdir -p $(ARCHIVE_DIR)\n" + "\ttar -cvhf - ", fp); + if (makefile->central_storage) { + fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n", + makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : ""); + if (makefile->preprocess) { + fprintf(fp, "\t$(TTCN3_PP_MODULES) $(BASE_TTCN3_PP_MODULES) " + "%s $(TTCN3_INCLUDES) \\\n", + makefile->linkingStrategy ? "$(BASE2_TTCN3_PP_MODULES)" : ""); + } + fprintf(fp, "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n" + "\t$(USER_HEADERS) $(BASE_USER_HEADERS) %s\\\n" + "\t$(USER_SOURCES) $(BASE_USER_SOURCES) %s", + makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "", + makefile->linkingStrategy ? "$(BASE2_USER_HEADERS) " : "", + makefile->linkingStrategy ? "$(BASE2_USER_SOURCES)" : ""); } - fputs("\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) \\\n" - "\t$(USER_HEADERS) $(BASE_USER_HEADERS) \\\n" - "\t$(USER_SOURCES) $(BASE_USER_SOURCES)", fp); - } else { - fputs("$(TTCN3_MODULES) ", fp); - if (makefile->preprocess) { - fputs("$(TTCN3_PP_MODULES) \\\n" - "\t$(TTCN3_INCLUDES) ", fp); + else { + fputs("$(TTCN3_MODULES) ", fp); + if (makefile->preprocess) { + fputs("$(TTCN3_PP_MODULES) \\\n" + "\t$(TTCN3_INCLUDES) ", fp); + } + fputs("$(ASN1_MODULES) \\\n" + "\t$(USER_HEADERS) $(USER_SOURCES)", fp); } - fputs("$(ASN1_MODULES) \\\n" - "\t$(USER_HEADERS) $(USER_SOURCES)", fp); + fputs(" $(OTHER_FILES) \\\n" + "\t| gzip >$(ARCHIVE_DIR)/`basename $(TARGET) .exe`-" + "`date '+%y%m%d-%H%M'`.tgz\n\n", fp); } - fputs(" $(OTHER_FILES) \\\n" - "\t| gzip >$(ARCHIVE_DIR)/`basename $(TARGET) .exe`-" - "`date '+%y%m%d-%H%M'`.tgz\n\n", fp); fprintf(fp, "diag:\n" - "\t$(TTCN3_DIR)/bin/compiler -v 2>&1\n" - "\t$(TTCN3_DIR)/bin/mctr_cli -v 2>&1\n" - "\t$(CXX) -v 2>&1\n" + "\t$(TTCN3_DIR)/bin/compiler -v 2>&1\n" + "\t$(TTCN3_DIR)/bin/mctr_cli -v 2>&1\n" + "\t$(CXX) -v 2>&1\n" "%s" "\t@echo TTCN3_DIR=$(TTCN3_DIR)\n" "\t@echo OPENSSL_DIR=$(OPENSSL_DIR)\n" @@ -2925,12 +3540,13 @@ static void print_makefile(struct makefile_struct *makefile) makefile->dynamic ? "" : "\t$(AR) -V 2>&1\n"); if (add_refd_prjs) { - fputs("referenced-all referenced-shared_objects referenced-executable referenced-library \\\n" - "referenced-objects referenced-check \\\n" - "referenced-clean referenced-archive:\n" - "\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n" - "\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n" - "\tdone; \n\n", fp); + fprintf(fp, "referenced-all referenced-shared_objects referenced-executable referenced-library \\\n" + "referenced-objects referenced-check \\\n" + "referenced-clean%s:\n" + "\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n" + "\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n" + "\tdone; \n\n", + (makefile->linkingStrategy && makefile->hierarchical) ? "-all" : ""); fputs("referenced-dep:\n" "\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n" "\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n" @@ -2953,9 +3569,12 @@ static void print_makefile(struct makefile_struct *makefile) } else { NOTIFY("Makefile skeleton was generated."); } - } else { - ERROR("Output file `%s' already exists. Use switch `-f' to force " - "overwrite.", makefile->output_file); + } + else { + ERROR("Output file `%s' already exists. Use switch `%s' to force " + "overwrite.", + makefile->output_file, + makefile->linkingStrategy ? "-F" : "-f"); } } @@ -2977,7 +3596,8 @@ static void run_makefilegen_commands(struct string2_list* run_command_list) rv = set_working_dir(sub_proj_effective_work_dir); if (rv) ERROR("Could not set working dir to `%s'", sub_proj_effective_work_dir); else { - printf("Executing `%s' in working directory `%s'...\n", command, sub_proj_effective_work_dir); + fprintf(stderr, "Executing `%s' in working directory `%s'...\n", + command, sub_proj_effective_work_dir); rv = system(command); if (rv) ERROR("Execution failed with error code %d", rv); // TODO: it's not clear what system()'s return codes can be in different situations and platforms } @@ -3015,15 +3635,15 @@ static void generate_symlinks(struct string2_list* create_symlink_list) * command line switches. */ static void generate_makefile(size_t n_arguments, char *arguments[], size_t n_other_files, const char *other_files[], const char *output_file, - const char *ets_name, boolean gnu_make, boolean single_mode, + const char *ets_name, char *project_name, boolean gnu_make, boolean single_mode, boolean central_storage, boolean absolute_paths, boolean preprocess, boolean dump_makefile_data, boolean force_overwrite, boolean use_runtime_2, boolean dynamic, boolean makedepend, boolean coverage, const char *code_splitting_mode, const char *tcov_file_name, - boolean Lflag, struct string_list* sub_project_dirs, struct string_list* ttcn3_prep_includes, - struct string_list* ttcn3_prep_defines, struct string_list* prep_includes, struct string_list* prep_defines, - boolean codesplittpd, boolean quietly, boolean disablesubtypecheck, const char* cxxcompiler, - const char* optlevel, const char* optflags, boolean disableber, boolean disableraw, boolean disabletext, + boolean Lflag, boolean Zflag, boolean Hflag, struct string_list* sub_project_dirs, struct string_list* ttcn3_prep_includes, + struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes, + struct string_list* prep_defines, struct string_list* prep_undefines, boolean codesplittpd, boolean quietly, boolean disablesubtypecheck, + const char* cxxcompiler, const char* optlevel, const char* optflags, boolean disableber, boolean disableraw, boolean disabletext, boolean disablexer, boolean disablejson, boolean forcexerinasn, boolean defaultasomit, boolean gccmsgformat, boolean linenumbersonlymsg, boolean includesourceinfo, boolean addsourcelineinfo, boolean suppresswarnings, boolean outparamboundness, struct string_list* solspeclibraries, struct string_list* sol8speclibraries, @@ -3037,6 +3657,7 @@ static void generate_makefile(size_t n_arguments, char *arguments[], struct makefile_struct makefile; init_makefile_struct(&makefile); + makefile.project_name = project_name; makefile.central_storage = central_storage; makefile.gnu_make = gnu_make; makefile.preprocess = preprocess; @@ -3047,11 +3668,15 @@ static void generate_makefile(size_t n_arguments, char *arguments[], makefile.gcc_dep = gnu_make && !makedepend; makefile.coverage = coverage; makefile.library = Lflag; + makefile.linkingStrategy = Zflag; + makefile.hierarchical = Hflag; makefile.sub_project_dirs = sub_project_dirs; makefile.ttcn3_prep_includes = ttcn3_prep_includes; makefile.ttcn3_prep_defines = ttcn3_prep_defines; + makefile.ttcn3_prep_undefines = ttcn3_prep_undefines; makefile.prep_includes = prep_includes; makefile.prep_defines = prep_defines; + makefile.prep_undefines = prep_undefines; makefile.codesplittpd = codesplittpd; makefile.quietly = quietly; makefile.disablesubtypecheck = disablesubtypecheck; @@ -3148,7 +3773,7 @@ static void generate_makefile(size_t n_arguments, char *arguments[], } if (tcov_file_name != NULL) { - makefile.tcov_file_name = mputprintf(makefile.tcov_file_name, "-K %s", tcov_file_name); + makefile.tcov_file_name = mputprintf(makefile.tcov_file_name, "-K %s", tcov_file_name); } if (makefile.nTTCN3Modules >= 1) { @@ -3188,7 +3813,6 @@ static void generate_makefile(size_t n_arguments, char *arguments[], if (dump_makefile_data) dump_makefile_struct(&makefile, 0); if (error_count == 0) print_makefile(&makefile); - free_makefile_struct(&makefile); } @@ -3202,7 +3826,7 @@ static void generate_makefile(size_t n_arguments, char *arguments[], static void usage(void) { fprintf(stderr, "\n" - "usage: %s [-abc" C_flag "dDfFglLmprRstTVwWX] [-K file] [-P dir]" + "usage: %s [-abc" C_flag "dDfFglLmprRstTVwWXZ] [-K file] [-P dir]" " [-U none|type] [-e ets_name] [-o dir|file]\n" " [-t project_descriptor.tpd [-b buildconfig]]\n" " [-O file] ... module_name ... testport_name ...\n" @@ -3242,6 +3866,8 @@ static void usage(void) " -P dir: prints out a file list found in a given TPD relative to the given directory\n" " -X: generate XML file that describes the TPD hierarchy, use with -r\n" " -W: prefix working directories with project name\n" + " -Z: recursive Makefile generation from TPD using object files and dynamic libraries too\n" + " -H: hierachical Makefile generation from TPD use with -Z\n" , program_name, program_name); } @@ -3285,10 +3911,11 @@ int main(int argc, char *argv[]) dxflag = FALSE, fxflag = FALSE, doflag = FALSE, gfflag = FALSE, lnflag = FALSE, isflag = FALSE, asflag = FALSE, swflag = FALSE, Vflag = FALSE, Dflag = FALSE, Wflag = FALSE, - djflag = FALSE; + djflag = FALSE, Zflag = FALSE, Hflag = FALSE; boolean error_flag = FALSE; char *output_file = NULL; char *ets_name = NULL; + char *project_name = NULL; size_t n_other_files = 0; const char **other_files = NULL; const char *code_splitting_mode = NULL; @@ -3301,8 +3928,10 @@ int main(int argc, char *argv[]) struct string2_list* create_symlink_list = NULL; struct string_list* ttcn3_prep_includes = NULL; struct string_list* ttcn3_prep_defines = NULL; + struct string_list* ttcn3_prep_undefines = NULL; struct string_list* prep_includes = NULL; struct string_list* prep_defines = NULL; + struct string_list* prep_undefines = NULL; char *cxxcompiler = NULL; char *optlevel = NULL; char *optflags = NULL; @@ -3318,6 +3947,7 @@ int main(int argc, char *argv[]) char* generatorCommandOutput = NULL; struct string2_list* target_placement_list = NULL; struct string2_list* run_command_list = NULL; + struct string2_list* required_configs = NULL; #ifdef LICENSE license_struct lstr; @@ -3334,7 +3964,7 @@ int main(int argc, char *argv[]) } for ( ; ; ) { - int c = getopt(argc, argv, "O:ab:c" C_flag "dDe:fFgK:o:lLmpP:rRst:TU:vVwWXY"); + int c = getopt(argc, argv, "O:ab:c" C_flag "dDe:fFgK:o:lLmpP:rRst:TU:vVwWXYZH"); if (c == -1) break; switch (c) { case 'O': @@ -3381,6 +4011,9 @@ int main(int argc, char *argv[]) case 'g': SET_FLAG(g); break; + case 'H': + SET_FLAG(H); + break; case 'o': SET_FLAG(o); output_file = optarg; @@ -3401,11 +4034,11 @@ int main(int argc, char *argv[]) SET_FLAG(P); /* Optional arguments with `::' are GNU specific... */ if (get_path_status(optarg) == PS_DIRECTORY) { - file_list_path = optarg; + file_list_path = optarg; } else { - ERROR("The -P flag requires a valid directory as its argument " - "instead of `%s'", optarg); - error_flag = TRUE; + ERROR("The -P flag requires a valid directory as its argument " + "instead of `%s'", optarg); + error_flag = TRUE; } break; case 'r': @@ -3451,6 +4084,9 @@ int main(int argc, char *argv[]) case 'X': SET_FLAG(X); break; + case 'Z': + SET_FLAG(Z); + break; default: error_flag = TRUE; break; @@ -3463,12 +4099,17 @@ int main(int argc, char *argv[]) if ( aflag || bflag || cflag || Cflag || dflag || eflag || fflag || Fflag || gflag || mflag || oflag || lflag || pflag || Pflag || rflag || Rflag || sflag || tflag || Tflag || Vflag || wflag || Xflag || Kflag || Dflag || Wflag || Yflag - || n_other_files > 0) - error_flag = TRUE; + || Zflag || Hflag || n_other_files > 0) + error_flag = TRUE; + } + + if (Zflag) { + if (!gflag) gflag = TRUE; // GNU make + if (!cflag) cflag = TRUE; // central sorage } - if ((bflag || Dflag || Pflag || Vflag || rflag || Wflag) && !tflag) { - ERROR("Using the '-b', '-D', '-P', '-V', '-r' or '-W' option requires the use of the -t' option."); + if ((bflag || Dflag || Pflag || Vflag || rflag || Wflag || Zflag) && !tflag) { + ERROR("Using the '-b', '-D', '-P', '-V', '-r' 'Z' or '-W' option requires the use of the -t' option."); error_flag = TRUE; } @@ -3492,6 +4133,16 @@ int main(int argc, char *argv[]) error_flag = TRUE; } + if (!Zflag && Hflag) { + ERROR("Using the '-H' option requires use of the '-Z' option."); + error_flag = TRUE; + } + + if (Zflag && !Fflag && !fflag) { + ERROR("Using the '-Z' option requires use of the '-F' option."); + error_flag = TRUE; + } + if (lflag && !strncmp(get_platform_string(), "WIN32", 5)) { ERROR("Generating Makefile with dynamic linking enabled is not supported " "on Windows platform"); @@ -3544,12 +4195,18 @@ int main(int argc, char *argv[]) ttcn3_prep_defines = (struct string_list*)Malloc(sizeof(struct string_list)); ttcn3_prep_defines->str = NULL; ttcn3_prep_defines->next = NULL; + ttcn3_prep_undefines = (struct string_list*)Malloc(sizeof(struct string_list)); + ttcn3_prep_undefines->str = NULL; + ttcn3_prep_undefines->next = NULL; prep_includes = (struct string_list*)Malloc(sizeof(struct string_list)); prep_includes->str = NULL; prep_includes->next = NULL; prep_defines = (struct string_list*)Malloc(sizeof(struct string_list)); prep_defines->str = NULL; prep_defines->next = NULL; + prep_undefines = (struct string_list*)Malloc(sizeof(struct string_list)); + prep_undefines->str = NULL; + prep_undefines->next = NULL; solspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list)); solspeclibraries->str = NULL; solspeclibraries->next = NULL; @@ -3593,29 +4250,45 @@ int main(int argc, char *argv[]) run_command_list->str1 = NULL; run_command_list->str2 = NULL; run_command_list->next = NULL; + required_configs = (struct string2_list*)Malloc(sizeof(struct string2_list)); + required_configs->str1 = NULL; + required_configs->str2 = NULL; + required_configs->next = NULL; + tpd_processed = process_tpd(tpd_file_name, tpd_build_config, file_list_path, - &argc, &argv, &optind, &ets_name, + &argc, &argv, &optind, &ets_name, &project_name, &gflag, &sflag, &cflag, &aflag, &pflag, &Rflag, &lflag, &mflag, &Pflag, &Lflag, rflag, Fflag, Tflag, output_file, &abs_work_dir, sub_project_dirs, program_name, prj_graph_fp, - create_symlink_list,ttcn3_prep_includes, ttcn3_prep_defines, prep_includes, prep_defines, &csflag, &quflag, &dsflag, &cxxcompiler, - &optlevel, &optflags, &dbflag, &drflag, &dtflag, &dxflag, &djflag, &fxflag, &doflag, &gfflag, &lnflag, &isflag, + create_symlink_list,ttcn3_prep_includes, ttcn3_prep_defines,ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, &csflag, + &quflag, &dsflag, &cxxcompiler, &optlevel, &optflags, &dbflag, &drflag, &dtflag, &dxflag, &djflag, &fxflag, &doflag, &gfflag, &lnflag, &isflag, &asflag, &swflag, &Yflag, solspeclibraries, sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, &ttcn3prep, - linkerlibraries, additionalObjects, linkerlibsearchpath, Vflag, Dflag, &generatorCommandOutput, target_placement_list, Wflag, run_command_list); + linkerlibraries, additionalObjects, linkerlibsearchpath, Vflag, Dflag, &Zflag, &Hflag, + &generatorCommandOutput, target_placement_list, Wflag, run_command_list, required_configs); + Free(abs_work_dir); if (prj_graph_fp) { fprintf(prj_graph_fp, "\n"); fclose(prj_graph_fp); } - if (tpd_processed == TPD_FAILED) ERROR("Failed to process %s", tpd_file_name); + if (tpd_processed == TPD_FAILED) { + ERROR("Failed to process %s", tpd_file_name); + exit(EXIT_FAILURE); + } } if (!Pflag) { run_makefilegen_commands(run_command_list); generate_symlinks(create_symlink_list); + if (Zflag) { + if (Fflag) + NOTIFY("Makefile generation from top-level TPD: %s", tpd_file_name); + if (!Fflag && fflag) + NOTIFY("Makefile generation from lower level TPD: %s", tpd_file_name); + } generate_makefile(argc - optind, argv + optind, n_other_files, other_files, - output_file, ets_name, gflag, sflag, cflag, aflag, pflag, dflag, fflag||Fflag, - Rflag, lflag, mflag, Cflag, code_splitting_mode, tcov_file_name, Lflag, rflag ? sub_project_dirs : NULL, ttcn3_prep_includes, - ttcn3_prep_defines, prep_includes, prep_defines, csflag, quflag, dsflag, cxxcompiler, optlevel, optflags, dbflag, + output_file, ets_name, project_name, gflag, sflag, cflag, aflag, pflag, dflag, fflag||Fflag, + Rflag, lflag, mflag, Cflag, code_splitting_mode, tcov_file_name, Lflag, Zflag, Hflag, rflag ? sub_project_dirs : NULL, ttcn3_prep_includes, + ttcn3_prep_defines, ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, csflag, quflag, dsflag, cxxcompiler, optlevel, optflags, dbflag, drflag, dtflag, dxflag, djflag, fxflag, doflag, gfflag, lnflag, isflag, asflag, swflag, Yflag, solspeclibraries, sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, ttcn3prep, linkerlibraries, additionalObjects, linkerlibsearchpath, generatorCommandOutput, target_placement_list); @@ -3624,8 +4297,10 @@ int main(int argc, char *argv[]) free_string_list(sub_project_dirs); free_string_list(ttcn3_prep_includes); free_string_list(ttcn3_prep_defines); + free_string_list(ttcn3_prep_undefines); free_string_list(prep_includes); free_string_list(prep_defines); + free_string_list(prep_undefines); free_string_list(solspeclibraries); free_string_list(sol8speclibraries); free_string_list(linuxspeclibraries); @@ -3637,6 +4312,7 @@ int main(int argc, char *argv[]) Free(generatorCommandOutput); free_string2_list(target_placement_list); + free_string2_list(required_configs); Free(other_files); if (tpd_processed == TPD_SUCCESS) { @@ -3655,8 +4331,7 @@ int main(int argc, char *argv[]) for (E = 0; E < argc; ++E) Free(argv[E]); Free(argv); } - /* check_mem_leak(program_name); not needed when linked to new.cc */ + /* check_mem_leak(program_name); not needed when linked to new.cc */ return error_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS; } - diff --git a/compiler2/record.c b/compiler2/record.c index 67b7e96..79e914f 100644 --- a/compiler2/record.c +++ b/compiler2/record.c @@ -1799,11 +1799,6 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) /* start_at is the index of the first "real" member of the record */ size_t start_at = uo + (sdef->xerUseOrderPossible != 0); - /* Max. number of EMBED-VALUES strings. The actual number may change - * at runtime: omitted optional (non-attribute) members decrease the - * number of embed strings needed, and xsi:nil=true sets it to zero.*/ - size_t max_embed; - /* Number of optional non-attributes */ size_t n_opt_elements = 0; @@ -1828,7 +1823,6 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) ++n_opt_elements; } } - max_embed = sdef->nElements - start_at - num_attributes + 1; /* Write some helper functions */ def = mputstr(def, @@ -1904,7 +1898,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) /* * * * * * * * * * XER_encode * * * * * * * * * * * * * * */ src = mputprintf(src, "int %s::XER_encode(const XERdescriptor_t& p_td, " - "TTCN_Buffer& p_buf, unsigned int p_flavor, int p_indent) const\n" + "TTCN_Buffer& p_buf, unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n" "{\n" " if (!is_bound()) TTCN_EncDec_ErrorContext::error" "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" @@ -1994,7 +1988,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) " if (e_xer && (p_td.xer_bits & USE_QNAME)) {\n" " if (field_%s.is_value()) {\n" " p_buf.put_s(11, (cbyte*)\" xmlns:b0='\");\n" - " field_%s.XER_encode(%s_xer_, p_buf, p_flavor | XER_LIST, p_indent+1);\n" + " field_%s.XER_encode(%s_xer_, p_buf, p_flavor | XER_LIST, p_indent+1, 0);\n" " p_buf.put_c('\\'');\n" " }\n" " if (p_td.xer_bits & XER_ATTRIBUTE) begin_attribute(p_td, p_buf);\n" @@ -2003,7 +1997,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) " p_buf.put_s(3, (cbyte*)\"b0:\");\n" " sub_len += 3;\n" " }\n" - " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor | XER_LIST, p_indent+1);\n" + " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor | XER_LIST, p_indent+1, 0);\n" " if (p_td.xer_bits & XER_ATTRIBUTE) p_buf.put_c('\\'');\n" " } else" /* no newline */ , sdef->elements[0].name @@ -2017,12 +2011,10 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) /* First, the EMBED-VALUES member as an ordinary member if not doing EXER */ if (sdef->xerEmbedValuesPossible) { src = mputprintf(src, - " int exp_emb = %u;\n" " if (!e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" " ec_1.set_msg(\"%s': \");\n" - " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1);\n" + " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" " }\n" - , (unsigned int)max_embed , sdef->elements[0].dispname , sdef->elements[0].name, sdef->elements[0].typegen ); @@ -2031,7 +2023,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) if (sdef->xerUseOrderPossible) { src = mputprintf(src, " if (!e_xer && (p_td.xer_bits & USE_ORDER)) {\n" - " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1);\n" + " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" " }\n" , sdef->elements[uo].name, sdef->elements[uo].typegen ); @@ -2067,7 +2059,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) if (i==0 && sdef->xerEmbedValuesPossible && (sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT)) continue ; src = mputprintf(src, " ec_1.set_msg(\"%s': \");\n" - " tmp_len = field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1);\n" + " tmp_len = field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" " %ssub_len += tmp_len;\n" /* do not add if attribute and EXER */ , sdef->elements[i].dispname , sdef->elements[i].name, sdef->elements[i].typegen @@ -2098,46 +2090,19 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) } if (sdef->xerEmbedValuesPossible) { - size_t op; src = mputprintf(src, " ec_1.set_msg(\"%s': \");\n" " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" - , sdef->elements[0].dispname - ); - - if (sdef->xerUseNilPossible) { - src = mputstr(src, /* 25.2.6 a */ - " if ((p_td.xer_bits & USE_NIL) && nil_attribute) exp_emb = 0;\n" - " else {\n"); - } - - for (op = 0; op < sdef->nElements; ++op) { - if (sdef->elements[op].isOptional && !sdef->elements[op].xerAttribute) { - src = mputprintf(src, - " if (!field_%s.ispresent()) --exp_emb;\n" - , sdef->elements[op].name - ); - } - } - - if (sdef->xerUseNilPossible) src = mputstr(src, " }\n"); - - src = mputprintf(src, - " if (field_%s.size_of()!=exp_emb) " - "TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, " - "\"Wrong number %%d of EMBED-VALUEs, expected %%d\", field_%s.size_of(), exp_emb);\n" - , sdef->elements[0].name - , sdef->elements[0].name); /* write the first string (must come AFTER the attributes) */ - src = mputprintf(src, - " %ssub_len += field_%s[0].XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1);\n" + " if (field_%s.size_of() > 0) {\n" + " sub_len += field_%s[0].XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" + " }\n" " }\n" - , (sdef->xerUseNilPossible ? "if (exp_emb > 0) " : "") - , sdef->elements[0].name); + , sdef->elements[0].dispname, sdef->elements[0].name, sdef->elements[0].name); if (want_namespaces) { /* here's another chance */ src = mputprintf(src, " else if ( !(p_td.xer_bits & EMBED_VALUES)) {\n" - " %sfield_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1);\n" + " %sfield_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" " }\n" , ((sdef->elements[0].xerAnyKind & ANY_ATTRIB_BIT) ? "" : "sub_len += " ) , sdef->elements[0].name, sdef->elements[0].typegen @@ -2148,6 +2113,17 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) /* Then, all the non-attributes. Structuring the code like this depends on * all attributes appearing before all non-attributes (excluding * special members for EMBED-VALUES, USE-ORDER, etc.) */ + if (sdef->xerEmbedValuesPossible) { + src = mputprintf(src, + " embed_values_enc_struct_t* emb_val = 0;\n" + " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && field_%s.size_of() > 1) {\n" + " emb_val = new embed_values_enc_struct_t;\n" + " emb_val->embval_array = &field_%s;\n" + " emb_val->embval_index = 1;\n" + " emb_val->embval_size = field_%s.size_of();\n" + " }\n", sdef->elements[0].name, sdef->elements[0].name, sdef->elements[0].name); + } + if (sdef->xerUseOrderPossible) { int max_ordered = sdef->nElements - start_at - num_attributes; int min_ordered = max_ordered - n_opt_elements; @@ -2169,7 +2145,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) src = mputprintf(src, " if (!nil_attribute) {\n" "%s" - " if (!e_xer) sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag);\n" + " if (!e_xer) sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag, 0);\n" " else" /* no newline */ , (sdef->xerUseNilPossible ? " if (!(p_td.xer_bits & USE_ORDER)) p_flavor |= (p_td.xer_bits & USE_NIL);\n" : "") /* If USE-ORDER is on, the tag-removing effect of USE-NIL has been @@ -2224,7 +2200,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) src = mputprintf(src, " case %lu:\n" " ec_1.set_msg(\"%s': \");\n" - " sub_len += field_%s%s%s%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag);\n" + " sub_len += field_%s%s%s%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag, %s);\n" , (unsigned long)offset++ , sdef->elements[i].dispname @@ -2233,7 +2209,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) , (sdef->xerUseNilPossible ? sdef->elements[i].name : "") , (sdef->xerUseNilPossible ? "()" : "") , sdef->elements[i].typegen - + , sdef->xerEmbedValuesPossible ? "emb_val" : "0" ); src = mputstr(src, " break;\n"); @@ -2246,8 +2222,11 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) if (sdef->xerEmbedValuesPossible) { src = mputprintf(src, - " if (e_xer && i+1 < exp_emb && (p_td.xer_bits & EMBED_VALUES)) { // embed-val\n" - " field_%s[i+1].XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1);\n" + " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&\n" + " emb_val->embval_index < emb_val->embval_size) { // embed-val\n" + " field_%s[emb_val->embval_index].XER_encode(\n" + " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" + " ++emb_val->embval_index;\n" " }\n" , sdef->elements[0].name); } @@ -2267,22 +2246,38 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) , sdef->elements[i].dispname ); src = mputprintf(src, - " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor%s, p_indent+!omit_tag);\n" + " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor%s, p_indent+!omit_tag, %s);\n" , sdef->elements[i].name, sdef->elements[i].typegen , sdef->xerUseNilPossible ? "| (p_td.xer_bits & USE_NIL)" : "" + , sdef->xerEmbedValuesPossible ? "emb_val" : "0" ); if (sdef->xerEmbedValuesPossible) { - unsigned long idx = i - start_at - num_attributes + 1; src = mputprintf(src, - " if (e_xer && exp_emb > %lu && (p_td.xer_bits & EMBED_VALUES)) {\n" - " field_%s[%lu].XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1);\n" + " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&\n" + " emb_val->embval_index < emb_val->embval_size) {\n" + " field_%s[emb_val->embval_index].XER_encode(\n" + " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" + " ++emb_val->embval_index;\n" " }\n" - , idx - , sdef->elements[0].name, idx); + , sdef->elements[0].name); } } /* next field when not USE-ORDER */ + if (sdef->xerEmbedValuesPossible) { + src = mputprintf(src, + " if (0 != emb_val) {\n" + " if (emb_val->embval_index < emb_val->embval_size) {\n" + " ec_1.set_msg(\"%s': \");\n" + " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,\n" + " \"Too many EMBED-VALUEs specified: %%d (expected %%d or less)\",\n" + " emb_val->embval_size, emb_val->embval_index);\n" + " }\n" + " delete emb_val;\n" + " }\n" + , sdef->elements[0].name); + } + src = mputstr(src, " } // QN?\n"); { @@ -2335,7 +2330,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) src = mputprintf(src, /* XERSTUFF decodegen for record/SEQUENCE*/ "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader," - " unsigned int p_flavor)\n" + " unsigned int p_flavor, embed_values_dec_struct_t*)\n" "{\n" " bound_flag = TRUE;\n" /* Remove XER_LIST, XER_RECOF from p_flavor. This is not required @@ -2441,8 +2436,9 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) } else { /* must be the ANY-ATTRIBUTES */ src = mputprintf(src, - " field_%s.set_size(0);\n", - sdef->elements[aaa].name); + " field_%s%s;\n" + , sdef->elements[aaa].name + , sdef->elements[aaa].isOptional ? " = OMIT_VALUE" : ".set_size(0)"); } } @@ -2493,7 +2489,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) src = mputprintf(src, " if (check_name(attr_name, %s_xer_, 1) && check_namespace(ns_uri, %s_xer_)) {\n" " ec_1.set_msg(\"%s': \");\n" - " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL));\n" + " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL), 0);\n" " } else" , sdef->elements[i].typegen, sdef->elements[i].typegen , sdef->elements[i].dispname /* set_msg */ @@ -2514,8 +2510,8 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) /* we are at a dangling else */ src = mputprintf(src, " {\n" - " TTCN_EncDec_ErrorContext ec_0(\"Attribute %%d: \", (int)num_aa);" - " UNIVERSAL_CHARSTRING& new_elem = field_%s[num_aa++];\n" + " TTCN_EncDec_ErrorContext ec_0(\"Attribute %%d: \", (int)num_aa);\n" + " UNIVERSAL_CHARSTRING& new_elem = field_%s%s[num_aa++];\n" /* Construct the AnyAttributeFormat (X.693amd1, 18.2.6) */ " TTCN_Buffer aabuf;\n" " const xmlChar *x_name = p_reader.LocalName();\n" @@ -2536,6 +2532,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) " new_elem.decode_utf8(aabuf.get_len(), aabuf.get_data());\n" " } \n" , sdef->elements[aa_index].name + , sdef->elements[aa_index].isOptional ? "()" : "" , sdef->elements[aa_index].typegen, sdef->elements[aa_index].typegen ); } @@ -2584,7 +2581,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) " if (!(p_td.xer_bits & EMBED_VALUES)) {\n" " ec_1.set_msg(\"%s': \");\n" " field_%s.XER_decode(%s_xer_, p_reader, " - "p_flavor | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : 0));\n" + "p_flavor | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : 0), 0);\n" " }\n" , sdef->elements[0].dispname , sdef->elements[0].name, sdef->elements[0].typegen @@ -2618,7 +2615,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) src = mputprintf(src, " {\n" " ec_1.set_msg(\"%s': \");\n" - " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL));\n" + " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL), 0);\n" " }\n" , sdef->elements[i].dispname , sdef->elements[i].name, sdef->elements[i].typegen @@ -2633,6 +2630,17 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) { src = mputstr(src, "}\n"); } + + if (sdef->xerEmbedValuesPossible) { + src = mputprintf(src, + " embed_values_dec_struct_t* emb_val = 0;\n" + " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" + " emb_val = new embed_values_dec_struct_t;\n" + " emb_val->embval_array = &field_%s;\n" + " emb_val->embval_index = 0;\n" + " field_%s.set_size(0);\n" + " }\n", sdef->elements[0].name, sdef->elements[0].name); + } if (sdef->xerUseOrderPossible) { size_t begin = start_at + num_attributes; /* first non-attribute */ @@ -2657,23 +2665,6 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) } } - if (sdef->xerEmbedValuesPossible) { /* EMBED-VALUES with USE-ORDER */ - src = mputprintf(src, - " if (p_td.xer_bits & EMBED_VALUES) {\n" - " field_%s.set_size(%lu);\n" - " %s::of_type empty_string(\"\");\n" - " for (int j_j=0; j_j<%lu; ++j_j) {\n" - " field_%s[j_j] = empty_string;\n" - " }\n" - " }\n" - , sdef->elements[0].name - , (unsigned long)(n_embed + 1) - , sdef->elements[0].type - , (unsigned long)(n_embed + 1) - , sdef->elements[0].name - ); - } - if (sdef->xerUseNilPossible) { /* USE-NIL and USE-ORDER */ src = mputprintf(src, " if (nil_attribute) field_%s.set_size(0);\n else" @@ -2684,18 +2675,26 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) " {\n" " field_%s.set_size(0);\n" " int e_val, num_seen = 0, *seen_f = new int[%lu];\n" - " for (int i=0; i < %lu; ++i) {\n" - " for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n" , sdef->elements[uo].name , (unsigned long)(n_embed) + ); + if (sdef->xerEmbedValuesPossible) { + // The index of the latest embedded value can change outside of this function + // (if the field is a untagged record of), in this case the next value should + // be ignored, as it's already been handled by the record of + src = mputstr(src, " int last_embval_index = 0;\n"); + } + src = mputprintf(src, + " for (int i=0; i < %lu; ++i) {\n" + " for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n" , (unsigned long)(n_embed)); if (sdef->xerEmbedValuesPossible) { /* read and store embedValues text if present */ src = mputprintf(src, - " if ((p_td.xer_bits & EMBED_VALUES) && (p_reader.NodeType()==XML_READER_TYPE_TEXT)) {\n" + " if (0 != emb_val && p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" - " field_%s[i] = emb_ustr;\n" + " field_%s[emb_val->embval_index] = emb_ustr;\n" " }\n" , sdef->elements[0].name); } @@ -2706,7 +2705,16 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) " }\n" " if (rd_ok != 1) break;\n" " const char * x_name = (const char*)p_reader.LocalName();\n" /* Name or LocalName ? */); - + + if (sdef->xerEmbedValuesPossible) { + src = mputstr(src, + " if (0 != emb_val) {\n" + " if (last_embval_index == emb_val->embval_index) {\n" + " ++emb_val->embval_index;\n" + " }\n" + " last_embval_index = emb_val->embval_index;\n" + " }\n"); + } /* * * * * code for USE-ORDER * * * * */ @@ -2716,20 +2724,20 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) src = mputprintf(src, " if (check_name(x_name, %s_xer_, 1)) {\n" " ec_1.set_msg(\"%s': \");\n" - " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor);\n" + " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor, %s);\n" , sdef->elements[i].typegen , sdef->elements[i].dispname - , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name: sdef->elements[i].name) , (sdef->xerUseNilPossible ? "()." : "") , (sdef->xerUseNilPossible ? sdef->elements[i].name : "") , (sdef->xerUseNilPossible ? "()" : "") , sdef->elements[i].typegen + , sdef->xerEmbedValuesPossible ? "emb_val" : "0" ); src = mputprintf(src, - " field_%s[i] = e_val = %s::of_type::%s;\n" - , sdef->elements[uo].name - , sdef->elements[uo].typegen, sdef->elements[i].name); + " field_%s[i] = e_val = %s::of_type::%s;\n" + , sdef->elements[uo].name + , sdef->elements[uo].typegen, sdef->elements[i].name); src = mputstr(src, " }\n else"); } } @@ -2753,7 +2761,7 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) " }\n" " if (!next_any) {\n" " ec_1.set_msg(\"%s': \");\n" - " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor);\n" + " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor, 0);\n" " field_%s[i] = e_val;\n" " any_found = true;\n" " }\n" @@ -2781,11 +2789,16 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) if (sdef->xerEmbedValuesPossible) { /* read and store embedValues text if present */ src = mputprintf(src, - " if ((p_td.xer_bits & EMBED_VALUES) && (p_reader.NodeType()==XML_READER_TYPE_TEXT)) {\n" - " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" - " field_%s[%lu] = emb_ustr;\n" + " if (0 != emb_val) {\n" + " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" + " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" + " field_%s[emb_val->embval_index] = emb_ustr;\n" + " }\n" + " if (last_embval_index == emb_val->embval_index) {\n" + " ++emb_val->embval_index;\n" + " }\n" " }\n" - , sdef->elements[0].name, (unsigned long)(n_embed)); + , sdef->elements[0].name); } src = mputprintf(src, @@ -2816,16 +2829,29 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) " p_reader.MoveToElement();\n" " } else {\n"); } + if (sdef->xerEmbedValuesPossible) { + // The index of the latest embedded value can change outside of this function + // (if the field is a untagged record of), in this case the next value should + // be ignored, as it's already been handled by the record of + // Omitted fields can also reset this value + src = mputstr(src, " int last_embval_index = 0;\n"); + } /* for all the non-attribute fields... */ for (i = start_at + num_attributes; i < sdef->nElements; ++i) { if (sdef->xerEmbedValuesPossible) { /* read and store embedValues text if present */ src = mputprintf(src, - " if ((p_td.xer_bits & EMBED_VALUES) && (p_reader.NodeType()==XML_READER_TYPE_TEXT)) {\n" - " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" - " field_%s[%lu] = emb_ustr;\n" + " if (0 != emb_val) {\n" + " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" + " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" + " field_%s[emb_val->embval_index] = emb_ustr;\n" + " }\n" + " if (last_embval_index == emb_val->embval_index) {\n" + " ++emb_val->embval_index;\n" + " }\n" + " last_embval_index = emb_val->embval_index;\n" " }\n" - , sdef->elements[0].name, (unsigned long)(i-(start_at+num_attributes))); + , sdef->elements[0].name); } /* The DEFAULT-FOR-EMPTY member can not be involved with EMBED-VALUES, * so we can use the same pattern: optional "if(...) else" before {} @@ -2860,69 +2886,59 @@ void gen_xer(const struct_def *sdef, char **pdef, char **psrc) src = mputprintf(src, " field_%s.XER_decode(%s_xer_, p_reader, p_flavor" - " | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : 0));\n" + " | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : 0), %s);\n" " }\n" - , sdef->elements[i].name, sdef->elements[i].typegen); + , sdef->elements[i].name, sdef->elements[i].typegen + , sdef->xerEmbedValuesPossible ? "emb_val" : "0"); + if (sdef->xerEmbedValuesPossible) { + src = mputprintf(src, + " if (!field_%s.is_present()) {\n" + // there was no new element, the last embedded value is for the next field + // (or the end of the record if this is the last field) + " last_embval_index = -1;\n" + " }\n" + , sdef->elements[i].name); + } } /* next field */ - if (sdef->xerUseNilPossible) { - src = mputstr(src, " } // use_nil\n"); - } - if (sdef->xerEmbedValuesPossible) { /* read and store embedValues text if present */ src = mputprintf(src, - " if ((p_td.xer_bits & EMBED_VALUES) && (p_reader.NodeType()==XML_READER_TYPE_TEXT)) {\n" - " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" - " field_%s[%lu] = emb_ustr;\n" + " if (0 != emb_val) {\n" + " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" + " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" + " field_%s[emb_val->embval_index] = emb_ustr;\n" + " }\n" + " if (last_embval_index == emb_val->embval_index) {\n" + " ++emb_val->embval_index;\n" + " }\n" " }\n" - , sdef->elements[0].name, (unsigned long)(i-(start_at+num_attributes))); + , sdef->elements[0].name); + } + + if (sdef->xerUseNilPossible) { + src = mputstr(src, " } // use_nil\n"); } + if (sdef->xerUseOrderPossible) { + src = mputstr(src, " } // uo\n"); + } + if (sdef->xerEmbedValuesPossible) { - size_t op; src = mputprintf(src, - /* Set the embed-values member to the correct nr of strings */ - " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" - " int exp_embed = %lu;\n" - , (unsigned long)max_embed - ); - - if (sdef->xerUseNilPossible) { - src = mputstr(src, - " if (nil_attribute) exp_embed = 0;\n" - " else {"); - } - - for (op = 0; op < sdef->nElements; ++op) { - if (sdef->elements[op].isOptional && !sdef->elements[op].xerAttribute) { - src = mputprintf(src, - " if (!field_%s.ispresent()) --exp_embed;\n" - , sdef->elements[op].name - ); - } - } - - if (sdef->xerUseNilPossible) src = mputstr(src, " }\n"); - - src = mputprintf(src, - " field_%s.set_size(exp_embed);//normal\n" + " if (0 != emb_val) {\n" " %s::of_type empty_string(\"\");\n" - " for (int j_j=0; j_jembval_index; ++j_j) {\n" " if (!field_%s[j_j].is_bound()) field_%s[j_j] = empty_string;\n" " }\n" - " }" - , sdef->elements[0].name + " delete emb_val;\n" + " }\n" , sdef->elements[0].type , sdef->elements[0].name , sdef->elements[0].name ); } - if (sdef->xerUseOrderPossible) { - src = mputstr(src, " } // uo\n"); - } - if (sdef->xerUseQName) { src = mputstr(src, " } // qn\n"); } @@ -5773,8 +5789,8 @@ static void defEmptyRecordClass(const struct_def *sdef, ); src = mputprintf(src, - "int %s::XER_encode(const XERdescriptor_t& p_td," - " TTCN_Buffer& p_buf, unsigned int p_flavor, int p_indent) const{\n" + "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, " + "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const{\n" " int encoded_length=(int)p_buf.get_len();\n" " int is_indented = !is_canonical(p_flavor);\n" " int e_xer = is_exer(p_flavor);\n" @@ -5791,7 +5807,7 @@ static void defEmptyRecordClass(const struct_def *sdef, "// written by %s in " __FILE__ " at %d\n" #endif "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, " - "unsigned int p_flavor)\n" + "unsigned int p_flavor, embed_values_dec_struct_t*)\n" "{\n" " int e_xer = is_exer(p_flavor);\n" " bound_flag = true;\n" diff --git a/compiler2/record_of.c b/compiler2/record_of.c index 0b76165..b820722 100644 --- a/compiler2/record_of.c +++ b/compiler2/record_of.c @@ -56,8 +56,6 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "int n_elements;\n" "%s **value_elements;\n" "} *val_ptr;\n" - "Vector refd_indices;\n" - "int max_refd_index;\n" #ifndef NDEBUG , __FUNCTION__, __LINE__ #endif @@ -98,63 +96,6 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "}\n" "}\n\n", name, name, dispname, name, dispname, name, name, name, name, name); } - - /* function that returns the actual number of elements */ - def = mputstr(def, "int get_nof_elements() const;\n"); - src = mputprintf(src, - "int %s::get_nof_elements() const\n" - "{\n" - " int nof_elements = (val_ptr != NULL) ? val_ptr->n_elements : 0;\n" - " if (!refd_indices.empty()) {\n" - " while (nof_elements > 0) {\n" - " if (is_elem_bound(nof_elements - 1)) {\n" - " break;\n" - " }\n" - " --nof_elements;\n" - " }\n" - " }\n" - " return nof_elements;\n" - "}\n\n", name); - - /* element boundness check function */ - def = mputstr(def, "bool is_elem_bound(int index) const;\n"); - src = mputprintf(src, - "bool %s::is_elem_bound(int index) const\n" - "{\n" - " return val_ptr->value_elements[index] != NULL &&\n" - " val_ptr->value_elements[index]->is_bound();\n" - "}\n\n", name); - - /* function that calculates and caches the maximum referenced index */ - def = mputstr(def, "int get_max_refd_index();\n"); - src = mputprintf(src, - "int %s::get_max_refd_index()\n" - "{\n" - " if (refd_indices.empty()) {\n" - " return -1;\n" - " }\n" - " if (-1 == max_refd_index) {\n" - " for (size_t i = 0; i < refd_indices.size(); ++i) {\n" - " if (refd_indices[i] > max_refd_index) {\n" - " max_refd_index = refd_indices[i];\n" - " }\n" - " }\n" - " }\n" - " return max_refd_index;\n" - "}\n\n", name); - - /* referenced index check function */ - def = mputstr(def, "bool is_index_refd(int index);\n"); - src = mputprintf(src, - "bool %s::is_index_refd(int index)\n" - "{\n" - " for (size_t i = 0; i < refd_indices.size(); ++i) {\n" - " if (index == refd_indices[i]) {\n" - " return true;\n" - " }\n" - " }\n" - " return false;\n" - "}\n\n", name); /* public member functions */ def = mputstr(def, "\npublic:\n"); @@ -166,7 +107,6 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "%s::%s()\n" "{\n" "val_ptr = NULL;\n" - "max_refd_index = -1;\n" "}\n\n", name, name); def = mputprintf(def, "%s(null_type other_value);\n", name); @@ -177,7 +117,6 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "val_ptr->ref_count = 1;\n" "val_ptr->n_elements = 0;\n" "val_ptr->value_elements = NULL;\n" - "max_refd_index = -1;\n" "}\n\n", name, name); /* copy constructor */ @@ -187,23 +126,9 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "{\n" "if (!other_value.is_bound()) " "TTCN_error(\"Copying an unbound value of type %s.\");\n" - "if (other_value.refd_indices.empty()) {\n" "val_ptr = other_value.val_ptr;\n" "val_ptr->ref_count++;\n" - "}\n" - "else {\n" - // there are references to at least one element => the array must be copied - "val_ptr = NULL;\n" - "int nof_elements = other_value.get_nof_elements();\n" - "set_size(nof_elements);\n" - "for (int i = 0; i < nof_elements; ++i) {\n" - "if (other_value.is_elem_bound(i)) {\n" - "val_ptr->value_elements[i] = new %s(*(other_value.val_ptr->value_elements[i]));\n" - "}\n" - "}\n" - "}\n" - "max_refd_index = -1;\n" - "}\n\n", name, name, name, dispname, type); + "}\n\n", name, name, name, dispname); /* destructor */ def = mputprintf(def, "~%s();\n\n", name); @@ -226,7 +151,6 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "val_ptr = NULL;\n" "}\n" "else if (val_ptr->ref_count == 1) {\n" - "if (refd_indices.empty()) {\n" "for (int elem_count = 0; elem_count < val_ptr->n_elements;\n" "elem_count++)\n" "if (val_ptr->value_elements[elem_count] != NULL)\n" @@ -235,10 +159,6 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "delete val_ptr;\n" "val_ptr = NULL;\n" "}\n" - "else {\n" - "set_size(0);\n" - "}\n" - "}\n" "else\n" "TTCN_error(\"Internal error: Invalid reference counter in a record " "of/set of value.\");\n" @@ -250,7 +170,11 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) src = mputprintf(src, "%s& %s::operator=(null_type)\n" "{\n" - "set_size(0);\n" + "clean_up();\n" + "val_ptr = new recordof_setof_struct;\n" + "val_ptr->ref_count = 1;\n" + "val_ptr->n_elements = 0;\n" + "val_ptr->value_elements = NULL;\n" "return *this;\n" "}\n\n", name, name); @@ -259,39 +183,15 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) src = mputprintf(src, "%s& %s::operator=(const %s& other_value)\n" "{\n" - "if (!other_value.is_bound()) " + "if (other_value.val_ptr == NULL) " "TTCN_error(\"Assigning an unbound value of type %s.\");\n" "if (this != &other_value) {\n" - "if (refd_indices.empty() && other_value.refd_indices.empty()) {\n" "clean_up();\n" "val_ptr = other_value.val_ptr;\n" "val_ptr->ref_count++;\n" "}\n" - "else {\n" - // there are references to at least one element => the array must be copied - "int nof_elements = other_value.get_nof_elements();\n" - "set_size(nof_elements);\n" - "for (int i = 0; i < nof_elements; ++i) {\n" - "if (other_value.is_elem_bound(i)) {\n" - "if (val_ptr->value_elements[i] == NULL) {\n" - "val_ptr->value_elements[i] = new %s;\n" - "}\n" - "*val_ptr->value_elements[i] = *other_value.val_ptr->value_elements[i];\n" - "}\n" - "else if (val_ptr->value_elements[i] != NULL) {\n" - "if (is_index_refd(i)) {\n" - "val_ptr->value_elements[i]->clean_up();\n" - "}\n" - "else {\n" - "delete val_ptr->value_elements[i];\n" - "val_ptr->value_elements[i] = NULL;\n" - "}\n" - "}\n" - "}\n" - "}\n" - "}\n" "return *this;\n" - "}\n\n", name, name, name, dispname, type); + "}\n\n", name, name, name, dispname); /* comparison operators */ def = mputstr(def, "boolean operator==(null_type other_value) const;\n"); @@ -301,7 +201,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "if (val_ptr == NULL)\n" "TTCN_error(\"The left operand of comparison is an unbound value of " "type %s.\");\n" - "return get_nof_elements() == 0 ;\n" + "return val_ptr->n_elements == 0 ;\n" "}\n\n", name, dispname); def = mputprintf(def, "boolean operator==(const %s& other_value) const;\n", @@ -319,22 +219,23 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) dispname, dispname); if (sdef->kind == SET_OF) { src = mputstr(src, - "return compare_set_of(this, get_nof_elements(), &other_value, " - "other_value.get_nof_elements(), compare_function);\n"); + "return compare_set_of(this, val_ptr->n_elements, &other_value, " + "(other_value.val_ptr)->n_elements, compare_function);\n"); } else { src = mputstr (src, - "if (get_nof_elements() != other_value.get_nof_elements())\n" + "if (val_ptr->n_elements != (other_value.val_ptr)->n_elements)\n" "return FALSE;\n" - "for (int elem_count = 0; elem_count < get_nof_elements(); elem_count++){\n" - "if (is_elem_bound(elem_count)){\n" - "if (other_value.is_elem_bound(elem_count)){\n" + "for (int elem_count = 0; elem_count < val_ptr->n_elements; elem_count++){\n" + "if (val_ptr->value_elements[elem_count] != NULL){\n" + "if ((other_value.val_ptr)->value_elements[elem_count] != NULL){\n" " if (*val_ptr->value_elements[elem_count] != " "*(other_value.val_ptr)->value_elements[elem_count]) " "return FALSE;\n" "} else return FALSE;\n" "} else {\n" - "if (other_value.is_elem_bound(elem_count)) return FALSE;\n" + "if ((other_value.val_ptr)->value_elements[elem_count] != NULL) " + "return FALSE;\n" "}\n" "}\n" "return TRUE;\n"); @@ -403,9 +304,9 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "TTCN_error(\"Accessing an element in an unbound value of type %s.\");\n" "if (index_value < 0) TTCN_error(\"Accessing an element of type %s " "using a negative index: %%d.\", index_value);\n" - "if (index_value >= get_nof_elements()) TTCN_error(\"Index overflow in " + "if (index_value >= val_ptr->n_elements) TTCN_error(\"Index overflow in " "a value of type %s: The index is %%d, but the value has only %%d " - "elements.\", index_value, get_nof_elements());\n" + "elements.\", index_value, val_ptr->n_elements);\n" "return (val_ptr->value_elements[index_value] != NULL) ?\n" "*val_ptr->value_elements[index_value] : UNBOUND_ELEM;\n" "}\n\n", type, name, dispname, dispname, dispname); @@ -449,17 +350,16 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "if (val_ptr == NULL) " "TTCN_error(\"Performing rotation operation on an unbound value of type " "%s.\");\n" - "int nof_elements = get_nof_elements();\n" - "if (nof_elements == 0) return *this;\n" + "if (val_ptr->n_elements == 0) return *this;\n" "int rc;\n" - "if (rotate_count>=0) rc = rotate_count %% nof_elements;\n" - "else rc = nof_elements - ((-rotate_count) %% nof_elements);\n" + "if (rotate_count>=0) rc = rotate_count %% val_ptr->n_elements;\n" + "else rc = val_ptr->n_elements - ((-rotate_count) %% val_ptr->n_elements);\n" "if (rc == 0) return *this;\n" "%s ret_val;\n" - "ret_val.set_size(nof_elements);\n" - "for (int i=0; ivalue_elements[(i+rc)%%nof_elements] =" + "ret_val.set_size(val_ptr->n_elements);\n" + "for (int i=0; in_elements; i++) {\n" + "if (val_ptr->value_elements[i] != NULL) {\n" + "ret_val.val_ptr->value_elements[(i+rc)%%val_ptr->n_elements] =" "new %s(*val_ptr->value_elements[i]);\n" "}\n" "}\n" @@ -475,20 +375,18 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "{\n" "if (val_ptr == NULL || other_value.val_ptr == NULL) " "TTCN_error(\"Unbound operand of %s concatenation.\");\n" - "int nof_elements = get_nof_elements();\n" - "if (nof_elements == 0) return other_value;\n" - "int other_value_nof_elements = other_value.get_nof_elements();" - "if (other_value_nof_elements == 0) return *this;\n" + "if (val_ptr->n_elements == 0) return other_value;\n" + "if (other_value.val_ptr->n_elements == 0) return *this;\n" "%s ret_val;\n" - "ret_val.set_size(nof_elements + other_value_nof_elements);\n" - "for (int i=0; in_elements+other_value.val_ptr->n_elements);\n" + "for (int i=0; in_elements; i++) {\n" + "if (val_ptr->value_elements[i] != NULL) {\n" "ret_val.val_ptr->value_elements[i] = new %s(*val_ptr->value_elements[i]);\n" "}\n" "}\n" - "for (int i=0; ivalue_elements[i + nof_elements] = " + "for (int i=0; in_elements; i++) {\n" + "if (other_value.val_ptr->value_elements[i] != NULL) {\n" + "ret_val.val_ptr->value_elements[i+val_ptr->n_elements] = " "new %s(*other_value.val_ptr->value_elements[i]);\n" "}\n" "}\n" @@ -504,12 +402,12 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "if (val_ptr == NULL) " "TTCN_error(\"The first argument of substr() is an unbound value of " "type %s.\");\n" - "check_substr_arguments(get_nof_elements(), index, returncount, " + "check_substr_arguments(val_ptr->n_elements, index, returncount, " "\"%s\",\"element\");\n" "%s ret_val;\n" "ret_val.set_size(returncount);\n" "for (int i=0; ivalue_elements[i+index] != NULL) {\n" "ret_val.val_ptr->value_elements[i] = " "new %s(*val_ptr->value_elements[i+index]);\n" "}\n" @@ -529,26 +427,24 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "if (repl.val_ptr == NULL) " "TTCN_error(\"The fourth argument of replace() is an unbound value of " "type %s.\");\n" - "int nof_elements = get_nof_elements();\n" - "check_replace_arguments(nof_elements, index, len, " + "check_replace_arguments(val_ptr->n_elements, index, len, " "\"%s\",\"element\");\n" "%s ret_val;\n" - "int repl_nof_elements = repl.get_nof_elements();\n" - "ret_val.set_size(nof_elements + repl_nof_elements - len);\n" + "ret_val.set_size(val_ptr->n_elements + repl.val_ptr->n_elements - len);\n" "for (int i = 0; i < index; i++) {\n" - "if (is_elem_bound(i)) {\n" + "if (val_ptr->value_elements[i] != NULL) {\n" "ret_val.val_ptr->value_elements[i] = new %s(*val_ptr->value_elements[i]);\n" "}\n" "}\n" - "for (int i = 0; i < repl_nof_elements; i++) {\n" - "if (repl.is_elem_bound(i)) {\n" + "for (int i = 0; i < repl.val_ptr->n_elements; i++) {\n" + "if (repl.val_ptr->value_elements[i] != NULL) {\n" "ret_val.val_ptr->value_elements[i+index] = " "new %s(*repl.val_ptr->value_elements[i]);\n" "}\n" "}\n" - "for (int i = 0; i < nof_elements - index - len; i++) {\n" - "if (is_elem_bound(index+i+len)) {\n" - "ret_val.val_ptr->value_elements[index+i+repl_nof_elements] = " + "for (int i = 0; i < val_ptr->n_elements - index - len; i++) {\n" + "if (val_ptr->value_elements[index+i+len] != NULL) {\n" + "ret_val.val_ptr->value_elements[index+i+repl.val_ptr->n_elements] = " "new %s(*val_ptr->value_elements[index+i+len]);\n" "}\n" "}\n" @@ -604,40 +500,19 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "val_ptr->n_elements = new_size;\n" "} else if (new_size < val_ptr->n_elements) {\n" "for (int elem_count = new_size; elem_count < val_ptr->n_elements; " - "elem_count++) {\n" - "if (val_ptr->value_elements[elem_count] != NULL) {\n" - "if (is_index_refd(elem_count)) {\n" - "val_ptr->value_elements[elem_count]->clean_up();\n" - "}\n" - "else {\n" + "elem_count++)\n" + "if (val_ptr->value_elements[elem_count] != NULL)" "delete val_ptr->value_elements[elem_count];\n" - "val_ptr->value_elements[elem_count] = 0;\n" - "}\n" - "}\n" - "}\n" - "if (new_size <= get_max_refd_index()) {\n" - "new_size = get_max_refd_index() + 1;\n" - "}\n" - "if (new_size < val_ptr->n_elements) {\n" "val_ptr->value_elements = (%s**)" "reallocate_pointers((void**)val_ptr->value_elements, " "val_ptr->n_elements, new_size);\n" "val_ptr->n_elements = new_size;\n" "}\n" - "}\n" "}\n\n", name, dispname, type, type, type, dispname, type); /* is_bound function */ def = mputstr(def, - "boolean is_bound() const;\n"); - src = mputprintf(src, - "boolean %s::is_bound() const\n" - "{\n" - "if (refd_indices.empty()) {\n" - "return (val_ptr != NULL);\n" - "}\n" - "return (get_nof_elements() != 0);\n" - "}\n\n", name); + "inline boolean is_bound() const {return val_ptr != NULL; }\n"); /* is_present function */ def = mputstr(def, @@ -650,8 +525,8 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "boolean %s::is_value() const\n" "{\n" "if (val_ptr == NULL) return false;\n" - "for(int i = 0; i < get_nof_elements(); ++i) {\n" - "if (!is_elem_bound(i) || " + "for(int i = 0; i < val_ptr->n_elements; ++i) {\n" + "if (val_ptr->value_elements[i] == NULL || " "!val_ptr->value_elements[i]->is_value()) return FALSE;\n" "}\n" "return TRUE;\n" @@ -667,7 +542,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "if (val_ptr == NULL) " "TTCN_error(\"Performing sizeof operation on an unbound value of type " "%s.\");\n" - "return get_nof_elements();\n" + "return val_ptr->n_elements;\n" "}\n\n", name, dispname); /* lengthof operation */ @@ -678,8 +553,8 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "if (val_ptr == NULL) " "TTCN_error(\"Performing lengthof operation on an unbound value of type " "%s.\");\n" - "for (int my_length=get_nof_elements(); my_length>0; my_length--) " - "if (is_elem_bound(my_length-1)) return my_length;\n" + "for (int my_length=val_ptr->n_elements; my_length>0; my_length--) " + "if (val_ptr->value_elements[my_length-1] != NULL) return my_length;\n" "return 0;\n" "}\n\n", name, dispname); @@ -693,13 +568,13 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "TTCN_Logger::log_event_unbound();\n" "return;\n" "}\n" - "switch (get_nof_elements()) {\n" + "switch (val_ptr->n_elements) {\n" "case 0:\n" "TTCN_Logger::log_event_str(\"{ }\");\n" "break;\n" "default:\n" "TTCN_Logger::log_event_str(\"{ \");\n" - "for (int elem_count = 0; elem_count < get_nof_elements(); " + "for (int elem_count = 0; elem_count < val_ptr->n_elements; " "elem_count++) {\n" "if (elem_count > 0) TTCN_Logger::log_event_str(\", \");\n" "(*this)[elem_count].log();\n" @@ -786,35 +661,9 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) src = mputprintf(src, "void %s::set_implicit_omit()\n{\n" "if (val_ptr == NULL) return;\n" - "for (int i = 0; i < get_nof_elements(); i++) {\n" - "if (is_elem_bound(i)) val_ptr->value_elements[i]->set_implicit_omit();\n" + "for (int i = 0; i < val_ptr->n_elements; i++) {\n" + "if (val_ptr->value_elements[i] != NULL) val_ptr->value_elements[i]->set_implicit_omit();\n" "}\n}\n\n", name); - - /* functions for inserting and removing references to elements of the record of */ - def = mputstr(def, " void add_refd_index(int index);\n"); - src = mputprintf(src, - "void %s::add_refd_index(int index)\n" - "{\n" - " refd_indices.push_back(index);\n" - " if (index > get_max_refd_index()) {\n" - " max_refd_index = index;\n" - " }\n" - "}\n\n", name); - - def = mputstr(def, " void remove_refd_index(int index);\n"); - src = mputprintf(src, - "void %s::remove_refd_index(int index)\n" - "{\n" - " for (size_t i = refd_indices.size(); i > 0; --i) {\n" - " if (refd_indices[i - 1] == index) {\n" - " refd_indices.erase_at(i - 1);\n" - " break;\n" - " }\n" - " }\n" - " if (get_max_refd_index() == index) {\n" - " max_refd_index = -1;\n" - " }\n" - "}\n\n", name); /* encoding / decoding functions */ def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); @@ -823,8 +672,8 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "{\n" "if (val_ptr == NULL) " "TTCN_error(\"Text encoder: Encoding an unbound value of type %s.\");\n" - "text_buf.push_int(get_nof_elements());\n" - "for (int elem_count = 0; elem_count < get_nof_elements(); " + "text_buf.push_int(val_ptr->n_elements);\n" + "for (int elem_count = 0; elem_count < val_ptr->n_elements; " "elem_count++)\n" "(*this)[elem_count].encode_text(text_buf);\n" "}\n\n", name, dispname); @@ -833,18 +682,19 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) src = mputprintf(src, "void %s::decode_text(Text_Buf& text_buf)\n" "{\n" - "int new_size = text_buf.pull_int().get_val();\n" - "if (new_size < 0)\n TTCN_error(\"Text decoder: Negative size " + "clean_up();\n" + "val_ptr = new recordof_setof_struct;\n" + "val_ptr->ref_count = 1;\n" + "val_ptr->n_elements = text_buf.pull_int().get_val();\n" + "if (val_ptr->n_elements < 0) TTCN_error(\"Text decoder: Negative size " "was received for a value of type %s.\");\n" - "set_size(new_size);\n" - "for (int elem_count = 0; elem_count < new_size; " + "val_ptr->value_elements = (%s**)allocate_pointers(val_ptr->n_elements);\n" + "for (int elem_count = 0; elem_count < val_ptr->n_elements; " "elem_count++) {\n" - "if (val_ptr->value_elements[elem_count] == NULL) {\n" "val_ptr->value_elements[elem_count] = new %s;\n" - "}\n" "val_ptr->value_elements[elem_count]->decode_text(text_buf);\n" "}\n" - "}\n\n", name, dispname, type); + "}\n\n", name, dispname, type, type); if(ber_needed || raw_needed || text_needed || xer_needed || json_needed) def_encdec(name, &def, &src, ber_needed, raw_needed, text_needed, @@ -868,7 +718,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " }\n" " return encoded_length;\n" " }\n" - " for(int a=0;an_elements;a++){\n" " if(a!=0 && p_td.text->separator_encode){\n" " p_buf.put_cs(*p_td.text->separator_encode);\n" " encoded_length+=p_td.text->separator_encode->lengthof();\n" @@ -914,9 +764,13 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " ml++;\n" " }\n" " if(first_call) {\n" - " set_size(0);\n" + " clean_up();\n" + " val_ptr=new recordof_setof_struct;\n" + " val_ptr->ref_count=1;\n" + " val_ptr->n_elements=0;\n" + " val_ptr->value_elements=NULL;\n" " }\n" - " int more=get_nof_elements();\n" + " int more=val_ptr->n_elements;\n" " while(TRUE){\n" " %s *val=new %s;\n" " pos=p_buf.get_pos();\n" @@ -931,17 +785,11 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " break;\n" " }\n" " sep_found=FALSE;\n" - " if (refd_indices.empty()) {\n" - " val_ptr->value_elements = (%s**)reallocate_pointers" + " val_ptr->value_elements = (%s**)reallocate_pointers" "((void**)val_ptr->value_elements, val_ptr->n_elements, " "val_ptr->n_elements + 1);\n" - " val_ptr->value_elements[val_ptr->n_elements]=val;\n" - " val_ptr->n_elements++;\n" - " }\n" - " else {\n" - " (*this)[get_nof_elements()] = *val;\n" - " delete val;\n" - " }\n" + " val_ptr->value_elements[val_ptr->n_elements]=val;\n" + " val_ptr->n_elements++;\n" " decoded_length+=len;\n" " if(p_td.text->separator_decode){\n" " int tl;\n" @@ -977,7 +825,9 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n" " if(no_err){" " if(!first_call){\n" - " set_size(more);\n" + " for(int a=more; an_elements; a++) " + "delete val_ptr->value_elements[a];\n" + " val_ptr->n_elements=more;\n" " }\n" " return -1;\n" " }\n" @@ -990,7 +840,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " decoded_length+=tl;\n" " p_buf.increase_pos(tl);\n" " }\n" - " if(get_nof_elements()==0){\n" + " if(val_ptr->n_elements==0){\n" " if(!(p_td.text->end_decode || p_td.text->begin_decode)) {\n" " if(no_err)return -1;\n" " TTCN_EncDec_ErrorContext::error" @@ -998,7 +848,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " return decoded_length;\n" " }\n" " }\n" - " if(!first_call && more==get_nof_elements() && " + " if(!first_call && more==val_ptr->n_elements && " "!(p_td.text->end_decode || p_td.text->begin_decode)) return -1;\n" " return decoded_length;\n" "}\n" @@ -1018,7 +868,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " if(!new_tlv) {\n" " new_tlv=ASN_BER_TLV_t::construct(NULL);\n" " TTCN_EncDec_ErrorContext ec;\n" - " for(int elem_i=0; elem_in_elements; elem_i++) {\n" " ec.set_msg(\"Component #%%d: \", elem_i);\n" " new_tlv->add_TLV((*this)[elem_i].BER_encode_TLV" "(%s_descr_, p_coding));\n" @@ -1039,23 +889,32 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%%s' type: \"," " p_td.name);\n" " stripped_tlv.chk_constructed_flag(TRUE);\n" - " set_size(0);\n" + " clean_up();\n" + " val_ptr = new recordof_setof_struct;\n" + " val_ptr->ref_count = 1;\n" + " val_ptr->n_elements = 0;\n" + " val_ptr->value_elements = NULL;\n" " size_t V_pos=0;\n" " ASN_BER_TLV_t tmp_tlv;\n" " TTCN_EncDec_ErrorContext ec_1(\"Component #\");\n" " TTCN_EncDec_ErrorContext ec_2(\"0: \");\n" " while(BER_decode_constdTLV_next(stripped_tlv, V_pos, L_form, " "tmp_tlv)) {\n" - " (*this)[get_nof_elements()].BER_decode_TLV(%s_descr_, tmp_tlv, " + " val_ptr->value_elements = (%s**)reallocate_pointers(" + "(void**)val_ptr->value_elements, val_ptr->n_elements, " + "val_ptr->n_elements + 1);\n" + " val_ptr->n_elements++;\n" + " val_ptr->value_elements[val_ptr->n_elements - 1] = new %s;\n" + " val_ptr->value_elements[val_ptr->n_elements - 1]->BER_decode_TLV(%s_descr_, tmp_tlv, " "L_form);\n" - " ec_2.set_msg(\"%%d: \", get_nof_elements());\n" + " ec_2.set_msg(\"%%d: \", val_ptr->n_elements);\n" " }\n" " return TRUE;\n" "}\n" "\n" , name, sdef->oftypedescrname , sdef->kind==SET_OF?" new_tlv->sort_tlvs();\n":"" - , name, sdef->oftypedescrname + , name, type, type, sdef->oftypedescrname ); if(sdef->has_opentypes) { @@ -1072,9 +931,9 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " p_typelist.push(this);\n" " TTCN_EncDec_ErrorContext ec_0(\"Component #\");\n" " TTCN_EncDec_ErrorContext ec_1;\n" - " for(int elem_i=0; elem_in_elements; elem_i++) {\n" " ec_1.set_msg(\"%%d: \", elem_i);\n" - " (*this)[elem_i].BER_decode_opentypes(p_typelist," + " val_ptr->value_elements[elem_i]->BER_decode_opentypes(p_typelist," " L_form);\n" " }\n" " p_typelist.pop();\n" @@ -1096,9 +955,13 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " int decoded_field_length=0;\n" " size_t start_of_field=0;\n" " if(first_call) {\n" - " set_size(0);\n" + " clean_up();\n" + " val_ptr=new recordof_setof_struct;\n" + " val_ptr->ref_count=1;\n" + " val_ptr->n_elements=0;\n" + " val_ptr->value_elements=NULL;\n" " }\n" - " int start_field=get_nof_elements();\n" + " int start_field=val_ptr->n_elements;\n" " if(p_td.raw->fieldlength || sel_field!=-1){\n" " int a=0;\n" " if(sel_field==-1) sel_field=p_td.raw->fieldlength;\n" @@ -1109,10 +972,12 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " decoded_length+=decoded_field_length;\n" " limit-=decoded_field_length;\n" " }\n" + " if(a==0) val_ptr->n_elements=0;\n" " } else {\n" " int a=start_field;\n" " if(limit==0){\n" " if(!first_call) return -1;\n" + " val_ptr->n_elements=0;\n" " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)" "+prepaddlength;\n" " }\n" @@ -1121,7 +986,8 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " decoded_field_length=(*this)[a].RAW_decode(%s_descr_,p_buf,limit," "top_bit_ord,TRUE);\n" " if(decoded_field_length < 0){\n" - " set_size(get_nof_elements() - 1);\n" + " delete &(*this)[a];\n" + " val_ptr->n_elements--;\n" " p_buf.set_pos_bit(start_of_field);\n" " if(a>start_field){\n" " return decoded_length+p_buf.increase_pos_padd(p_td.raw->padding)" @@ -1149,8 +1015,8 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "RAW_enc_tree& myleaf) const{\n" " int encoded_length=0;\n" " int encoded_num_of_records=p_td.raw->fieldlength?" - "smaller(get_nof_elements(), p_td.raw->fieldlength)" - ":get_nof_elements();\n" + "smaller(val_ptr->n_elements, p_td.raw->fieldlength)" + ":val_ptr->n_elements;\n" " myleaf.isleaf=FALSE;\n" " myleaf.rec_of=TRUE;\n" " myleaf.body.node.num_of_nodes=encoded_num_of_records;\n" @@ -1215,7 +1081,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " if (val_ptr) try {\n" " char **new_ns;\n" " size_t num_new;\n" - " for (int i = 0; i < get_nof_elements(); ++i) {\n" + " for (int i = 0; i < val_ptr->n_elements; ++i) {\n" " bool def_ns_1 = false;" " new_ns = (*this)[i].collect_ns(%s_xer_, num_new, def_ns_1);\n" " merge_ns(collected_ns, num_collected, new_ns, num_new);\n" @@ -1235,8 +1101,8 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) , name, sdef->oftypedescrname); src=mputprintf(src, - "int %s::XER_encode(const XERdescriptor_t& p_td," - " TTCN_Buffer& p_buf, unsigned int p_flavor, int p_indent) const\n{\n" + "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, " + "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t* emb_val) const\n{\n" " if (val_ptr == 0) TTCN_error(\"Attempt to XER-encode an unbound record of\");\n" /* TODO type name */ " int encoded_length=(int)p_buf.get_len();\n" " boolean e_xer = is_exer(p_flavor);\n" @@ -1244,8 +1110,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " || (p_flavor & USE_TYPE_ATTR)));\n" " boolean indenting = !is_canonical(p_flavor) && own_tag;\n" "%s" /* Factor out p_indent if not attribute */ - " int nof_elements = get_nof_elements();\n" - " if (nof_elements==0) {\n" /* Empty record of */ + " if (val_ptr->n_elements==0) {\n" /* Empty record of */ , name , sdef->xerAttribute ? "" : " if (indenting) do_indent(p_buf, p_indent);\n" ); @@ -1298,9 +1163,9 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " unsigned char saved[4];\n" " memcpy(saved, buf_data + (buf_len - shorter), shorter);\n" " p_buf.increase_length(-shorter);\n" - " for (int i = 0; i < nof_elements; ++i) {\n" + " for (int i = 0; i < val_ptr->n_elements; ++i) {\n" " TTCN_EncDec_ErrorContext ec_0(\"Attribute %d: \", i);\n" - " if (!is_elem_bound(i)) {\n" + " if (val_ptr->value_elements[i] == NULL) {\n" " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" " \"Encoding an unbound universal charstring value.\");\n" " continue;\n" @@ -1330,7 +1195,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " p_buf.put_s(ns_len, (const unsigned char*)ns);\n" " UNIVERSAL_CHARSTRING before(sp_at, (const universal_char*)(*val_ptr->value_elements[i]));\n" - " before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent);\n" + " before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n" // Ensure the namespace abides to its restrictions " if (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n" " TTCN_Buffer ns_buf;\n" @@ -1358,7 +1223,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " }\n" " UNIVERSAL_CHARSTRING after(len - j, (const universal_char*)(*val_ptr->value_elements[i]) + j);\n" - " after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent);\n" + " after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n" // Put this attribute in a dummy element and walk through it to check its validity " TTCN_Buffer check_buf;\n" " check_buf.put_s(2, (unsigned char*)\"n_elements; ++i) {\n" + /*" if (i > 0 && !own_tag && 0 != emb_val &&\n" + " emb_val->embval_index < emb_val->embval_size) {\n" + " emb_val->embval_array->get_embedded_value(emb_val->embval_index).XER_encode(\n" + " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" + " ++emb_val->embval_index;\n" + " }\n" - temporarily removed in RT1 */ " ec_1.set_msg(\"%%d: \", i);\n" " if (e_xer && (p_td.xer_bits & XER_LIST) && i>0) p_buf.put_c(' ');\n" - " (*this)[i].XER_encode(%s_xer_, p_buf, p_flavor, p_indent+own_tag);\n" + " (*this)[i].XER_encode(%s_xer_, p_buf, p_flavor, p_indent+own_tag, emb_val);\n" " }\n" " if (indenting && !is_exerlist(p_flavor)) {\n", sdef->oftypedescrname @@ -1453,7 +1324,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "// written by %s in " __FILE__ " at %d\n" #endif "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, " - "unsigned int p_flavor)\n{\n" + "unsigned int p_flavor, embed_values_dec_struct_t* emb_val)\n{\n" " boolean e_xer = is_exer(p_flavor);\n" " int xerbits = p_td.xer_bits;\n" " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n" @@ -1462,7 +1333,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) /* not toplevel anymore and remove the flags for USE-UNION the oftype doesn't need them */ " p_flavor &= ~XER_TOPLEVEL & ~XER_LIST & ~USE_TYPE_ATTR;\n" " int rd_ok=1, xml_depth=-1;\n" - " set_size(0);\n" /* empty but initialized array */ + " *this = NULL_VALUE;\n" /* empty but initialized array */ " int type = 0;\n" /* none */ " if (own_tag) for (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n" " type = p_reader.NodeType();\n" @@ -1530,14 +1401,14 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) /* Don't move to the #text, that's the callee's responsibility. */ /* The call to the non-const operator[] creates a new element object, * then we call its XER_decode with the temporary XML reader. */ - " (*this)[get_nof_elements()].XER_decode(%s_xer_, reader_2, p_flavor);\n" - " if (p_flavor & EXIT_ON_ERROR && !(*this)[get_nof_elements() - 1].is_bound()) {\n" - " if (1 == get_nof_elements()) {\n" + " (*this)[val_ptr->n_elements].XER_decode(%s_xer_, reader_2, p_flavor, 0);\n" + " if (p_flavor & EXIT_ON_ERROR && !(*this)[val_ptr->n_elements - 1].is_bound()) {\n" + " if (1 == val_ptr->n_elements) {\n" // Failed to decode even the first element " clean_up();\n" " } else {\n" // Some elements were successfully decoded -> only delete the last one - " set_size(get_nof_elements() - 1);\n" + " set_size(val_ptr->n_elements - 1);\n" " }\n" " xmlFree(x_val);\n" " return -1;\n" @@ -1580,7 +1451,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) * for the element type (a string), so behave like a record-of * (string with ANY-ELEMENT): call the non-const operator[] * to create a new element, then read the entire XML element into it. */ - " (*this)[get_nof_elements()] = (const char*)p_reader.ReadOuterXml();\n" + " (*this)[val_ptr->n_elements] = (const char*)p_reader.ReadOuterXml();\n" /* Consume the element, then move ahead */ " for (rd_ok = p_reader.Read(); rd_ok == 1 && p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) {}\n" " if (p_reader.NodeType() != XML_READER_TYPE_ELEMENT) rd_ok = p_reader.Read();\n" @@ -1596,7 +1467,10 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " break;\n" " }\n" /* The call to the non-const operator[] creates the element */ - " (*this)[get_nof_elements()].XER_decode(%s_xer_, p_reader, p_flavor);\n" + " (*this)[val_ptr->n_elements].XER_decode(%s_xer_, p_reader, p_flavor, emb_val);\n" + " if (0 != emb_val && !own_tag && val_ptr->n_elements > 1) {\n" + " ++emb_val->embval_index;\n" + " }\n" " }\n" " }\n" " else if (XML_READER_TYPE_END_ELEMENT == type) {\n" @@ -1607,6 +1481,11 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " }\n" " break;\n" " }\n" + /*" else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && get_nof_elements() > 0) {\n" + " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" + " emb_val->embval_array->set_embedded_value(emb_val->embval_index, emb_ustr);\n" + " rd_ok = p_reader.Read();\n" + " }\n" - temporarily removed in RT1 */ " else {\n" " rd_ok = p_reader.Read();\n" " }\n" @@ -1629,7 +1508,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " return -1;\n" " }\n\n" " int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);\n" - " for(int i = 0; i < get_nof_elements(); ++i) {\n" + " for(int i = 0; i < val_ptr->n_elements; ++i) {\n" " int ret_val = (*this)[i].JSON_encode(%s_descr_, p_tok);\n" " if (0 > ret_val) break;\n" " enc_len += ret_val;\n" @@ -1669,17 +1548,11 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) " }\n" " return JSON_ERROR_FATAL;\n" " }\n" - " if (refd_indices.empty()) {\n" - " val_ptr->value_elements = (%s**)reallocate_pointers(\n" - " (void**)val_ptr->value_elements, val_ptr->n_elements, val_ptr->n_elements + 1);\n" - " val_ptr->value_elements[val_ptr->n_elements] = val;\n" - " val_ptr->n_elements++;\n" - " dec_len += ret_val;\n" - " }\n" - " else {\n" - " (*this)[get_nof_elements()] = *val;\n" - " delete val;\n" - " }\n" + " val_ptr->value_elements = (%s**)reallocate_pointers(\n" + " (void**)val_ptr->value_elements, val_ptr->n_elements, val_ptr->n_elements + 1);\n" + " val_ptr->value_elements[val_ptr->n_elements] = val;\n" + " val_ptr->n_elements++;\n" + " dec_len += ret_val;\n" " }\n\n" " dec_len += p_tok.get_next_token(&token, NULL, NULL);\n" " if (JSON_TOKEN_ARRAY_END != token) {\n" @@ -1714,7 +1587,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "if (other_value.val_ptr == NULL)\n" "TTCN_error(\"The right operand of comparison is an unbound value of " "type %s.\");\n" - "return other_value.get_nof_elements() == 0;\n" + "return other_value.val_ptr->n_elements == 0;\n" "}\n\n", name, dispname); output->header.function_prototypes = @@ -2657,8 +2530,8 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct , name, sdef->oftypedescrname); src=mputprintf(src, - "int %s::XER_encode(const XERdescriptor_t& p_td," - " TTCN_Buffer& p_buf, unsigned int p_flavor, int p_indent) const\n{\n" + "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, " + "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t* emb_val) const\n{\n" " if (n_elements==-1) TTCN_error(\"Attempt to XER-encode an unbound record of\");\n" /* TODO type name */ " int encoded_length=(int)p_buf.get_len();\n" " boolean e_xer = is_exer(p_flavor);\n" @@ -2746,7 +2619,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct " p_buf.put_s(ns_len, (const unsigned char*)ns);\n" " UNIVERSAL_CHARSTRING before(sp_at, (const universal_char*)(value_elements[i]));\n" - " before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent);\n" + " before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n" // Ensure the namespace abides to its restrictions " if (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n" " TTCN_Buffer ns_buf;\n" @@ -2774,7 +2647,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct " }\n" " UNIVERSAL_CHARSTRING after(len - j, (const universal_char*)(value_elements[i]) + j);\n" - " after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent);\n" + " after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n" // Put this attribute in a dummy element and walk through it to check its validity " TTCN_Buffer check_buf;\n" " check_buf.put_s(2, (unsigned char*)\" 0 && !own_tag && 0 != emb_val &&\n" + " emb_val->embval_index < emb_val->embval_size) {\n" + " emb_val->embval_array->get_embedded_value(emb_val->embval_index).XER_encode(\n" + " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" + " ++emb_val->embval_index;\n" + " }\n" - temporarily removed in RT1 */ " ec_1.set_msg(\"%%d: \", i);\n" " if (e_xer && (p_td.xer_bits & XER_LIST) && i>0) p_buf.put_c(' ');\n" - " value_elements[i].XER_encode(%s_xer_, p_buf, p_flavor, p_indent+own_tag);\n" + " value_elements[i].XER_encode(%s_xer_, p_buf, p_flavor, p_indent+own_tag, emb_val);\n" " }\n" " if (indenting && !is_exerlist(p_flavor)) {\n", sdef->oftypedescrname @@ -2869,7 +2748,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct "// written by %s in " __FILE__ " at %d\n" #endif "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, " - "unsigned int p_flavor)\n{\n" + "unsigned int p_flavor, embed_values_dec_struct_t* emb_val)\n{\n" " boolean e_xer = is_exer(p_flavor);\n" " int xerbits = p_td.xer_bits;\n" " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n" @@ -2946,7 +2825,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct /* Don't move to the #text, that's the callee's responsibility. */ /* The call to the non-const operator[] creates a new element object, * then we call its XER_decode with the temporary XML reader. */ - " (*this)[n_elements].XER_decode(%s_xer_, reader_2, p_flavor);\n" + " (*this)[n_elements].XER_decode(%s_xer_, reader_2, p_flavor, 0);\n" " if (p_flavor & EXIT_ON_ERROR && !(*this)[n_elements - 1].is_bound()) {\n" " if (1 == n_elements) {\n" // Failed to decode even the first element @@ -3012,7 +2891,10 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct " break;\n" " }\n" /* The call to the non-const operator[] creates the element */ - " operator [](n_elements).XER_decode(%s_xer_, p_reader, p_flavor);\n" + " operator [](n_elements).XER_decode(%s_xer_, p_reader, p_flavor, emb_val);\n" + " if (0 != emb_val && !own_tag && n_elements > 1) {\n" + " ++emb_val->embval_index;\n" + " }\n" " }\n" " }\n" " else if (XML_READER_TYPE_END_ELEMENT == type) {\n" @@ -3023,6 +2905,11 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct " }\n" " break;\n" " }\n" + /*" else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && n_elements > 0) {\n" + " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" + " emb_val->embval_array->set_embedded_value(emb_val->embval_index, emb_ustr);\n" + " rd_ok = p_reader.Read();\n" + " }\n" - temporarily removed in RT1 */ " else {\n" " rd_ok = p_reader.Read();\n" " }\n" @@ -3099,11 +2986,6 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct "}\n\n" , name, type, sdef->oftypedescrname); } - - /* functions for keeping track of referenced indices (only implemented for regular record of class) */ - def = mputstr(def, - "void add_refd_index(int) {}\n" - "void remove_refd_index(int) {}\n\n"); /* end of class */ def = mputstr(def, "};\n\n"); diff --git a/compiler2/subtype.cc b/compiler2/subtype.cc index d59cf5c..29b0232 100644 --- a/compiler2/subtype.cc +++ b/compiler2/subtype.cc @@ -1241,6 +1241,30 @@ bool SubtypeConstraint::is_length_compatible(const SubtypeConstraint *p_st) cons return ((*length_restriction * *(p_st->length_restriction)).is_empty()!=TTRUE); } +bool SubtypeConstraint::is_upper_limit_infinity() const +{ + if (ST_INTEGER == subtype && integer_st) { + return integer_st->is_upper_limit_infinity(); + } + if (ST_FLOAT == subtype && float_st) { + return float_st->is_upper_limit_infinity(); + } + return false; +} + +bool SubtypeConstraint::is_lower_limit_infinity() const +{ + if (ST_INTEGER == subtype && integer_st) { + return integer_st->is_lower_limit_infinity(); + } + + if (ST_FLOAT == subtype && float_st) { + return float_st->is_lower_limit_infinity(); + } + return false; +} + + void SubtypeConstraint::except(const SubtypeConstraint* other) { if (other==NULL) FATAL_ERROR("SubtypeConstraint::except()"); diff --git a/compiler2/subtype.hh b/compiler2/subtype.hh index a9618aa..f7fde1a 100644 --- a/compiler2/subtype.hh +++ b/compiler2/subtype.hh @@ -199,6 +199,8 @@ public: bool is_compatible_with_elem() const; // used to check compatibility of structured types bool is_length_compatible(const SubtypeConstraint *p_st) const; + bool is_upper_limit_infinity() const; + bool is_lower_limit_infinity() const; }; /** diff --git a/compiler2/subtypestuff.cc b/compiler2/subtypestuff.cc index 02adf32..bc18d92 100644 --- a/compiler2/subtypestuff.cc +++ b/compiler2/subtypestuff.cc @@ -451,6 +451,16 @@ string RealRangeListConstraint::to_string() const return ret_val; } +bool RealRangeListConstraint::is_upper_limit_infinity () const +{ + return rlc.is_upper_limit_infinity(); +} + +bool RealRangeListConstraint::is_lower_limit_infinity () const +{ + return rlc.is_lower_limit_infinity(); +} + //////////////////////////////////////////////////////////////////////////////// string BooleanListConstraint::to_string() const diff --git a/compiler2/subtypestuff.hh b/compiler2/subtypestuff.hh index 86970b3..473213e 100644 --- a/compiler2/subtypestuff.hh +++ b/compiler2/subtypestuff.hh @@ -260,6 +260,9 @@ public: LIMITTYPE get_minimal() const; LIMITTYPE get_maximal() const; + bool is_upper_limit_infinity() const; + bool is_lower_limit_infinity() const; + string to_string(bool add_brackets=true) const; /** conversion from integer range to size range, @@ -538,6 +541,20 @@ LIMITTYPE RangeListConstraint::get_maximal() const return values[values.size()-1]; } +template +bool RangeListConstraint::is_upper_limit_infinity () const +{ + if (0 == values.size()) return false; + return LIMITTYPE::maximum == values[values.size()-1]; +} + +template +bool RangeListConstraint::is_lower_limit_infinity () const +{ + if (0 == values.size()) return false; + return LIMITTYPE::minimum == values[0]; +} + template string RangeListConstraint::to_string(bool add_brackets) const { @@ -597,6 +614,8 @@ public: real_limit_t get_maximal() const { return rlc.get_maximal(); } string to_string() const; + bool is_upper_limit_infinity() const; + bool is_lower_limit_infinity() const; }; //////////////////////////////////////////////////////////////////////////////// diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index 80c0563..7b0a70c 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -2707,28 +2707,37 @@ namespace Ttcn { return false; } - void Module::add_types_to_json_schema(JSON_Tokenizer& json) + void Module::generate_json_schema(JSON_Tokenizer& json, map& json_refs) { // add a new property for this module - json.put_next_token(JSON_TOKEN_NAME, modid->get_dispname().c_str()); + json.put_next_token(JSON_TOKEN_NAME, modid->get_ttcnname().c_str()); // add type definitions into an object json.put_next_token(JSON_TOKEN_OBJECT_START); - // pass the JSON tokenizer onto each type definition + // cycle through each type, generate schema segment and reference when needed for (size_t i = 0; i < asss->get_nof_asss(); ++i) { Def_Type* def = dynamic_cast(asss->get_ass_byIndex(i)); if (def != NULL) { - def->generate_json_schema(json); + Type* t = def->get_Type(); + if (t->has_encoding(Type::CT_JSON)) { + // insert type's schema segment + t->generate_json_schema(json, false, false); + + if (json_refs_for_all_types && !json_refs.has_key(t)) { + // create JSON schema reference for the type + JSON_Tokenizer* json_ref = new JSON_Tokenizer; + json_refs.add(t, json_ref); + t->generate_json_schema_ref(*json_ref); + } + } } } // end of type definitions json.put_next_token(JSON_TOKEN_OBJECT_END); - } - - void Module::add_func_to_json_schema(map& json_refs) - { + + // insert function data for (size_t i = 0; i < asss->get_nof_asss(); ++i) { Def_ExtFunction* def = dynamic_cast(asss->get_ass_byIndex(i)); if (def != NULL) { @@ -3124,13 +3133,6 @@ namespace Ttcn { } w_attrib_path->set_parent(p_path); } - - void Def_Type::generate_json_schema(JSON_Tokenizer& json) - { - if (type->has_encoding(Type::CT_JSON)) { - type->generate_json_schema(json, false, false); - } - } // ================================= // ===== Def_Const @@ -6729,13 +6731,7 @@ namespace Ttcn { // the schema segment doesn't exist yet, create it and insert the reference json = new JSON_Tokenizer; json_refs.add(type, json); - json->put_next_token(JSON_TOKEN_OBJECT_START); - json->put_next_token(JSON_TOKEN_NAME, "$ref"); - char* ref_str = mprintf("\"#/definitions/%s/%s\"", - type->get_my_scope()->get_scope_mod()->get_modid().get_dispname().c_str(), - type->get_dispname().c_str()); - json->put_next_token(JSON_TOKEN_STRING, ref_str); - Free(ref_str); + type->generate_json_schema_ref(*json); } // insert a property to specify which function this is (encoding or decoding) @@ -9087,7 +9083,7 @@ namespace Ttcn { case AP_REF: if (gen_restriction_check!=TR_NONE || gen_post_restriction_check!=TR_NONE) return false; - if (ref->get_subrefs() != NULL) { + if (use_runtime_2 && ref->get_subrefs() != NULL) { FieldOrArrayRefs* subrefs = ref->get_subrefs(); for (size_t i = 0; i < subrefs->get_nof_refs(); ++i) { if (FieldOrArrayRef::ARRAY_REF == subrefs->get_ref(i)->get_type()) { @@ -9488,7 +9484,7 @@ namespace Ttcn { } } - if (ActualPar::AP_REF == par->get_selection()) { + if (use_runtime_2 && ActualPar::AP_REF == par->get_selection()) { // if the parameter references an element of a record of/set of, then // the record of object needs to know, so it doesn't delete the referenced // element @@ -9526,17 +9522,12 @@ namespace Ttcn { // let the array object know that the index is referenced before // calling the function, and let it know that it's now longer // referenced after the function call - string tmp_id = ref->get_my_scope()->get_scope_mod_gen()->get_temporary_id(); - expr->preamble = mputprintf(expr->preamble, - "INTEGER %s = %s;\n" + expr->preamble = mputprintf(expr->preamble, "%s.add_refd_index(%s);\n", - tmp_id.c_str(), index_expr.expr, array_expr.expr, index_expr.expr); + array_expr.expr, index_expr.expr); expr->postamble = mputprintf(expr->postamble, - "%s.remove_refd_index(%s);\n" - "if (%s >= %s.size_of()) TTCN_warning(\"" - "Warning: possibly incompatible behaviour related to TR HT24380;" - " for details see release notes\");\n", - array_expr.expr, index_expr.expr, tmp_id.c_str(), array_expr.expr); + "%s.remove_refd_index(%s);\n", + array_expr.expr, index_expr.expr); // insert any postambles the array object or the index might have if (array_expr.postamble != NULL) { expr->preamble = mputstr(expr->preamble, array_expr.postamble); diff --git a/compiler2/ttcn3/AST_ttcn3.hh b/compiler2/ttcn3/AST_ttcn3.hh index 85e6999..06a57a6 100644 --- a/compiler2/ttcn3/AST_ttcn3.hh +++ b/compiler2/ttcn3/AST_ttcn3.hh @@ -625,14 +625,15 @@ namespace Ttcn { bool is_visible(const Identifier& id, visibility_t visibility); - /** Generates JSON schema segments for the types defined in the module - * and adds them to the JSON schema parameter. */ - void add_types_to_json_schema(JSON_Tokenizer& json); - - /** Generates JSON schemas containing references to the types that have JSON - * encoding and/or decoding functions declared in the module. Information - * related to these functions is also inserted after the references. */ - void add_func_to_json_schema(map& json_refs); + /** Generates JSON schema segments for the types defined in the modules, + * and references to these types. Information related to the types' + * JSON encoding and decoding functions is also inserted after the references. + * + * @param json JSON document containing the main schema, schema segments for + * the types will be inserted here + * @param json_refs map of JSON documents containing the references and function + * info related to each type */ + virtual void generate_json_schema(JSON_Tokenizer& json, map& json_refs); }; /** @@ -888,10 +889,6 @@ namespace Ttcn { virtual void set_with_attr(MultiWithAttrib* p_attrib); virtual WithAttribPath* get_attrib_path(); virtual void set_parent_path(WithAttribPath* p_path); - - /** Generates a JSON schema segment for the defined type and inserts it into - * the JSON schema parameter. */ - void generate_json_schema(JSON_Tokenizer& json); }; /** diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc index 717c361..2a452a9 100644 --- a/compiler2/ttcn3/Statement.cc +++ b/compiler2/ttcn3/Statement.cc @@ -152,13 +152,11 @@ namespace Ttcn { else return get_parent_scope()->get_ass_bySRef(p_ref); } - Type *StatementBlock::get_mtc_system_comptype(bool is_system, bool is_connecting) + Type *StatementBlock::get_mtc_system_comptype(bool is_system) { // return NULL outside test cases - if (!my_def || ((is_system || !is_connecting) && - my_def->get_asstype() != Common::Assignment::A_TESTCASE)) { + if (!my_def || my_def->get_asstype() != Common::Assignment::A_TESTCASE) return 0; - } if (is_system) { Def_Testcase *t_tc = dynamic_cast(my_def); if (!t_tc) FATAL_ERROR("StatementBlock::get_mtc_system_comptype()"); @@ -4958,7 +4956,7 @@ error: } } - Type *Statement::chk_comp_ref(Value *p_val, bool allow_mtc, bool allow_system, bool is_connecting) + Type *Statement::chk_comp_ref(Value *p_val, bool allow_mtc, bool allow_system) { if (!my_sb->get_my_def()) error("Component operation is not allowed in the control part"); @@ -5001,8 +4999,7 @@ error: p_val->error("A component reference was expected as operand"); return 0; } - Type *ret_val = is_connecting ? p_val->get_component_governor() : - p_val->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE); + Type *ret_val = p_val->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE); if (!ret_val) return 0; ret_val = ret_val->get_type_refd_last(); switch (ret_val->get_typetype()) { @@ -5020,7 +5017,7 @@ error: Type *Statement::chk_conn_endpoint(Value *p_compref, Reference *p_portref, bool allow_system) { - Type *comp_type = chk_comp_ref(p_compref, true, allow_system, true); + Type *comp_type = chk_comp_ref(p_compref, true, allow_system); if (comp_type) { ComponentTypeBody *comp_body = comp_type->get_CompBody(); p_portref->set_base_scope(comp_body); diff --git a/compiler2/ttcn3/Statement.hh b/compiler2/ttcn3/Statement.hh index 9a36b1e..1c1aa6c 100644 --- a/compiler2/ttcn3/Statement.hh +++ b/compiler2/ttcn3/Statement.hh @@ -96,7 +96,7 @@ namespace Ttcn { void register_def(Definition *p_def); virtual bool has_ass_withId(const Identifier& p_id); virtual Common::Assignment* get_ass_bySRef(Ref_simple *p_ref); - virtual Type *get_mtc_system_comptype(bool is_system, bool is_connecting); + virtual Type *get_mtc_system_comptype(bool is_system); Definition* get_my_def() const { return my_def; } virtual Ttcn::StatementBlock *get_statementblock_scope(); void set_my_sb(StatementBlock *p_sb, size_t p_index); @@ -702,9 +702,8 @@ namespace Ttcn { * type is a component type). Returns a pointer to the component * type if available or NULL otherwise. Flags \a allow_mtc and \a * allow_system indicate whether the mtc or system component - * reference is acceptable in this context. Flag \a is_connecting - * is set if the component is part of a 'map' or 'connect' statement. */ - Type *chk_comp_ref(Value *p_val, bool allow_mtc, bool allow_system, bool is_connecting = false); + * reference is acceptable in this context. */ + Type *chk_comp_ref(Value *p_val, bool allow_mtc, bool allow_system); /** Checks an endpoint for a port connection or mapping. Parameter * \a p_compref is a component reference, \a p_portref refers to * a port within the corresponding component type. A pointer to diff --git a/compiler2/ttcn3/Ttcn2Json.cc b/compiler2/ttcn3/Ttcn2Json.cc index ab34103..fb70102 100644 --- a/compiler2/ttcn3/Ttcn2Json.cc +++ b/compiler2/ttcn3/Ttcn2Json.cc @@ -36,31 +36,32 @@ void Ttcn2Json::create_schema(JSON_Tokenizer& json) json.put_next_token(JSON_TOKEN_NAME, "definitions"); json.put_next_token(JSON_TOKEN_OBJECT_START, NULL); - // insert module names and schemas for types - modules->add_types_to_json_schema(json); + // insert module names and schemas for types; gather references to types and + // JSON encoding/decoding function information + map json_refs; + modules->generate_json_schema(json, json_refs); // end of type definitions json.put_next_token(JSON_TOKEN_OBJECT_END, NULL); - - // top-level "anyOf" structure containing references to the types the schema validates - json.put_next_token(JSON_TOKEN_NAME, "anyOf"); - json.put_next_token(JSON_TOKEN_ARRAY_START, NULL); - - // gather type references and JSON encoding/decoding function data - map json_refs; - modules->add_func_to_json_schema(json_refs); - - // close schema segments and add them to the main schema - for (size_t i = 0; i < json_refs.size(); ++i) { - JSON_Tokenizer* segment = json_refs.get_nth_elem(i); - segment->put_next_token(JSON_TOKEN_OBJECT_END, NULL); - insert_schema(json, *segment); - delete segment; + + if (!json_refs.empty()) { + // top-level "anyOf" structure containing references to the types the schema validates + // don't insert an empty "anyOf" if there are no references + json.put_next_token(JSON_TOKEN_NAME, "anyOf"); + json.put_next_token(JSON_TOKEN_ARRAY_START, NULL); + + // close schema segments and add them to the main schema + for (size_t i = 0; i < json_refs.size(); ++i) { + JSON_Tokenizer* segment = json_refs.get_nth_elem(i); + segment->put_next_token(JSON_TOKEN_OBJECT_END, NULL); + insert_schema(json, *segment); + delete segment; + } + json_refs.clear(); + + // end of the "anyOf" structure + json.put_next_token(JSON_TOKEN_ARRAY_END, NULL); } - json_refs.clear(); - - // end of the "anyOf" structure - json.put_next_token(JSON_TOKEN_ARRAY_END, NULL); // top-level object end json.put_next_token(JSON_TOKEN_OBJECT_END, NULL); diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc index 8052ecc..bf646c6 100644 --- a/compiler2/ttcn3/TtcnTemplate.cc +++ b/compiler2/ttcn3/TtcnTemplate.cc @@ -1729,7 +1729,8 @@ namespace Ttcn { vs->add_v(v); } ret_val = new Value(Value::V_SEQOF, vs); - if (gov) ret_val->set_my_governor(gov->get_parent_type()); + if (gov) gov = gov->get_parent_type(); + if (gov) ret_val->set_my_governor(gov); break; } case NAMED_TEMPLATE_LIST: { NamedValues *nvs = new NamedValues; @@ -1744,7 +1745,8 @@ namespace Ttcn { nvs->add_nv(nv); } ret_val = new Value(Value::V_SEQ, nvs); - if (gov) ret_val->set_my_governor(gov->get_parent_type()); + if (gov) gov = gov->get_parent_type(); + if (gov) ret_val->set_my_governor(gov); break; } case INDEXED_TEMPLATE_LIST: { Values *ivs = new Values(true); @@ -1759,7 +1761,8 @@ namespace Ttcn { ivs->add_iv(iv); } ret_val = new Value(Value::V_SEQOF, ivs); - if (gov) ret_val->set_my_governor(gov->get_parent_type()); + if (gov) gov = gov->get_parent_type(); + if (gov) ret_val->set_my_governor(gov); break; } default: FATAL_ERROR("Template::get_Value()"); diff --git a/compiler2/ttcn3/compiler.c b/compiler2/ttcn3/compiler.c index 9f8675b..ce428ba 100644 --- a/compiler2/ttcn3/compiler.c +++ b/compiler2/ttcn3/compiler.c @@ -310,6 +310,10 @@ void write_output(output_struct *output, const char *module_name, COPYRIGHT_STRING "\n\n" "// Do not edit this file unless you know what you are doing.\n", is_ttcn ? "TTCN-3" : "ASN.1", user_info); + + if (profiler_enabled) { + output->source.includes = mputstr(output->source.includes, "#include \"Profiler.hh\"\n"); + } if (output->source.includes != NULL) { fputs("\n/* Including header files */\n\n", fp); diff --git a/compiler2/union.c b/compiler2/union.c index 0393bcc..e469f4a 100644 --- a/compiler2/union.c +++ b/compiler2/union.c @@ -1306,7 +1306,7 @@ void defUnionClass(struct_def const *sdef, output_struct *output) src = mputprintf(src, /* XERSTUFF XER_encode for union */ "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, " - "unsigned int p_flavor, int p_indent) const\n" + "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n" "{\n" "%s" " if (%s==union_selection) {\n" @@ -1318,7 +1318,7 @@ void defUnionClass(struct_def const *sdef, output_struct *output) " int encoded_length=(int)p_buf.get_len();\n" , name , (use_runtime_2 ? " if (err_descr) return XER_encode_negtest" - "(err_descr, p_td, p_buf, p_flavor, p_indent);\n" : "") + "(err_descr, p_td, p_buf, p_flavor, p_indent, 0);\n" : "") , unbound_value ); @@ -1380,7 +1380,7 @@ void defUnionClass(struct_def const *sdef, output_struct *output) src = mputprintf(src, " case %s_%s:\n" " ec_1.set_msg(\"%s': \");\n" " field_%s->XER_encode(%s_xer_, p_buf, flavor_0, " - "p_indent + (!p_indent || !omit_tag));\n" + "p_indent + (!p_indent || !omit_tag), 0);\n" " break;\n", selection_prefix, sdef->elements[i].name, sdef->elements[i].dispname, @@ -1403,11 +1403,11 @@ void defUnionClass(struct_def const *sdef, output_struct *output) def = mputstr(def, "int XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, " "const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, " - "unsigned int p_flavor, int p_indent) const;\n"); + "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const;\n"); src = mputprintf(src, /* XERSTUFF XER_encode for union */ "int %s::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, " "const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, " - "unsigned int p_flavor, int p_indent) const\n" + "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n" "{\n" " if (%s==union_selection) {\n" " TTCN_error(\"Attempt to XER-encode an unbound union value.\");\n" @@ -1486,15 +1486,15 @@ void defUnionClass(struct_def const *sdef, output_struct *output) "(\"internal error: erroneous value typedescriptor missing\");\n" " else err_vals->value->errval->XER_encode(" "*err_vals->value->type_descr->xer, p_buf, flavor_0, " - "p_indent + (!p_indent || !omit_tag));\n" + "p_indent + (!p_indent || !omit_tag), 0);\n" " }\n" " }\n" " } else {\n" " ec_1.set_msg(\"%s': \");\n" " if (emb_descr) field_%s->XER_encode_negtest(emb_descr, " - "%s_xer_, p_buf, flavor_0, p_indent + (!p_indent || !omit_tag));\n" + "%s_xer_, p_buf, flavor_0, p_indent + (!p_indent || !omit_tag), 0);\n" " else field_%s->XER_encode(%s_xer_, p_buf, flavor_0, " - "p_indent + (!p_indent || !omit_tag));\n" + "p_indent + (!p_indent || !omit_tag), 0);\n" " }\n" " break;\n", selection_prefix, sdef->elements[i].name, /* case label */ @@ -1533,7 +1533,7 @@ void defUnionClass(struct_def const *sdef, output_struct *output) #endif src = mputprintf(src, /* XERSTUFF decoder functions for union */ "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader," - " unsigned int p_flavor)\n" + " unsigned int p_flavor, embed_values_dec_struct_t*)\n" "{\n" " int e_xer = is_exer(p_flavor);\n" " int type = 0;\n" /* None */ @@ -1643,7 +1643,7 @@ void defUnionClass(struct_def const *sdef, output_struct *output) " ec_2.set_msg(\"%s': \");\n" " if (%s==union_selection) {\n" " matched = %d;\n" - " %s().XER_decode(%s_xer_, p_reader, flavor_1);\n" + " %s().XER_decode(%s_xer_, p_reader, flavor_1, 0);\n" " }\n" " if (field_%s->is_bound()) break; else clean_up();\n" " }\n", @@ -1696,7 +1696,7 @@ void defUnionClass(struct_def const *sdef, output_struct *output) src = mputprintf(src, " %sif (%s::can_start(elem_name, ns_uri, %s_xer_, flavor_1) || (%s_xer_.xer_bits & ANY_ELEMENT)) {\n" " ec_2.set_msg(\"%s': \");\n" - " %s%s().XER_decode(%s_xer_, p_reader, flavor_1);\n" + " %s%s().XER_decode(%s_xer_, p_reader, flavor_1, 0);\n" " if (!%s%s().is_bound()) {\n" " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, \"Failed to decode field.\");\n" " }\n" @@ -1713,7 +1713,7 @@ void defUnionClass(struct_def const *sdef, output_struct *output) src = mputprintf(src, " %sif ((e_xer && (type==XML_READER_TYPE_END_ELEMENT || !own_tag)) || %s::can_start(elem_name, ns_uri, %s_xer_, flavor_1) || (%s_xer_.xer_bits & ANY_ELEMENT)) {\n" "empty_xml: ec_2.set_msg(\"%s': \");\n" - " %s%s().XER_decode(%s_xer_, p_reader, flavor_1);\n" + " %s%s().XER_decode(%s_xer_, p_reader, flavor_1, 0);\n" " if (!%s%s().is_bound()) {\n" " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, \"Failed to decode field.\");\n" " }\n" diff --git a/compiler2/xpather.cc b/compiler2/xpather.cc index 14c15a6..d816584 100644 --- a/compiler2/xpather.cc +++ b/compiler2/xpather.cc @@ -29,7 +29,10 @@ // Do _NOT_ #include "string.hh", it drags in ustring.o, common/Quadruple.o, // Int.o, ttcn3/PatternString.o, and then the entire AST :( #include "map.hh" +#include "ProjectGenHelper.hh" #include "../common/path.h" +#include "ttcn3/ttcn3_preparser.h" +#include "asn1/asn1_preparser.h" // in makefile.c void ERROR (const char *fmt, ...); @@ -52,6 +55,8 @@ void fatal_error(const char * filename, int lineno, const char * fmt, ...) abort(); } +ProjectGenHelper& projGenHelper = ProjectGenHelper::Instance(); + /// Run an XPath query and return an xmlXPathObjectPtr, which must be freed xmlXPathObjectPtr run_xpath(xmlXPathContextPtr xpathCtx, const char *xpathExpr) { @@ -218,12 +223,299 @@ void xsdbool2boolean(const XPathContext& xpathCtx, const char *actcfg, } } +extern "C" string_list* getExternalLibs(const char* projName) +{ + if (!projGenHelper.getZflag()) return NULL; + ProjectDescriptor* proj = projGenHelper.getTargetOfProject(projName); + if (!proj) return NULL; + + std::vector externalLibs; + projGenHelper.getExternalLibs(externalLibs); + + if (0 == externalLibs.size()) return NULL; + + struct string_list* head = (struct string_list*)Malloc(sizeof(struct string_list)); + struct string_list* last_elem = head; + struct string_list* tail = head; + + for (size_t i = 0; i < externalLibs.size(); ++i) { + tail = last_elem; + last_elem->str = mcopystr(externalLibs[i]); + last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list)); + last_elem = last_elem->next; + } + Free(last_elem); + tail->next = NULL; + return head; +} + +extern "C" string_list* getExternalLibPathes(const char* projName) +{ + if (!projGenHelper.getZflag()) return NULL; + ProjectDescriptor* proj = projGenHelper.getTargetOfProject(projName); + if (!proj) return NULL; + + std::vector externalLibs; + projGenHelper.getExternalLibSearchPathes(externalLibs); + + if (0 == externalLibs.size()) return NULL; + + struct string_list* head = (struct string_list*)Malloc(sizeof(struct string_list)); + struct string_list* last_elem = head; + struct string_list* tail = head; + + for (size_t i = 0; i < externalLibs.size(); ++i) { + tail = last_elem; + last_elem->str = mcopystr(externalLibs[i]); + last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list)); + last_elem = last_elem->next; + } + Free(last_elem); + tail->next = NULL; + return head; +} + +extern "C" string_list* getRefWorkingDirs(const char* projName) +{ + if (!projGenHelper.getZflag()) return NULL; + ProjectDescriptor* proj = projGenHelper.getTargetOfProject(projName); + if (!proj) FATAL_ERROR("Project \"%s\" was not found in the project list", projName); + + struct string_list* head = (struct string_list*)Malloc(sizeof(struct string_list)); + struct string_list* last_elem = head; + struct string_list* tail = head; + last_elem->str = NULL; + last_elem->next = NULL; + for (size_t i = 0; i < proj->numOfRefProjWorkingDirs(); ++i) { + tail = last_elem; + last_elem->str = mcopystr(proj->getRefProjWorkingDir(i).c_str()); + last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list)); + last_elem = last_elem->next; + } + Free(last_elem); + tail->next = NULL; + return head; +} + +extern "C" string2_list* getLinkerLibs(const char* projName) +{ + + if (!projGenHelper.getZflag()) return NULL; + if (1 == projGenHelper.numOfProjects() || 0 == projGenHelper.numOfLibs()){ + return NULL; //no library + } + ProjectDescriptor* projLib = projGenHelper.getTargetOfProject(projName); + if (!projLib) FATAL_ERROR("Project \"%s\" was not found in the project list", projName); + + struct string2_list* head = (struct string2_list*)Malloc(sizeof(struct string2_list)); + struct string2_list* last_elem = head; + struct string2_list* tail = head; + last_elem->next = NULL; + last_elem->str1 = NULL; + last_elem->str2 = NULL; + for (std::map::const_iterator it = projGenHelper.getHead(); + it != projGenHelper.getEnd(); ++it) { + if ((it->second).isLibrary()) { + if (!(it->second).getLinkingStrategy() && + !projLib->hasLinkerLibTo((it->second).getProjectName())) { // static linked library + continue; + } + std::string relPath = projLib->setRelativePathTo((it->second).getProjectAbsWorkingDir()); + if (relPath == std::string(".")) { + continue; // the relpath shows to itself + } + tail = last_elem; + last_elem->str1 = mcopystr(relPath.c_str()); + last_elem->str2 = mcopystr((it->second).getTargetExecName().c_str()); + last_elem->next = (struct string2_list*)Malloc(sizeof(struct string2_list)); + last_elem = last_elem->next; + } + } + tail->next = NULL; + Free(last_elem); + + if (head->str1 && head->str2) + return head; + else + return NULL; +} + +extern "C" const char* getLibFromProject(const char* projName) +{ + if (!projGenHelper.getZflag()) return NULL; + ProjectDescriptor* lib = projGenHelper.getTargetOfProject(projName); + if (lib) return lib->getTargetExecName().c_str(); + return NULL; +} + +extern "C" void erase_libs() { + projGenHelper.cleanUp(); +} + +extern "C" void print_libs() { + projGenHelper.print(); +} + + +extern "C" boolean hasSubProject(const char* projName) { + if (!projGenHelper.getZflag()) return FALSE; + if (projGenHelper.getHflag()) + return static_cast(projGenHelper.hasReferencedProject()); + else if(std::string(projName) == projGenHelper.getToplevelProjectName()) + return static_cast(projGenHelper.hasReferencedProject()); + else + return FALSE; +} + +extern "C" boolean hasExternalLibrary(const char* libName, const char* projName) { + if (!projGenHelper.getZflag()) return FALSE; + ProjectDescriptor* projLib = projGenHelper.getTargetOfProject(projName); + if (projLib && projLib->hasLinkerLib(libName)) + return TRUE; + else + return FALSE; +} + +extern "C" boolean isTopLevelExecutable(const char* projName) { + if (!projGenHelper.getZflag()) return false; + ProjectDescriptor* proj = projGenHelper.getTargetOfProject(projName); + if (projGenHelper.getToplevelProjectName() != std::string(projName)) return FALSE; + if (proj && proj->isLibrary()) + return FALSE; + else + return TRUE; +} + +extern "C" boolean isDynamicLibrary(const char* key) { + if (!projGenHelper.getZflag()) return false; + ProjectDescriptor* proj = projGenHelper.getProjectDescriptor(key); + if (proj) return proj->getLinkingStrategy(); + FATAL_ERROR("Library \"%s\" was not found", key); + return false; +} + +extern "C" const char* getTPDFileName(const char* projName) { + if (!projGenHelper.getZflag()) return NULL; + ProjectDescriptor* proj = projGenHelper.getTargetOfProject(projName); + if (proj) return proj->getTPDFileName().c_str(); + FATAL_ERROR("TPD file name to project \"%s\" was not found", projName); +} + +extern "C" const char* getPathToRootDir(const char* projName) { + if (!projGenHelper.getZflag()) return NULL; + ProjectDescriptor* proj = projGenHelper.getTargetOfProject(projName); + const char* rootDir = projGenHelper.getRootDirOS(projName).c_str(); + if (proj && rootDir) { + return rootDir; + } + FATAL_ERROR("Project \"%s\": no relative path was found to top directory at OS level.", projName); +} + +extern "C" const char* findLibraryPath(const char* libraryName, const char* projName) +{ + if (!projGenHelper.getZflag()) return NULL; + ProjectDescriptor* projLib = projGenHelper.getTargetOfProject(projName); + if (!projLib) FATAL_ERROR("Project \"%s\" was not found in the project list", projName); + ProjectDescriptor* libLib = projGenHelper.getProjectDescriptor(libraryName); + if (!libLib) return NULL; + std::string str = projLib->setRelativePathTo(libLib->getProjectAbsWorkingDir()); + size_t refIndex = projLib->getLibSearchPathIndex(libLib->getProjectName()); + if (refIndex > projLib->numOfLibSearchPaths()) return NULL; + projLib->setLibSearchPath(refIndex, str); + return projLib->getLibSearchPath(libLib->getProjectName()); +} + +extern "C" const char* findLibraryName(const char* libraryName, const char* projName) +{ + if (!projGenHelper.getZflag()) return NULL; + ProjectDescriptor* projLib = projGenHelper.getTargetOfProject(projName); + if (!projLib) FATAL_ERROR("Project \"%s\" was not found in the project list", projName); + ProjectDescriptor* libLib = projGenHelper.getProjectDescriptor(libraryName); + if (!libLib) return NULL; + for (size_t i = 0; i < projLib->numOfReferencedProjects(); ++i) { + const std:: string refProjName = projLib->getReferencedProject(i); + ProjectDescriptor* refLib = projGenHelper.getTargetOfProject(refProjName.c_str()); + if (refLib->getTargetExecName() == std::string(libraryName)) + return libraryName; + } + return NULL; +} + +extern "C" boolean isTtcn3ModuleInLibrary(const char* moduleName) +{ + if (!projGenHelper.getZflag()) return FALSE; + return (boolean)projGenHelper.isTtcn3ModuleInLibrary(moduleName); +} + +extern "C" boolean isAsn1ModuleInLibrary(const char* moduleName) +{ + if (!projGenHelper.getZflag()) return FALSE; + return (boolean)projGenHelper.isAsn1ModuleInLibrary(moduleName); +} + +extern "C" boolean isSourceFileInLibrary(const char* fileName) +{ + if (!projGenHelper.getZflag()) return FALSE; + return (boolean)projGenHelper.isSourceFileInLibrary(fileName); +} + +extern "C" boolean isHeaderFileInLibrary(const char* fileName) +{ + if (!projGenHelper.getZflag()) return FALSE; + return (boolean)projGenHelper.isHeaderFileInLibrary(fileName); +} + +extern "C" boolean isTtcnPPFileInLibrary(const char* fileName) +{ + if (!projGenHelper.getZflag()) return FALSE; + return (boolean)projGenHelper.isTtcnPPFileInLibrary(fileName); +} + + +extern "C" boolean buildObjects(const char* projName, boolean add_referenced) +{ + if (!projGenHelper.getZflag()) return FALSE; + if (projGenHelper.getHflag()) return FALSE; + if (add_referenced) return FALSE; + ProjectDescriptor* desc =projGenHelper.getTargetOfProject(projName); + if (desc && desc->isLibrary()) return FALSE; + return TRUE; +} + +void append_to_library_list (const char* prjName, + const XPathContext& xpathCtx, + const char *actcfg) +{ + if (!projGenHelper.getZflag()) return; + + char *exeXpath = mprintf( + "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']" + "/ProjectProperties/MakefileSettings/targetExecutable/text()", + actcfg); + XPathObject exeObj(run_xpath(xpathCtx, exeXpath)); + Free(exeXpath); + std::string lib_name; + if (exeObj->nodesetval && exeObj->nodesetval->nodeNr > 0) { + const char* target_executable = (const char*)exeObj->nodesetval->nodeTab[0]->content; + autostring target_exe_dir(get_dir_from_path(target_executable)); + autostring target_exe_file(get_file_from_path(target_executable)); + lib_name = target_exe_file; + ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(prjName); + if (projDesc) { + projDesc->setTargetExecName(lib_name.c_str()); + } + } +} + // data structures and functions to manage excluded folders/files -map excluded_files; +map excluded_files; -boolean is_excluded_file(const cstring& path) { - return excluded_files.has_key(path); +boolean is_excluded_file(const cstring& path, const char* project) { + if (!excluded_files.has_key(path)) return false; + const char* proj = excluded_files[path]; + if (0 == strcmp(project, proj)) return true; + return false; } vector excluded_folders; @@ -305,58 +597,80 @@ static void clear_seen_tpd_files(map& seen_tpd_files) { seen_tpd_files.clear(); } +const char* get_act_config(struct string2_list* cfg, const char* project_name) { + while (cfg && cfg->str1 && project_name) { + if (!strcmp(cfg->str1, project_name)) return cfg->str2; + cfg = cfg->next; + } + return NULL; +} + static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcfg, const char *file_list_path, int *p_argc, char ***p_argv, - int *p_optind, char **p_ets_name, + int *p_optind, char **p_ets_name, char **p_project_name, boolean *p_gflag, boolean *p_sflag, boolean *p_cflag, boolean *p_aflag, boolean *preprocess, boolean *p_Rflag, boolean *p_lflag, boolean *p_mflag, boolean *p_Pflag, boolean *p_Lflag, boolean recursive, boolean force_overwrite, boolean gen_only_top_level, const char *output_file, char** abs_work_dir_p, struct string_list* sub_project_dirs, const char* program_name, FILE* prj_graph_fp, struct string2_list* create_symlink_list, struct string_list* ttcn3_prep_includes, - struct string_list* ttcn3_prep_defines, struct string_list* prep_includes, struct string_list* prep_defines, - boolean *p_csflag, boolean *p_quflag, boolean* p_dsflag, char** cxxcompiler, - char** optlevel, char** optflags, boolean* p_dbflag, boolean* p_drflag, boolean* p_dtflag, boolean* p_dxflag, boolean* p_djflag, - boolean* p_fxflag, boolean* p_doflag, boolean* p_gfflag, boolean* p_lnflag, boolean* p_isflag, + struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes, + struct string_list* prep_defines, struct string_list* prep_undefines, boolean *p_csflag, boolean *p_quflag, boolean* p_dsflag, + char** cxxcompiler, char** optlevel, char** optflags, boolean* p_dbflag, boolean* p_drflag, boolean* p_dtflag, boolean* p_dxflag, + boolean* p_djflag, boolean* p_fxflag, boolean* p_doflag, boolean* p_gfflag, boolean* p_lnflag, boolean* p_isflag, boolean* p_asflag, boolean* p_swflag, boolean* p_Yflag, struct string_list* solspeclibs, struct string_list* sol8speclibs, struct string_list* linuxspeclibs, struct string_list* freebsdspeclibs, struct string_list* win32speclibs, char** ttcn3prep, struct string_list* linkerlibs, struct string_list* additionalObjects, struct string_list* linkerlibsearchp, boolean Vflag, boolean Dflag, - char** generatorCommandOutput, struct string2_list* target_placement_list, boolean prefix_workdir, struct string2_list* run_command_list, - map& seen_tpd_files); + boolean *p_Zflag, boolean *p_Hflag, char** generatorCommandOutput, struct string2_list* target_placement_list, boolean prefix_workdir, + struct string2_list* run_command_list, map& seen_tpd_files, struct string2_list* required_configs); extern "C" tpd_result process_tpd(const char *p_tpd_name, const char *actcfg, const char *file_list_path, int *p_argc, char ***p_argv, - int *p_optind, char **p_ets_name, + int *p_optind, char **p_ets_name, char **p_project_name, boolean *p_gflag, boolean *p_sflag, boolean *p_cflag, boolean *p_aflag, boolean *preprocess, boolean *p_Rflag, boolean *p_lflag, boolean *p_mflag, boolean *p_Pflag, boolean *p_Lflag, boolean recursive, boolean force_overwrite, boolean gen_only_top_level, const char *output_file, char** abs_work_dir_p, struct string_list* sub_project_dirs, const char* program_name, FILE* prj_graph_fp, struct string2_list* create_symlink_list, struct string_list* ttcn3_prep_includes, - struct string_list* ttcn3_prep_defines, struct string_list* prep_includes, struct string_list* prep_defines, - boolean *p_csflag, boolean *p_quflag, boolean* p_dsflag, char** cxxcompiler, - char** optlevel, char** optflags, boolean* p_dbflag, boolean* p_drflag, boolean* p_dtflag, boolean* p_dxflag, boolean* p_djflag, - boolean* p_fxflag, boolean* p_doflag, boolean* p_gfflag, boolean* p_lnflag, boolean* p_isflag, + struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes, + struct string_list* prep_defines, struct string_list* prep_undefines, boolean *p_csflag, boolean *p_quflag, boolean* p_dsflag, + char** cxxcompiler, char** optlevel, char** optflags, boolean* p_dbflag, boolean* p_drflag, boolean* p_dtflag, boolean* p_dxflag, + boolean* p_djflag, boolean* p_fxflag, boolean* p_doflag, boolean* p_gfflag, boolean* p_lnflag, boolean* p_isflag, boolean* p_asflag, boolean* p_swflag, boolean* p_Yflag, struct string_list* solspeclibs, struct string_list* sol8speclibs, struct string_list* linuxspeclibs, struct string_list* freebsdspeclibs, struct string_list* win32speclibs, char** ttcn3prep, - string_list* linkerlibs, string_list* additionalObjects, string_list* linkerlibsearchp, boolean Vflag, boolean Dflag, - char** generatorCommandOutput, struct string2_list* target_placement_list, boolean prefix_workdir, struct string2_list* run_command_list) { + string_list* linkerlibs, string_list* additionalObjects, string_list* linkerlibsearchp, boolean Vflag, boolean Dflag, boolean *p_Zflag, + boolean *p_Hflag, char** generatorCommandOutput, struct string2_list* target_placement_list, boolean prefix_workdir, + struct string2_list* run_command_list, struct string2_list* required_configs) { map seen_tpd_files; + projGenHelper.setZflag(*p_Zflag); + projGenHelper.setWflag(prefix_workdir); + projGenHelper.setHflag(*p_Hflag); tpd_result success = process_tpd_internal(p_tpd_name, - actcfg, file_list_path, p_argc, p_argv, p_optind, p_ets_name, + actcfg, file_list_path, p_argc, p_argv, p_optind, p_ets_name, p_project_name, p_gflag, p_sflag, p_cflag, p_aflag, preprocess, p_Rflag, p_lflag, p_mflag, p_Pflag, p_Lflag, recursive, force_overwrite, gen_only_top_level, output_file, abs_work_dir_p, sub_project_dirs, program_name, prj_graph_fp, create_symlink_list, ttcn3_prep_includes, - ttcn3_prep_defines, prep_includes, prep_defines, - p_csflag, p_quflag, p_dsflag, cxxcompiler, + ttcn3_prep_defines, ttcn3_prep_undefines, prep_includes, prep_defines, + prep_undefines, p_csflag, p_quflag, p_dsflag, cxxcompiler, optlevel, optflags, p_dbflag, p_drflag, p_dtflag, p_dxflag, p_djflag, p_fxflag, p_doflag, p_gfflag, p_lnflag, p_isflag, p_asflag, p_swflag, p_Yflag, solspeclibs, sol8speclibs, linuxspeclibs, freebsdspeclibs, win32speclibs, ttcn3prep, - linkerlibs, additionalObjects, linkerlibsearchp, Vflag, Dflag, - generatorCommandOutput, target_placement_list, prefix_workdir, run_command_list, seen_tpd_files); + linkerlibs, additionalObjects, linkerlibsearchp, Vflag, Dflag, p_Zflag, + p_Hflag, generatorCommandOutput, target_placement_list, prefix_workdir, + run_command_list, seen_tpd_files, required_configs); + + if (TPD_FAILED == success) exit(EXIT_FAILURE); + + if (false == projGenHelper.sanityCheck()) { + fprintf (stderr, "makefilegen exits\n"); + exit(EXIT_FAILURE); + } + + projGenHelper.generateRefProjectWorkingDirsTo(*p_project_name); for (size_t i = 0, num = seen_tpd_files.size(); i < num; ++i) { const cstring& key = seen_tpd_files.get_nth_key(i); @@ -381,22 +695,23 @@ extern "C" tpd_result process_tpd(const char *p_tpd_name, const char *actcfg, // it must nevertheless make a copy on the heap via mcopystr(). static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcfg, const char *file_list_path, int *p_argc, char ***p_argv, - int *p_optind, char **p_ets_name, + int *p_optind, char **p_ets_name, char **p_project_name, boolean *p_gflag, boolean *p_sflag, boolean *p_cflag, boolean *p_aflag, boolean *preprocess, boolean *p_Rflag, boolean *p_lflag, boolean *p_mflag, boolean *p_Pflag, boolean *p_Lflag, boolean recursive, boolean force_overwrite, boolean gen_only_top_level, const char *output_file, char** abs_work_dir_p, struct string_list* sub_project_dirs, const char* program_name, FILE* prj_graph_fp, struct string2_list* create_symlink_list, struct string_list* ttcn3_prep_includes, - struct string_list* ttcn3_prep_defines, struct string_list* prep_includes, struct string_list* prep_defines, - boolean *p_csflag, boolean *p_quflag, boolean* p_dsflag, char** cxxcompiler, - char** optlevel, char** optflags, boolean* p_dbflag, boolean* p_drflag, boolean* p_dtflag, boolean* p_dxflag, boolean* p_djflag, - boolean* p_fxflag, boolean* p_doflag, boolean* p_gfflag, boolean* p_lnflag, boolean* p_isflag, + struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes, + struct string_list* prep_defines, struct string_list* prep_undefines, boolean *p_csflag, boolean *p_quflag, boolean* p_dsflag, + char** cxxcompiler, char** optlevel, char** optflags, boolean* p_dbflag, boolean* p_drflag, boolean* p_dtflag, boolean* p_dxflag, + boolean* p_djflag, boolean* p_fxflag, boolean* p_doflag, boolean* p_gfflag, boolean* p_lnflag, boolean* p_isflag, boolean* p_asflag, boolean* p_swflag, boolean* p_Yflag, struct string_list* solspeclibs, struct string_list* sol8speclibs, struct string_list* linuxspeclibs, struct string_list* freebsdspeclibs, struct string_list* win32speclibs, char** ttcn3prep, - string_list* linkerlibs, string_list* additionalObjects, string_list* linkerlibsearchp, boolean Vflag, boolean Dflag, - char** generatorCommandOutput, struct string2_list* target_placement_list, boolean prefix_workdir, struct string2_list* run_command_list, - map& seen_tpd_files) + string_list* linkerlibs, string_list* additionalObjects, string_list* linkerlibsearchp, boolean Vflag, boolean Dflag, boolean *p_Zflag, + boolean *p_Hflag, char** generatorCommandOutput, struct string2_list* target_placement_list, boolean prefix_workdir, + struct string2_list* run_command_list, map& seen_tpd_files, struct string2_list* required_configs) { + tpd_result result = TPD_SUCCESS; // read-only non-pointer aliases //char** const& local_argv = *p_argv; int const& local_argc = *p_argc; @@ -410,7 +725,10 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf autostring tpd_dir(get_dir_from_path(p_tpd_name)); autostring abs_tpd_dir(get_absolute_dir(tpd_dir, NULL)); - + if (NULL == (const char*)abs_tpd_dir) { + ERROR("absolut TPD directory could not be retreaved from %s", (const char*)tpd_dir); + return TPD_FAILED; + } autostring tpd_filename(get_file_from_path(p_tpd_name)); autostring abs_tpd_name(compose_path_name(abs_tpd_dir, tpd_filename)); @@ -552,8 +870,25 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf } // next FolderResource } - if (actcfg == NULL) + ///////////////////////////////////////////////////////////////////////////// { + char *projectNameXpath = mprintf("/TITAN_Project_File_Information/ProjectName/text()"); + XPathObject projectNameObj(run_xpath(xpathCtx, projectNameXpath)); + Free(projectNameXpath); + if (projectNameObj->nodesetval && projectNameObj->nodesetval->nodeNr > 0) { + *p_project_name = mcopystr((const char*)projectNameObj->nodesetval->nodeTab[0]->content); + projGenHelper.addTarget(*p_project_name); + projGenHelper.setToplevelProjectName(*p_project_name); + ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(*p_project_name); + if (projDesc) projDesc->setProjectAbsTpdDir((const char*)abs_tpd_dir); + } + } + ///////////////////////////////////////////////////////////////////////////// + + if (!actcfg) { + actcfg = get_act_config(required_configs,*p_project_name); + } + if (actcfg == NULL) { // Find out the active config XPathObject activeConfig(run_xpath(xpathCtx, "/TITAN_Project_File_Information/ActiveConfiguration/text()")); @@ -590,8 +925,6 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf return TPD_FAILED; } } - - ///////////////////////////////////////////////////////////////////////////// // working directory stuff autostring workdir; { @@ -623,6 +956,8 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf const char *real_workdir = folders[workdir]; // This is relative to the location of the tpd file excluded_folders.add(real_workdir); // excluded by convention + autostring proj_abs_workdir; + autostring abs_workdir; // If -D flag was specified then we ignore the workdir // in the TPD (the current dir is considered the work dir). @@ -643,7 +978,8 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf break; default: if (recursive || local_argc != 0) { // we only want to create workdir if necessary - printf("Working directory `%s' in project `%s' does not exist, trying to create it...\n", real_workdir, (const char*)abs_tpd_dir); + fprintf(stderr, "Working directory `%s' in project `%s' does not exist, trying to create it...\n", + real_workdir, (const char*)abs_tpd_dir); int rv = mkdir(real_workdir, 0755); if (rv) ERROR("Could not create working directory, mkdir() failed: %s", strerror(errno)); else printf("Working directory created\n"); @@ -660,8 +996,21 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf if (hasWorkDir) { //we created working directory, or its already been created (from a parent makefilegen process maybe) *abs_work_dir_p = get_absolute_dir(real_workdir, abs_tpd_dir); abs_workdir = (mcopystr(*abs_work_dir_p)); + proj_abs_workdir = mcopystr(*abs_work_dir_p); } } + + if (Dflag) { // the path to subproject working dir is needed to find the linkerlibsearchpath + proj_abs_workdir = compose_path_name(abs_tpd_dir, real_workdir); + } + + ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(*p_project_name); + if (projDesc) { + projDesc->setProjectAbsWorkingDir((const char*)proj_abs_workdir); + projDesc->setProjectWorkingDir(real_workdir); + projDesc->setTPDFileName(p_tpd_name); + } + ///////////////////////////////////////////////////////////////////////////// // Gather the excluded folders in the active config @@ -697,7 +1046,7 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf xmlNodePtr curnode = nodes->nodeTab[i]; cstring aa((const char*)curnode->content); - excluded_files.add(aa, 0); + excluded_files.add(aa, *p_project_name); } } @@ -742,13 +1091,45 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf } cstring cpath(path); - if (!is_excluded_file(cpath) && !is_excluded_folder(path)) { + if (!is_excluded_file(cpath, *p_project_name) && !is_excluded_folder(path)) { // relativeURI wins over rawURI char *ruri = uri ? mcopystr(uri) : cook(raw, path_vars); - if (files.has_key(cpath)) { ERROR("A FileResource %s must be unique!", (const char*)cpath); - } else { + } + else { + const char* file_path = ruri; + expstring_t rel_file_dir = get_dir_from_path(file_path); + expstring_t file_name = get_file_from_path(file_path); + expstring_t abs_dir_path = get_absolute_dir(rel_file_dir, abs_tpd_dir); + expstring_t abs_file_name = compose_path_name(abs_dir_path, file_name); + if (abs_file_name != NULL) { + if (get_path_status(abs_file_name) == PS_FILE) { + FILE *fp = fopen(abs_file_name, "r"); + if (fp != NULL) { + char* ttcn3_module_name; + if (is_ttcn3_module(abs_file_name, fp, &ttcn3_module_name)) { + projGenHelper.addTtcn3ModuleToProject(*p_project_name, ttcn3_module_name); + } + Free(ttcn3_module_name); + char* asn1_module_name; + if (is_asn1_module(abs_file_name, fp, &asn1_module_name)) { + projGenHelper.addAsn1ModuleToProject(*p_project_name, asn1_module_name); + } + Free(asn1_module_name); + if (projGenHelper.isCPPSourceFile(file_name)) { + projGenHelper.addUserSourceToProject(*p_project_name, file_name); + } + if (projGenHelper.isCPPHeaderFile(file_name)) { + projGenHelper.addUserHeaderToProject(*p_project_name, file_name); + } + if (projGenHelper.isTtcnPPFile(file_name)) { + projGenHelper.addTtcnPPToProject(*p_project_name, file_name); + } + } + fclose(fp); + } + } files.add(cpath, ruri); // relativeURI to the TPD location { // set the *preprocess value if .ttcnpp file was found const size_t ttcnpp_extension_len = 7; // ".ttcnpp" @@ -757,6 +1138,10 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf *preprocess = TRUE; } } + Free(rel_file_dir); + Free(file_name); + Free(abs_dir_path); + Free(abs_file_name); } } } // next FileResource @@ -765,6 +1150,7 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf // Check options xsdbool2boolean(xpathCtx, actcfg, "useAbsolutePath", p_aflag); xsdbool2boolean(xpathCtx, actcfg, "GNUMake", p_gflag); + if (*p_Zflag) *p_lflag = FALSE; xsdbool2boolean(xpathCtx, actcfg, "dynamicLinking", p_lflag); xsdbool2boolean(xpathCtx, actcfg, "functiontestRuntime", p_Rflag); xsdbool2boolean(xpathCtx, actcfg, "singleMode", p_sflag); @@ -785,6 +1171,9 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf xsdbool2boolean(xpathCtx, actcfg, "suppressWarnings", p_swflag); xsdbool2boolean(xpathCtx, actcfg, "outParamBoundness", p_Yflag); + projDesc = projGenHelper.getTargetOfProject(*p_project_name); + if (projDesc) projDesc->setLinkingStrategy(*p_lflag); + // Extract the "incremental dependencies" option { boolean incremental_deps = TRUE; @@ -811,7 +1200,7 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf // Extract the default target option // if it is not defined as a command line argument if (!(*p_Lflag)) { - char *defTargetXpath = mprintf( + expstring_t defTargetXpath = mprintf( "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']" "/ProjectProperties/MakefileSettings/defaultTarget/text()", actcfg); @@ -828,6 +1217,8 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf " The available targets are: 'executable', 'library'", content); } } + ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(*p_project_name); + if (projDesc) projDesc->setLibrary(*p_Lflag); } // Executable name (don't care unless top-level invocation) @@ -939,6 +1330,36 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf } } } + { + //TTCN3preprocessorUnDefines + char *ttcn3preUndefinesXpath = mprintf( + "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']" + "/ProjectProperties/MakefileSettings/TTCN3preprocessorUndefines/listItem/text()", + actcfg); + XPathObject ttcn3preUndefinesObj(run_xpath(xpathCtx, ttcn3preUndefinesXpath)); + Free(ttcn3preUndefinesXpath); + + xmlNodeSetPtr nodes = ttcn3preUndefinesObj->nodesetval; + + if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) { + const char* content = (const char*)ttcn3preUndefinesObj->nodesetval->nodeTab[i]->content; + + // add includes to the end of list + if (ttcn3_prep_undefines) { + // go to last element + struct string_list* last_elem = ttcn3_prep_undefines; + while (last_elem->next) last_elem = last_elem->next; + // add string to last element if empty or create new last element and add it to that + if (last_elem->str) { + last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list)); + last_elem = last_elem->next; + last_elem->next = NULL; + } + last_elem->str = mcopystr(content); + } + } + } + { //preprocessorIncludes char *preincludesXpath = mprintf( @@ -998,6 +1419,35 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf } } } + { + //preprocessorUnDefines + char *preUndefinesXpath = mprintf( + "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']" + "/ProjectProperties/MakefileSettings/preprocessorUndefines/listItem/text()", + actcfg); + XPathObject preUndefinesObj(run_xpath(xpathCtx, preUndefinesXpath)); + Free(preUndefinesXpath); + + xmlNodeSetPtr nodes = preUndefinesObj->nodesetval; + + if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) { + const char* content = (const char*)preUndefinesObj->nodesetval->nodeTab[i]->content; + + // add includes to the end of list + if (prep_undefines) { + // go to last element + struct string_list* last_elem = prep_undefines; + while (last_elem->next) last_elem = last_elem->next; + // add string to last element if empty or create new last element and add it to that + if (last_elem->str) { + last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list)); + last_elem = last_elem->next; + last_elem->next = NULL; + } + last_elem->str = mcopystr(content); + } + } + } { char *cxxCompilerXpath = mprintf( "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']" @@ -1229,6 +1679,16 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf } } { + //The project name needed the hierarchical projects + char* prjNameStr = 0; + char *prjNameStrXpath = mprintf("/TITAN_Project_File_Information/ProjectName/text()"); + XPathObject prjName(run_xpath(xpathCtx, prjNameStrXpath)); + if (prjName->nodesetval && prjName->nodesetval->nodeNr == 1) { + prjNameStr = (char*)prjName->nodesetval->nodeTab[0]->content; + } + Free(prjNameStrXpath); + append_to_library_list (prjNameStr, xpathCtx, actcfg); + //linkerLibraries char *linkerlibsXpath = mprintf( "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']" @@ -1255,6 +1715,9 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf } replacechar(&content); last_elem->str = content; + + ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(*p_project_name); + if (projDesc) projDesc->addToLinkerLibs(last_elem->str); } } } @@ -1285,6 +1748,9 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf } replacechar(&content); last_elem->str = content; + + ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(*p_project_name); + if (projDesc) projDesc->addToLibSearchPaths(last_elem->str); } } } @@ -1350,6 +1816,63 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf } } +// collect the required configurations + { + if (required_configs) { + char* cfgReqsXpath(mprintf( + "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']" + "/ProjectProperties/ConfigurationRequirements/configurationRequirement", + actcfg)); + XPathObject reqcfgObjects(run_xpath(xpathCtx, cfgReqsXpath)); + Free (cfgReqsXpath); + xmlNodeSetPtr configs = reqcfgObjects->nodesetval; + if (configs) for (int i = 0; i < configs->nodeNr; ++i) { + xmlNodePtr curNodePtr = configs->nodeTab[i]->children; + const char* projectName = NULL; + const char* reqConfig = NULL; + while(curNodePtr) { + if (!strcmp((const char*)curNodePtr->name, "projectName")) { + projectName = (const char*)curNodePtr->children->content; + } + if (!strcmp((const char*)curNodePtr->name, "rerquiredConfiguration") || // backward compatibility + !strcmp((const char*)curNodePtr->name, "requiredConfiguration")) { + reqConfig = (const char*)curNodePtr->children->content; + } + curNodePtr = curNodePtr->next; + } + struct string2_list* last_elem = required_configs; + bool duplicate = false; + while (last_elem->next) { + if (!strcmp(last_elem->str1, projectName) && !strcmp(last_elem->str2, reqConfig)) { + duplicate = true; + } + else if (!strcmp(last_elem->str1, projectName) && strcmp(last_elem->str2, reqConfig)) { + ERROR("Required configuration is inconsistent : Project '%s' cannot have 2 " + "different configuration '%s' '%s'", + last_elem->str1, last_elem->str2, reqConfig); + result = TPD_FAILED; + } + last_elem = last_elem->next; + } + // add string to last element if empty or create new last element and add it to that + if (last_elem->str1 && !duplicate) { + if (strcmp(last_elem->str1, projectName) || strcmp(last_elem->str2, reqConfig)) { + last_elem->next = (struct string2_list*)Malloc(sizeof(struct string2_list)); + last_elem = last_elem->next; + last_elem->next = NULL; + } + else { + duplicate = true; + } + } + if (!duplicate) { + last_elem->str1 = mcopystr(projectName); + last_elem->str2 = mcopystr(reqConfig); + } + } + } + } + // Referenced projects { XPathObject subprojects(run_xpath(xpathCtx, @@ -1374,28 +1897,17 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf if (name && projectLocationURI) { // collected both // see if there is a specified configuration for the project - const char *my_actcfg = NULL; - autostring req_xpath(mprintf( - "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']" - "/ProjectProperties/ConfigurationRequirements/configurationRequirement" - "/projectName[text()='%s']" - // Up to this point, we selected the projectName node which contains - // the name of the subproject. But we want its sibling. - // So we go up one and down the other path. - "/parent::*/rerquiredConfiguration/text()", - //Yes, it's rerquiredConfiguration; the Designer misspells it :( - actcfg, name)); - XPathObject reqcfgObj(run_xpath(xpathCtx, req_xpath)); - if (reqcfgObj->nodesetval && reqcfgObj->nodesetval->nodeNr == 1) { - my_actcfg = (const char*)reqcfgObj->nodesetval->nodeTab[0]->content; - } + ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(*p_project_name); + if (projDesc) projDesc->addToReferencedProjects(name); + + const char *my_actcfg = NULL; int my_argc = 0; char *my_args[] = { NULL }; char **my_argv = my_args + 0; int my_optind = 0; boolean my_gflag = *p_gflag, my_aflag = *p_aflag, my_cflag = *p_cflag, // pass down - my_Rflag = *p_Rflag, my_Pflag = *p_Pflag, + my_Rflag = *p_Rflag, my_Pflag = *p_Pflag, my_Zflag = *p_Zflag, my_Hflag = *p_Hflag, my_sflag = 0, my_Lflag = 0, my_lflag = 0, my_mflag = 0, my_csflag = 0, my_quflag = 0, my_dsflag = 0, my_dbflag = 0, my_drflag = 0, my_dtflag = 0, my_dxflag = 0, my_djflag = 0, my_fxflag = 0, my_doflag = 0, @@ -1403,24 +1915,28 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf my_swflag = 0, my_Yflag = 0; char *my_ets = NULL; - + char *my_proj_name = NULL; autostring abs_projectLocationURI( compose_path_name(abs_tpd_dir, projectLocationURI)); char* sub_proj_abs_work_dir = NULL; + tpd_result success = process_tpd_internal((const char*)abs_projectLocationURI, - my_actcfg, file_list_path, &my_argc, &my_argv, &my_optind, &my_ets, + my_actcfg, file_list_path, &my_argc, &my_argv, &my_optind, &my_ets, &my_proj_name, &my_gflag, &my_sflag, &my_cflag, &my_aflag, preprocess, &my_Rflag, &my_lflag, &my_mflag, &my_Pflag, &my_Lflag, recursive, force_overwrite, gen_only_top_level, NULL, &sub_proj_abs_work_dir, - sub_project_dirs, program_name, prj_graph_fp, create_symlink_list, ttcn3_prep_includes, ttcn3_prep_defines, prep_includes, prep_defines, &my_csflag, + sub_project_dirs, program_name, prj_graph_fp, create_symlink_list, ttcn3_prep_includes, ttcn3_prep_defines, ttcn3_prep_undefines, + prep_includes, prep_defines, prep_undefines, &my_csflag, &my_quflag, &my_dsflag, cxxcompiler, optlevel, optflags, &my_dbflag, &my_drflag, &my_dtflag, &my_dxflag, &my_djflag, &my_fxflag, &my_doflag, &my_gfflag, &my_lnflag, &my_isflag, &my_asflag, &my_swflag, &my_Yflag, solspeclibs, sol8speclibs, linuxspeclibs, freebsdspeclibs, win32speclibs, - ttcn3prep, linkerlibs, additionalObjects, linkerlibsearchp, Vflag, FALSE, NULL, NULL, prefix_workdir, run_command_list, seen_tpd_files); + ttcn3prep, linkerlibs, additionalObjects, linkerlibsearchp, Vflag, FALSE, &my_Zflag, + &my_Hflag, NULL, NULL, prefix_workdir, run_command_list, seen_tpd_files, required_configs); + autostring sub_proj_abs_work_dir_as(sub_proj_abs_work_dir); // ?! if (success == TPD_SUCCESS) { - + my_actcfg = get_act_config(required_configs, my_proj_name); if (recursive) { // call ttcn3_makefilegen on referenced project's tpd file // -r is not needed any more because top level process traverses all projects recursively expstring_t command = mprintf("%s -cVD", program_name); @@ -1432,6 +1948,8 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf if (*p_Rflag) command = mputc(command, 'R'); if (*p_lflag) command = mputc(command, 'l'); if (*p_mflag) command = mputc(command, 'm'); + if (*p_Zflag) command = mputc(command, 'Z'); + if (*p_Hflag) command = mputc(command, 'H'); command = mputstr(command, " -t "); command = mputstr(command, (const char*)abs_projectLocationURI); if (my_actcfg) { @@ -1491,6 +2009,7 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf Free(my_argv); // free the array; we keep the pointers Free(my_ets); + Free(my_proj_name); } else if (success == TPD_FAILED) { ERROR("Failed to process %s", (const char*)abs_projectLocationURI); @@ -1650,5 +2169,5 @@ static tpd_result process_tpd_internal(const char *p_tpd_name, const char *actcf xmlCleanupParser(); // ifdef debug xmlMemoryDump(); - return TPD_SUCCESS; + return result; } diff --git a/compiler2/xpather.h b/compiler2/xpather.h index fc5b9fc..935e225 100644 --- a/compiler2/xpather.h +++ b/compiler2/xpather.h @@ -27,6 +27,112 @@ char* str2; struct string2_list* next; }; +#ifdef __cplusplus +extern "C" +#endif +boolean isTopLevelExecutable(const char* projName); + +#ifdef __cplusplus +extern "C" +#endif +boolean isDynamicLibrary(const char* key); + +#ifdef __cplusplus +extern "C" +#endif +const char* findLibraryPath(const char* libraryName, const char* projName); + +#ifdef __cplusplus +extern "C" +#endif +const char* findLibraryName(const char* libraryName, const char* projName); + +#ifdef __cplusplus +extern "C" +#endif +void erase_libs(); + +#ifdef __cplusplus +extern "C" +#endif +const char* getLibFromProject(const char* projName); + +#ifdef __cplusplus + extern "C" +#endif +struct string_list* getExternalLibs(const char* projName); + +#ifdef __cplusplus +extern "C" +#endif +struct string_list* getExternalLibPathes(const char* projName); + +#ifdef __cplusplus +extern "C" +#endif +struct string2_list* getLinkerLibs(const char* projName); + +#ifdef __cplusplus +extern "C" +#endif +struct string_list* getRefWorkingDirs(const char* projName); + +#ifdef __cplusplus +extern "C" +#endif +boolean hasExternalLibrary(const char* libName, const char* projName); + +#ifdef __cplusplus +extern "C" +#endif +boolean hasSubProject(const char* projName); + +#ifdef __cplusplus +extern "C" +#endif +void print_libs(); + +#ifdef __cplusplus +extern "C" +#endif +boolean isTtcn3ModuleInLibrary(const char* moduleName); + +#ifdef __cplusplus +extern "C" +#endif +const char* getTPDFileName(const char* projName); + +#ifdef __cplusplus +extern "C" +#endif +const char* getPathToRootDir(const char* projName); + +#ifdef __cplusplus +extern "C" +#endif +boolean isAsn1ModuleInLibrary(const char* moduleName); + +#ifdef __cplusplus +extern "C" +#endif +boolean isSourceFileInLibrary(const char* fileName); + +#ifdef __cplusplus +extern "C" +#endif +boolean isHeaderFileInLibrary(const char* fileName); + +#ifdef __cplusplus +extern "C" +#endif +boolean isTtcnPPFileInLibrary(const char* fileName); + +#ifdef __cplusplus +extern "C" +#endif +boolean buildObjects(const char* projName, boolean add_referenced); + + /** * * @param p_tpd_name filename @@ -102,7 +208,7 @@ enum tpd_result process_tpd(const char *p_tpd_name, const char *actcfg, const char *file_list_path, int *argc, char ***argv, - int *optind, char **ets_name, + int *optind, char **ets_name, char **project_name, boolean *gnu_make, boolean *single_mode, boolean *central_storage, boolean *absolute_paths, boolean *preprocess, boolean *use_runtime_2, @@ -110,14 +216,15 @@ tpd_result process_tpd(const char *p_tpd_name, const char *actcfg, boolean *library, boolean recursive, boolean force_overwrite, boolean gen_only_top_level, const char *output_file, char** abs_work_dir, struct string_list* sub_project_dirs, const char* program_name, FILE* prj_graph_fp, struct string2_list* create_symlink_list, struct string_list* ttcn3_prep_includes, - struct string_list* ttcn3_prep_defines, struct string_list* prep_includes, struct string_list* prep_defines, - boolean *codesplit, boolean *quietly, boolean *disablesubtypecheck, char** cxxcompiler, - char** optlevel, char** optflags, boolean *disableber, boolean *disableraw, boolean *disabletext, boolean *disablexer, + struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes, + struct string_list* prep_defines, struct string_list* prep_undefines, boolean *codesplit, boolean *quietly, boolean *disablesubtypecheck, + char** cxxcompiler, char** optlevel, char** optflags, boolean *disableber, boolean *disableraw, boolean *disabletext, boolean *disablexer, boolean *disablejson, boolean *forcexerinasn, boolean *defaultasomit, boolean *gccmessageformat, boolean *linenumber, boolean *includesourceinfo, boolean *addsourcelineinfo, boolean *suppresswarnings, boolean *outparamboundness, struct string_list* solspeclibs, struct string_list* sol8speclibs, struct string_list* linuxspeclibs, struct string_list* freebsdspeclibs, struct string_list* win32speclibs, char** ttcn3preprocessor, struct string_list* linkerlibs, struct string_list* additionalObjects, struct string_list* linkerlibsearchpath, boolean Vflag, boolean Dflag, - char** generatorCommandOutput, struct string2_list* target_placement_list, boolean prefix_workdir, struct string2_list* run_command_list); + boolean *Zflag, boolean *Hflag, char** generatorCommandOutput, struct string2_list* target_placement_list, boolean prefix_workdir, struct string2_list* run_command_list, + struct string2_list* required_configs); #endif /* XPATHER_H_ */ diff --git a/core/ASN_Any.cc b/core/ASN_Any.cc index daf4620..129081b 100644 --- a/core/ASN_Any.cc +++ b/core/ASN_Any.cc @@ -25,6 +25,15 @@ void ASN_ANY::encode(const TTCN_Typedescriptor_t& p_td, tlv->put_in_buffer(p_buf); ASN_BER_TLV_t::destruct(tlv); break;} + case TTCN_EncDec::CT_JSON: { + TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); + if(!p_td.json) + TTCN_EncDec_ErrorContext::error_internal + ("No JSON descriptor available for type '%s'.", p_td.name); + JSON_Tokenizer tok(va_arg(pvar, int) != 0); + JSON_encode(p_td, tok); + p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); + break;} case TTCN_EncDec::CT_RAW: default: TTCN_error("Unknown coding method requested to encode type '%s'", @@ -48,6 +57,19 @@ void ASN_ANY::decode(const TTCN_Typedescriptor_t& p_td, BER_decode_TLV(p_td, tlv, L_form); if(tlv.isComplete) p_buf.increase_pos(tlv.get_len()); break;} + case TTCN_EncDec::CT_JSON: { + TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name); + if(!p_td.json) + TTCN_EncDec_ErrorContext::error_internal + ("No JSON descriptor available for type '%s'.", p_td.name); + JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len()); + if(JSON_decode(p_td, tok, false)<0) + ec.error(TTCN_EncDec::ET_INCOMPL_MSG, + "Can not decode type '%s', because invalid or incomplete" + " message was received" + , p_td.name); + p_buf.set_pos(tok.get_buf_pos()); + break;} case TTCN_EncDec::CT_RAW: default: TTCN_error("Unknown coding method requested to decode type '%s'", diff --git a/core/ASN_CharacterString.cc b/core/ASN_CharacterString.cc index c9c01f0..f4ae4a5 100644 --- a/core/ASN_CharacterString.cc +++ b/core/ASN_CharacterString.cc @@ -646,7 +646,7 @@ boolean CHARACTER_STRING_identification::BER_decode_TLV(const TTCN_Typedescripto // FIXME maybe: XER_encode and decode is virtually identical to EMBEDDED_PDV int CHARACTER_STRING_identification::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { int encoded_length=(int)p_buf.get_len(); @@ -655,22 +655,22 @@ int CHARACTER_STRING_identification::XER_encode(const XERdescriptor_t& p_td, flavor &= XER_MASK; switch (union_selection) { case ALT_syntaxes: - field_syntaxes->XER_encode(EMBEDDED_PDV_identification_sxs_xer_, p_buf, flavor, indent); + field_syntaxes->XER_encode(EMBEDDED_PDV_identification_sxs_xer_, p_buf, flavor, indent, 0); break; case ALT_syntax: - field_syntax->XER_encode(EMBEDDED_PDV_identification_sx_xer_, p_buf, flavor, indent); + field_syntax->XER_encode(EMBEDDED_PDV_identification_sx_xer_, p_buf, flavor, indent, 0); break; case ALT_presentation__context__id: - field_presentation__context__id->XER_encode(EMBEDDED_PDV_identification_pci_xer_, p_buf, flavor, indent); + field_presentation__context__id->XER_encode(EMBEDDED_PDV_identification_pci_xer_, p_buf, flavor, indent, 0); break; case ALT_context__negotiation: - field_context__negotiation->XER_encode(EMBEDDED_PDV_identification_cn_xer_, p_buf, flavor, indent); + field_context__negotiation->XER_encode(EMBEDDED_PDV_identification_cn_xer_, p_buf, flavor, indent, 0); break; case ALT_transfer__syntax: - field_transfer__syntax->XER_encode(EMBEDDED_PDV_identification_ts_xer_, p_buf, flavor, indent); + field_transfer__syntax->XER_encode(EMBEDDED_PDV_identification_ts_xer_, p_buf, flavor, indent, 0); break; case ALT_fixed: - field_fixed->XER_encode(EMBEDDED_PDV_identification_fix_xer_, p_buf, flavor, indent); + field_fixed->XER_encode(EMBEDDED_PDV_identification_fix_xer_, p_buf, flavor, indent, 0); break; default: TTCN_EncDec_ErrorContext::error_internal("Unknown selection."); @@ -683,7 +683,7 @@ int CHARACTER_STRING_identification::XER_encode(const XERdescriptor_t& p_td, } int CHARACTER_STRING_identification::XER_decode(const XERdescriptor_t& p_td, - XmlReaderWrap& reader, unsigned int flavor) + XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); // we are supposed to be parked on our element @@ -704,27 +704,27 @@ int CHARACTER_STRING_identification::XER_decode(const XERdescriptor_t& p_td, size_t namelen = strlen(name); switch (namelen) { case 8: // syntaxes - syntaxes().XER_decode(EMBEDDED_PDV_identification_sxs_xer_, reader, flavor); + syntaxes().XER_decode(EMBEDDED_PDV_identification_sxs_xer_, reader, flavor, 0); break; case 6: // syntax - syntax().XER_decode(EMBEDDED_PDV_identification_sx_xer_, reader, flavor); + syntax().XER_decode(EMBEDDED_PDV_identification_sx_xer_, reader, flavor, 0); break; case 23: // presentation-context-id - presentation__context__id().XER_decode(EMBEDDED_PDV_identification_pci_xer_, reader, flavor); + presentation__context__id().XER_decode(EMBEDDED_PDV_identification_pci_xer_, reader, flavor, 0); break; case 19: // context-negotiation - context__negotiation().XER_decode(EMBEDDED_PDV_identification_cn_xer_, reader, flavor); + context__negotiation().XER_decode(EMBEDDED_PDV_identification_cn_xer_, reader, flavor, 0); break; case 15: // transfer-syntax - transfer__syntax().XER_decode(EMBEDDED_PDV_identification_ts_xer_, reader, flavor); + transfer__syntax().XER_decode(EMBEDDED_PDV_identification_ts_xer_, reader, flavor, 0); break; case 5: // fixed - fixed().XER_decode(EMBEDDED_PDV_identification_fix_xer_, reader, flavor); + fixed().XER_decode(EMBEDDED_PDV_identification_fix_xer_, reader, flavor, 0); break; default: @@ -1673,14 +1673,14 @@ boolean CHARACTER_STRING_identification_syntaxes::BER_decode_TLV(const TTCN_Type } int CHARACTER_STRING_identification_syntaxes::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { int encoded_length=(int)p_buf.get_len(); begin_xml(p_td, p_buf, flavor, indent++, false); - field_abstract.XER_encode(CHARACTER_STRING_identification_sxs_abs_xer_, p_buf, flavor, indent); - field_transfer.XER_encode(CHARACTER_STRING_identification_sxs_xfr_xer_, p_buf, flavor, indent); + field_abstract.XER_encode(CHARACTER_STRING_identification_sxs_abs_xer_, p_buf, flavor, indent, 0); + field_transfer.XER_encode(CHARACTER_STRING_identification_sxs_xfr_xer_, p_buf, flavor, indent, 0); end_xml(p_td, p_buf, flavor, --indent, false); @@ -1688,7 +1688,7 @@ int CHARACTER_STRING_identification_syntaxes::XER_encode(const XERdescriptor_t& } int CHARACTER_STRING_identification_syntaxes::XER_decode( - const XERdescriptor_t& /*p_td*/, XmlReaderWrap& reader, unsigned int flavor) + const XERdescriptor_t& /*p_td*/, XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*) { // we stand on , move ahead first for (int success = reader.Read(); success == 1; success = reader.Read()) { @@ -1698,8 +1698,8 @@ int CHARACTER_STRING_identification_syntaxes::XER_decode( break; } // FIXME this assumes the right element - field_abstract.XER_decode(EMBEDDED_PDV_identification_sxs_abs_xer_, reader, flavor); - field_transfer.XER_decode(EMBEDDED_PDV_identification_sxs_xfr_xer_, reader, flavor); + field_abstract.XER_decode(EMBEDDED_PDV_identification_sxs_abs_xer_, reader, flavor, 0); + field_transfer.XER_decode(EMBEDDED_PDV_identification_sxs_xfr_xer_, reader, flavor, 0); for (int success = 1; success == 1; success = reader.Read()) { int type = reader.NodeType(); @@ -2319,14 +2319,14 @@ boolean CHARACTER_STRING_identification_context__negotiation::BER_decode_TLV(con } int CHARACTER_STRING_identification_context__negotiation::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { int encoded_length=(int)p_buf.get_len(); begin_xml(p_td, p_buf, flavor, indent++, false); - field_presentation__context__id.XER_encode(CHARACTER_STRING_identification_pci_xer_, p_buf, flavor, indent); - field_transfer__syntax .XER_encode(CHARACTER_STRING_identification_ts_xer_ , p_buf, flavor, indent); + field_presentation__context__id.XER_encode(CHARACTER_STRING_identification_pci_xer_, p_buf, flavor, indent, 0); + field_transfer__syntax .XER_encode(CHARACTER_STRING_identification_ts_xer_ , p_buf, flavor, indent, 0); end_xml(p_td, p_buf, flavor, --indent, false); @@ -2334,7 +2334,7 @@ int CHARACTER_STRING_identification_context__negotiation::XER_encode(const XERde } int CHARACTER_STRING_identification_context__negotiation::XER_decode( - const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor) + const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int type = reader.NodeType(), depth = -1; @@ -2345,8 +2345,8 @@ int CHARACTER_STRING_identification_context__negotiation::XER_decode( depth = reader.Depth(); success = reader.Read(); } - field_presentation__context__id.XER_decode(EMBEDDED_PDV_identification_cn_pci_xer_, reader, flavor); - field_transfer__syntax .XER_decode(EMBEDDED_PDV_identification_cn_tsx_xer_, reader, flavor); + field_presentation__context__id.XER_decode(EMBEDDED_PDV_identification_cn_pci_xer_, reader, flavor, 0); + field_transfer__syntax .XER_decode(EMBEDDED_PDV_identification_cn_tsx_xer_, reader, flavor, 0); for (; success == 1; success = reader.Read()) { type = reader.NodeType(); if (XML_READER_TYPE_END_ELEMENT == type) { @@ -2972,7 +2972,7 @@ void CHARACTER_STRING::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_ case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer,p_buf, XER_coding, 0); + XER_encode(*p_td.xer,p_buf, XER_coding, 0, 0); p_buf.put_c('\n'); break;} case TTCN_EncDec::CT_JSON: { @@ -3019,7 +3019,7 @@ void CHARACTER_STRING::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_ if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -3085,7 +3085,8 @@ boolean CHARACTER_STRING::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, cons return TRUE; } -int CHARACTER_STRING::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent) const +int CHARACTER_STRING::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, + unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if(!is_bound()) { TTCN_EncDec_ErrorContext::error @@ -3096,10 +3097,10 @@ int CHARACTER_STRING::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf flavor &= ~XER_RECOF; // ASN.1 character string doesn't care begin_xml(p_td, p_buf, flavor, indent++, false); - field_identification.XER_encode(CHARACTER_STRING_identification_xer_, p_buf, flavor, indent); + field_identification.XER_encode(CHARACTER_STRING_identification_xer_, p_buf, flavor, indent, 0); // data-value-descriptor is OPTIONAL and can never be present. // Its encoding is empty. - field_string__value .XER_encode(CHARACTER_STRING_data_value_xer_ , p_buf, flavor, indent); + field_string__value .XER_encode(CHARACTER_STRING_data_value_xer_ , p_buf, flavor, indent, 0); end_xml(p_td, p_buf, flavor, --indent, false); @@ -3107,7 +3108,7 @@ int CHARACTER_STRING::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf } int CHARACTER_STRING::XER_decode(const XERdescriptor_t& p_td, - XmlReaderWrap& reader, unsigned int flavor) + XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int success = reader.Ok(), depth = -1, type; @@ -3120,13 +3121,13 @@ int CHARACTER_STRING::XER_decode(const XERdescriptor_t& p_td, break; } } - field_identification .XER_decode(CHARACTER_STRING_identification_xer_ , reader, flavor); - field_data__value__descriptor.XER_decode(CHARACTER_STRING_data_value_descriptor_xer_, reader, flavor); + field_identification .XER_decode(CHARACTER_STRING_identification_xer_ , reader, flavor, 0); + field_data__value__descriptor.XER_decode(CHARACTER_STRING_data_value_descriptor_xer_, reader, flavor, 0); if (field_data__value__descriptor.is_value()) { TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "data-value-descriptor not allowed for EMBEDDED PDV"); } - field_string__value .XER_decode(CHARACTER_STRING_data_value_xer_ , reader, flavor); + field_string__value .XER_decode(CHARACTER_STRING_data_value_xer_ , reader, flavor, 0); for (success = reader.Read(); success == 1; success = reader.Read()) { type = reader.NodeType(); if (XML_READER_TYPE_END_ELEMENT == type) { diff --git a/core/ASN_CharacterString.hh b/core/ASN_CharacterString.hh index 5e0c24b..279bccc 100644 --- a/core/ASN_CharacterString.hh +++ b/core/ASN_CharacterString.hh @@ -86,9 +86,9 @@ public: ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const; boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); int XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, - XmlReaderWrap& reader, unsigned int flavor); + XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*); private: boolean BER_decode_set_selection(const ASN_BER_TLV_t& p_tlv); public: @@ -208,9 +208,9 @@ public: ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const; boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); int XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, - XmlReaderWrap& reader, unsigned int flavor); + XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*); }; class CHARACTER_STRING_identification_syntaxes_template : public Base_Template { @@ -315,9 +315,9 @@ public: ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const; boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); int XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, - XmlReaderWrap& reader, unsigned int flavor); + XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*); }; class CHARACTER_STRING_identification_context__negotiation_template : public Base_Template { @@ -430,8 +430,8 @@ public: void decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...); ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const; boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); - int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int) const; - int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int); + int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int, embed_values_enc_struct_t*) const; + int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int, embed_values_dec_struct_t*); }; class CHARACTER_STRING_template : public Base_Template { diff --git a/core/ASN_EmbeddedPDV.cc b/core/ASN_EmbeddedPDV.cc index 003b81f..7a05319 100644 --- a/core/ASN_EmbeddedPDV.cc +++ b/core/ASN_EmbeddedPDV.cc @@ -633,7 +633,7 @@ boolean EMBEDDED_PDV_identification::BER_decode_TLV(const TTCN_Typedescriptor_t& // FIXME maybe: XER_encode and decode is virtually identical to CHARACTER_STRING int EMBEDDED_PDV_identification::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { int indenting = !is_canonical(flavor); int exer = is_exer(flavor); @@ -646,22 +646,22 @@ int EMBEDDED_PDV_identification::XER_encode(const XERdescriptor_t& p_td, ++indent; switch (union_selection) { case ALT_syntaxes: - field_syntaxes->XER_encode(EMBEDDED_PDV_identification_sxs_xer_, p_buf, flavor, indent);; + field_syntaxes->XER_encode(EMBEDDED_PDV_identification_sxs_xer_, p_buf, flavor, indent, 0);; break; case ALT_syntax: - field_syntax->XER_encode(EMBEDDED_PDV_identification_sx_xer_, p_buf, flavor, indent);; + field_syntax->XER_encode(EMBEDDED_PDV_identification_sx_xer_, p_buf, flavor, indent, 0);; break; case ALT_presentation__context__id: - field_presentation__context__id->XER_encode(EMBEDDED_PDV_identification_pci_xer_, p_buf, flavor, indent);; + field_presentation__context__id->XER_encode(EMBEDDED_PDV_identification_pci_xer_, p_buf, flavor, indent, 0);; break; case ALT_context__negotiation: - field_context__negotiation->XER_encode(EMBEDDED_PDV_identification_cn_xer_, p_buf, flavor, indent);; + field_context__negotiation->XER_encode(EMBEDDED_PDV_identification_cn_xer_, p_buf, flavor, indent, 0);; break; case ALT_transfer__syntax: - field_transfer__syntax->XER_encode(EMBEDDED_PDV_identification_ts_xer_, p_buf, flavor, indent);; + field_transfer__syntax->XER_encode(EMBEDDED_PDV_identification_ts_xer_, p_buf, flavor, indent, 0);; break; case ALT_fixed: - field_fixed->XER_encode(EMBEDDED_PDV_identification_fix_xer_, p_buf, flavor, indent);; + field_fixed->XER_encode(EMBEDDED_PDV_identification_fix_xer_, p_buf, flavor, indent, 0);; break; default: TTCN_EncDec_ErrorContext::error_internal("Unknown selection."); @@ -677,7 +677,7 @@ int EMBEDDED_PDV_identification::XER_encode(const XERdescriptor_t& p_td, } int EMBEDDED_PDV_identification::XER_decode(const XERdescriptor_t& p_td, - XmlReaderWrap& reader, unsigned int flavor) + XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); // we are supposed to be parked on our element @@ -697,27 +697,27 @@ int EMBEDDED_PDV_identification::XER_decode(const XERdescriptor_t& p_td, size_t namelen = strlen(name); switch (namelen) { case 8: // syntaxes - syntaxes().XER_decode(EMBEDDED_PDV_identification_sxs_xer_, reader, flavor); + syntaxes().XER_decode(EMBEDDED_PDV_identification_sxs_xer_, reader, flavor, 0); break; case 6: // syntax - syntax().XER_decode(EMBEDDED_PDV_identification_sx_xer_, reader, flavor); + syntax().XER_decode(EMBEDDED_PDV_identification_sx_xer_, reader, flavor, 0); break; case 23: // presentation-context-id - presentation__context__id().XER_decode(EMBEDDED_PDV_identification_pci_xer_, reader, flavor); + presentation__context__id().XER_decode(EMBEDDED_PDV_identification_pci_xer_, reader, flavor, 0); break; case 19: // context-negotiation - context__negotiation().XER_decode(EMBEDDED_PDV_identification_cn_xer_, reader, flavor); + context__negotiation().XER_decode(EMBEDDED_PDV_identification_cn_xer_, reader, flavor, 0); break; case 15: // transfer-syntax - transfer__syntax().XER_decode(EMBEDDED_PDV_identification_ts_xer_, reader, flavor); + transfer__syntax().XER_decode(EMBEDDED_PDV_identification_ts_xer_, reader, flavor, 0); break; case 5: // fixed - fixed().XER_decode(EMBEDDED_PDV_identification_fix_xer_, reader, flavor); + fixed().XER_decode(EMBEDDED_PDV_identification_fix_xer_, reader, flavor, 0); break; default: @@ -1667,7 +1667,7 @@ boolean EMBEDDED_PDV_identification_syntaxes::BER_decode_TLV(const TTCN_Typedesc } int EMBEDDED_PDV_identification_syntaxes::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { int indenting = !is_canonical(flavor); int exer = is_exer(flavor); @@ -1678,8 +1678,8 @@ int EMBEDDED_PDV_identification_syntaxes::XER_encode(const XERdescriptor_t& p_td p_buf.put_s((size_t)p_td.namelens[exer] - 1 + indenting, (const unsigned char*)p_td.names[exer]); ++indent; - field_abstract.XER_encode(EMBEDDED_PDV_identification_sxs_abs_xer_, p_buf, flavor, indent); - field_transfer.XER_encode(EMBEDDED_PDV_identification_sxs_xfr_xer_, p_buf, flavor, indent); + field_abstract.XER_encode(EMBEDDED_PDV_identification_sxs_abs_xer_, p_buf, flavor, indent, 0); + field_transfer.XER_encode(EMBEDDED_PDV_identification_sxs_xfr_xer_, p_buf, flavor, indent, 0); if (indenting) do_indent(p_buf, --indent); p_buf.put_c('<'); @@ -1690,7 +1690,7 @@ int EMBEDDED_PDV_identification_syntaxes::XER_encode(const XERdescriptor_t& p_td } int EMBEDDED_PDV_identification_syntaxes::XER_decode(const XERdescriptor_t& /*p_td*/, - XmlReaderWrap& reader, unsigned int flavor) + XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*) { // we stand on , move ahead first int type; for (int success = reader.Read(); success == 1; success = reader.Read()) @@ -1701,8 +1701,8 @@ int EMBEDDED_PDV_identification_syntaxes::XER_decode(const XERdescriptor_t& /*p_ break; } // FIXME this assumes the right element - field_abstract.XER_decode(EMBEDDED_PDV_identification_sxs_abs_xer_, reader, flavor); - field_transfer.XER_decode(EMBEDDED_PDV_identification_sxs_xfr_xer_, reader, flavor); + field_abstract.XER_decode(EMBEDDED_PDV_identification_sxs_abs_xer_, reader, flavor, 0); + field_transfer.XER_decode(EMBEDDED_PDV_identification_sxs_xfr_xer_, reader, flavor, 0); for (int success = 1; success == 1; success = reader.Read()) { type = reader.NodeType(); @@ -2323,7 +2323,7 @@ boolean EMBEDDED_PDV_identification_context__negotiation::BER_decode_TLV(const T } int EMBEDDED_PDV_identification_context__negotiation::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { int indenting = !is_canonical(flavor); int exer = is_exer(flavor); @@ -2334,8 +2334,8 @@ int EMBEDDED_PDV_identification_context__negotiation::XER_encode(const XERdescri p_buf.put_s((size_t)p_td.namelens[exer] - 1 + indenting, (const unsigned char*)p_td.names[exer]); ++indent; - field_presentation__context__id.XER_encode(EMBEDDED_PDV_identification_cn_pci_xer_, p_buf, flavor, indent); - field_transfer__syntax .XER_encode(EMBEDDED_PDV_identification_cn_tsx_xer_, p_buf, flavor, indent); + field_presentation__context__id.XER_encode(EMBEDDED_PDV_identification_cn_pci_xer_, p_buf, flavor, indent, 0); + field_transfer__syntax .XER_encode(EMBEDDED_PDV_identification_cn_tsx_xer_, p_buf, flavor, indent, 0); if (indenting) do_indent(p_buf, --indent); p_buf.put_c('<'); @@ -2346,7 +2346,7 @@ int EMBEDDED_PDV_identification_context__negotiation::XER_encode(const XERdescri } int EMBEDDED_PDV_identification_context__negotiation::XER_decode( - const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor) + const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int type = reader.NodeType(), depth = -1; @@ -2357,8 +2357,8 @@ int EMBEDDED_PDV_identification_context__negotiation::XER_decode( depth = reader.Depth(); success = reader.Read(); } - field_presentation__context__id.XER_decode(EMBEDDED_PDV_identification_cn_pci_xer_, reader, flavor); - field_transfer__syntax .XER_decode(EMBEDDED_PDV_identification_cn_tsx_xer_, reader, flavor); + field_presentation__context__id.XER_decode(EMBEDDED_PDV_identification_cn_pci_xer_, reader, flavor, 0); + field_transfer__syntax .XER_decode(EMBEDDED_PDV_identification_cn_tsx_xer_, reader, flavor, 0); for (; success == 1; success = reader.Read()) { type = reader.NodeType(); if (XML_READER_TYPE_END_ELEMENT == type) { @@ -2984,7 +2984,7 @@ void EMBEDDED_PDV::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer,p_buf, XER_coding, 0); + XER_encode(*p_td.xer,p_buf, XER_coding, 0, 0); break;} case TTCN_EncDec::CT_JSON: { TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); @@ -3030,7 +3030,7 @@ void EMBEDDED_PDV::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -3097,7 +3097,7 @@ boolean EMBEDDED_PDV::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const AS } int EMBEDDED_PDV::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const { + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if(!is_bound()) { TTCN_EncDec_ErrorContext::error (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value."); @@ -3111,13 +3111,13 @@ int EMBEDDED_PDV::XER_encode(const XERdescriptor_t& p_td, p_buf.put_s((size_t)p_td.namelens[exer] - 1 + indenting, (const unsigned char*)p_td.names[exer]); flavor &= XER_MASK; ++indent; - field_identification .XER_encode(EMBEDDED_PDV_identification_xer_ , p_buf, flavor, indent); + field_identification .XER_encode(EMBEDDED_PDV_identification_xer_ , p_buf, flavor, indent, 0); if (field_data__value__descriptor.is_value()) { TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "data-value-descriptor not allowed for EMBEDDED PDV"); } - field_data__value__descriptor.XER_encode(EMBEDDED_PDV_data_value_descriptor_xer_, p_buf, flavor, indent); - field_data__value .XER_encode(EMBEDDED_PDV_data_value_xer_ , p_buf, flavor, indent); + field_data__value__descriptor.XER_encode(EMBEDDED_PDV_data_value_descriptor_xer_, p_buf, flavor, indent, 0); + field_data__value .XER_encode(EMBEDDED_PDV_data_value_xer_ , p_buf, flavor, indent, 0); if (indenting) do_indent(p_buf, --indent); p_buf.put_c('<'); @@ -3127,7 +3127,7 @@ int EMBEDDED_PDV::XER_encode(const XERdescriptor_t& p_td, return (int)p_buf.get_len() - encoded_length; } -int EMBEDDED_PDV::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor) +int EMBEDDED_PDV::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int depth = 1, type, success; @@ -3140,13 +3140,13 @@ int EMBEDDED_PDV::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, break; } } - field_identification .XER_decode(EMBEDDED_PDV_identification_xer_ , reader, flavor); - field_data__value__descriptor.XER_decode(EMBEDDED_PDV_data_value_descriptor_xer_, reader, flavor); + field_identification .XER_decode(EMBEDDED_PDV_identification_xer_ , reader, flavor, 0); + field_data__value__descriptor.XER_decode(EMBEDDED_PDV_data_value_descriptor_xer_, reader, flavor, 0); if (field_data__value__descriptor.is_value()) { TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "data-value-descriptor not allowed for EMBEDDED PDV"); } - field_data__value .XER_decode(EMBEDDED_PDV_data_value_xer_ , reader, flavor); + field_data__value .XER_decode(EMBEDDED_PDV_data_value_xer_ , reader, flavor, 0); for (success = reader.Read(); success == 1; success = reader.Read()) { type = reader.NodeType(); if (XML_READER_TYPE_END_ELEMENT == type) { diff --git a/core/ASN_EmbeddedPDV.hh b/core/ASN_EmbeddedPDV.hh index 6dce034..0ee44cf 100644 --- a/core/ASN_EmbeddedPDV.hh +++ b/core/ASN_EmbeddedPDV.hh @@ -86,9 +86,9 @@ public: ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const; boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); int XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor); + unsigned int flavor, embed_values_dec_struct_t*); private: boolean BER_decode_set_selection(const ASN_BER_TLV_t& p_tlv); public: @@ -207,8 +207,8 @@ public: //void decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...); ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const; boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); - int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int) const; - int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int); + int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int, embed_values_enc_struct_t*) const; + int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int, embed_values_dec_struct_t*); }; class EMBEDDED_PDV_identification_syntaxes_template : public Base_Template { @@ -312,8 +312,8 @@ public: //void decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...); ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const; boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); - int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int) const; - int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int); + int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int, embed_values_enc_struct_t*) const; + int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int, embed_values_dec_struct_t*); }; class EMBEDDED_PDV_identification_context__negotiation_template : public Base_Template { @@ -423,8 +423,8 @@ public: void decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...); ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const; boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); - int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int) const; - int XER_decode(const XERdescriptor_t&, XmlReaderWrap&, unsigned int); + int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int, embed_values_enc_struct_t*) const; + int XER_decode(const XERdescriptor_t&, XmlReaderWrap&, unsigned int, embed_values_dec_struct_t*); }; class EMBEDDED_PDV_template : public Base_Template { diff --git a/core/ASN_External.cc b/core/ASN_External.cc index 94836ac..65e7e3d 100644 --- a/core/ASN_External.cc +++ b/core/ASN_External.cc @@ -102,9 +102,9 @@ namespace { /* anonymous namespace */ ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const; boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); int XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor); + unsigned int flavor, embed_values_dec_struct_t*); private: boolean BER_decode_set_selection(const ASN_BER_TLV_t& p_tlv); public: @@ -159,9 +159,9 @@ namespace { /* anonymous namespace */ ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const; boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); int XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor); + unsigned int flavor, embed_values_dec_struct_t*); }; /** Transform the information from the visible format to the encoding format @@ -398,7 +398,7 @@ namespace { /* anonymous namespace */ } int EXTERNALtransfer_encoding::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { int indenting = !is_canonical(flavor); int exer = is_exer(flavor); @@ -411,13 +411,13 @@ namespace { /* anonymous namespace */ ++indent; switch (union_selection) { case ALT_single__ASN1__type: - field_single__ASN1__type->XER_encode(EXTERNAL_encoding_singleASN_xer_, p_buf, flavor, indent); + field_single__ASN1__type->XER_encode(EXTERNAL_encoding_singleASN_xer_, p_buf, flavor, indent, 0); break; case ALT_octet__aligned: - field_octet__aligned ->XER_encode(EXTERNAL_encoding_octet_aligned_xer_, p_buf, flavor, indent); + field_octet__aligned ->XER_encode(EXTERNAL_encoding_octet_aligned_xer_, p_buf, flavor, indent, 0); break; case ALT_arbitrary: - field_arbitrary ->XER_encode(EXTERNAL_encoding_arbitrary_xer_, p_buf, flavor, indent); + field_arbitrary ->XER_encode(EXTERNAL_encoding_arbitrary_xer_, p_buf, flavor, indent, 0); break; case UNBOUND_VALUE: TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, @@ -438,7 +438,7 @@ namespace { /* anonymous namespace */ } int EXTERNALtransfer_encoding::XER_decode(const XERdescriptor_t& p_td, - XmlReaderWrap& reader, unsigned int flavor) + XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int success = reader.Ok(), type, depth = -1; @@ -461,15 +461,15 @@ namespace { /* anonymous namespace */ switch (*name) { case 's': // single-ASN1-type - single__ASN1__type().XER_decode(EXTERNAL_encoding_singleASN_xer_, reader, flavor); + single__ASN1__type().XER_decode(EXTERNAL_encoding_singleASN_xer_, reader, flavor, 0); break; case 'o': // octet-aligned - octet__aligned().XER_decode(EXTERNAL_encoding_octet_aligned_xer_, reader, flavor); + octet__aligned().XER_decode(EXTERNAL_encoding_octet_aligned_xer_, reader, flavor, 0); break; case 'a': // arbitrary - arbitrary().XER_decode(EXTERNAL_encoding_arbitrary_xer_, reader, flavor); + arbitrary().XER_decode(EXTERNAL_encoding_arbitrary_xer_, reader, flavor, 0); break; default: @@ -555,7 +555,7 @@ namespace { /* anonymous namespace */ } int EXTERNALtransfer::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { int indenting = !is_canonical(flavor); int exer = is_exer(flavor); @@ -566,10 +566,10 @@ namespace { /* anonymous namespace */ p_buf.put_s((size_t)p_td.namelens[exer] - 1 + indenting, (const unsigned char*)p_td.names[exer]); ++indent; - field_direct__reference .XER_encode(EXTERNAL_direct_reference_xer_ , p_buf, flavor, indent); - field_indirect__reference .XER_encode(EXTERNAL_indirect_reference_xer_ , p_buf, flavor, indent); - field_data__value__descriptor.XER_encode(EXTERNAL_data_value_descriptor_xer_, p_buf, flavor, indent); - field_encoding .XER_encode(EXTERNAL_encoding_xer_ , p_buf, flavor, indent); + field_direct__reference .XER_encode(EXTERNAL_direct_reference_xer_ , p_buf, flavor, indent, 0); + field_indirect__reference .XER_encode(EXTERNAL_indirect_reference_xer_ , p_buf, flavor, indent, 0); + field_data__value__descriptor.XER_encode(EXTERNAL_data_value_descriptor_xer_, p_buf, flavor, indent, 0); + field_encoding .XER_encode(EXTERNAL_encoding_xer_ , p_buf, flavor, indent, 0); if (indenting) do_indent(p_buf, --indent); p_buf.put_c('<'); @@ -579,7 +579,8 @@ namespace { /* anonymous namespace */ return (int)p_buf.get_len() - encoded_length; } - int EXTERNALtransfer::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor) + int EXTERNALtransfer::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, + unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int success = reader.Ok(), depth = -1; @@ -593,10 +594,10 @@ namespace { /* anonymous namespace */ } } - field_direct__reference .XER_decode(EXTERNAL_direct_reference_xer_ , reader, flavor); - field_indirect__reference .XER_decode(EXTERNAL_indirect_reference_xer_ , reader, flavor); - field_data__value__descriptor.XER_decode(EXTERNAL_data_value_descriptor_xer_, reader, flavor); - field_encoding .XER_decode(EXTERNAL_encoding_xer_ , reader, flavor); + field_direct__reference .XER_decode(EXTERNAL_direct_reference_xer_ , reader, flavor, 0); + field_indirect__reference .XER_decode(EXTERNAL_indirect_reference_xer_ , reader, flavor, 0); + field_data__value__descriptor.XER_decode(EXTERNAL_data_value_descriptor_xer_, reader, flavor, 0); + field_encoding .XER_decode(EXTERNAL_encoding_xer_ , reader, flavor, 0); for (success = reader.Read(); success == 1; success = reader.Read()) { int type = reader.NodeType(); @@ -694,7 +695,7 @@ boolean EXTERNAL::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BE } int EXTERNAL::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if(!is_bound()) { TTCN_EncDec_ErrorContext::error @@ -702,14 +703,14 @@ int EXTERNAL::XER_encode(const XERdescriptor_t& p_td, } EXTERNALtransfer xfer; xfer.load(*this); - return xfer.XER_encode(p_td, p_buf, flavor, indent); + return xfer.XER_encode(p_td, p_buf, flavor, indent, 0); } int EXTERNAL::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor) + unsigned int flavor, embed_values_dec_struct_t*) { EXTERNALtransfer xfer; - xfer.XER_decode(p_td, reader, flavor); + xfer.XER_decode(p_td, reader, flavor, 0); transfer(&xfer); return 1; // decode successful } @@ -3182,7 +3183,7 @@ void EXTERNAL::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTC case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer, p_buf, XER_coding, 0); + XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); break;} case TTCN_EncDec::CT_JSON: { TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); @@ -3228,7 +3229,7 @@ void EXTERNAL::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTC if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} diff --git a/core/ASN_External.hh b/core/ASN_External.hh index cb926e1..9405c25 100644 --- a/core/ASN_External.hh +++ b/core/ASN_External.hh @@ -403,9 +403,9 @@ public: ASN_BER_TLV_t* BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const; boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); int XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor); + unsigned int flavor, embed_values_dec_struct_t*); }; class EXTERNAL_template : public Base_Template { diff --git a/core/ASN_Null.cc b/core/ASN_Null.cc index 800c533..ab3c9a2 100644 --- a/core/ASN_Null.cc +++ b/core/ASN_Null.cc @@ -105,7 +105,16 @@ void ASN_NULL::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer, p_buf, XER_coding, 0); + XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); + break;} + case TTCN_EncDec::CT_JSON: { + TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); + if(!p_td.json) + TTCN_EncDec_ErrorContext::error_internal + ("No JSON descriptor available for type '%s'.", p_td.name); + JSON_Tokenizer tok(va_arg(pvar, int) != 0); + JSON_encode(p_td, tok); + p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); break;} case TTCN_EncDec::CT_RAW: default: @@ -130,7 +139,7 @@ void ASN_NULL::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, if(tlv.isComplete) p_buf.increase_pos(tlv.get_len()); break;} case TTCN_EncDec::CT_XER: { - TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); + TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); XmlReaderWrap reader(p_buf); int success = reader.Read(); @@ -139,10 +148,23 @@ void ASN_NULL::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} + case TTCN_EncDec::CT_JSON: { + TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name); + if(!p_td.json) + TTCN_EncDec_ErrorContext::error_internal + ("No JSON descriptor available for type '%s'.", p_td.name); + JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len()); + if(JSON_decode(p_td, tok, false)<0) + ec.error(TTCN_EncDec::ET_INCOMPL_MSG, + "Can not decode type '%s', because invalid or incomplete" + " message was received" + , p_td.name); + p_buf.set_pos(tok.get_buf_pos()); + break;} case TTCN_EncDec::CT_RAW: default: TTCN_error("Unknown coding method requested to decode type '%s'", @@ -181,7 +203,7 @@ boolean ASN_NULL::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, } int ASN_NULL::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent ) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { int exer = is_exer(flavor); TTCN_EncDec_ErrorContext ec("While XER encoding NULL type: "); @@ -205,7 +227,7 @@ int ASN_NULL::XER_encode(const XERdescriptor_t& p_td, } int ASN_NULL::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor) + unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); TTCN_EncDec_ErrorContext ec("While XER decoding NULL type: "); @@ -235,6 +257,32 @@ int ASN_NULL::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, return 1; // decode successful } +int ASN_NULL::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const +{ + if (!is_bound()) { + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound ASN.1 NULL value."); + return -1; + } + + return p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL); +} + +int ASN_NULL::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent) +{ + json_token_t token = JSON_TOKEN_NONE; + int dec_len = p_tok.get_next_token(&token, NULL, NULL); + if (JSON_TOKEN_ERROR == token) { + JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, ""); + return JSON_ERROR_FATAL; + } + else if (JSON_TOKEN_LITERAL_NULL != token) { + return JSON_ERROR_INVALID_TOKEN; + } + bound_flag = TRUE; + return dec_len; +} + boolean operator==(asn_null_type, const ASN_NULL& other_value) { if (!other_value.is_bound()) TTCN_error("The right operand of comparison " diff --git a/core/ASN_Null.hh b/core/ASN_Null.hh index e83c564..dae43d0 100644 --- a/core/ASN_Null.hh +++ b/core/ASN_Null.hh @@ -69,9 +69,17 @@ public: boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); int XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor); + unsigned int flavor, embed_values_dec_struct_t*); + + /** Encodes accordingly to the JSON encoding rules. + * Returns the length of the encoded data. */ + int JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const; + + /** Decodes accordingly to the JSON decoding rules. + * Returns the length of the encoded data. */ + int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); }; extern boolean operator==(asn_null_type par_value, const ASN_NULL& other_value); diff --git a/core/Array.hh b/core/Array.hh index a85ab09..bfbfde7 100644 --- a/core/Array.hh +++ b/core/Array.hh @@ -85,6 +85,13 @@ public: } TTCN_Logger::log_event_str(" }"); } + +#ifdef TITAN_RUNTIME_2 + // Dummy functions, only used in record of/set of in RT2 (the referenced indices + // cannot be deleted, since arrays have a fixed size) + void add_refd_index(int) {} + void remove_refd_index(int) {} +#endif }; extern unsigned int get_port_array_index(int index_value, @@ -145,6 +152,13 @@ public: } TTCN_Logger::log_event_str(" }"); } + +#ifdef TITAN_RUNTIME_2 + // Dummy functions, only used in record of/set of in RT2 (the referenced indices + // cannot be deleted, since arrays have a fixed size) + void add_refd_index(int) {} + void remove_refd_index(int) {} +#endif }; //////////////////////////////////////////////////////////////////////////////// @@ -227,10 +241,12 @@ public: * Returns the length of the decoded data. */ int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); - // Dummy functions, only used in record of/set of (the referenced indices +#ifdef TITAN_RUNTIME_2 + // Dummy functions, only used in record of/set of in RT2 (the referenced indices // cannot be deleted, since arrays have a fixed size) void add_refd_index(int) {} void remove_refd_index(int) {} +#endif }; template diff --git a/core/Basetype.cc b/core/Basetype.cc index d253707..104e6b0 100644 --- a/core/Basetype.cc +++ b/core/Basetype.cc @@ -16,6 +16,7 @@ #include "JSON.hh" #include "XmlReader.hh" #include "Module_list.hh" +#include "Universal_charstring.hh" #include @@ -74,7 +75,7 @@ void Base_Type::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, if(!p_td.xer) TTCN_EncDec_ErrorContext::error_internal( "No XER descriptor available for type '%s'.", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*(p_td.xer),p_buf, XER_coding, 0); + XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0); p_buf.put_c('\n'); break;} case TTCN_EncDec::CT_JSON: { @@ -148,7 +149,7 @@ void Base_Type::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, for (int success=reader.Read(); success==1; success=reader.Read()) { if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break; } - XER_decode(*(p_td.xer), reader, XER_coding); + XER_decode(*(p_td.xer), reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -966,14 +967,15 @@ int Base_Type::RAW_decode(const TTCN_Typedescriptor_t& p_td, } int Base_Type::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer&, unsigned int, int) const + TTCN_Buffer&, unsigned int, int, embed_values_enc_struct_t*) const { TTCN_error("XER encoding requested for type '%-.*s' which has no" " XER encoding method.", p_td.namelens[0]-2, p_td.names[0]); return 0; } -int Base_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap&, unsigned int) { +int Base_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap&, + unsigned int, embed_values_dec_struct_t*) { TTCN_error("XER decoding requested for type '%-.*s' which has no" " XER decoding method.", p_td.namelens[0]-2, p_td.names[0]); return 0; @@ -1096,7 +1098,7 @@ const TTCN_Typedescriptor_t VERDICTTYPE_descr_={"verdicttype", NULL, NULL, NULL, &VERDICTTYPE_xer_, &VERDICTTYPE_json_, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t OBJID_descr_={"OBJECT IDENTIFIER", &OBJID_ber_, - NULL, NULL, &OBJID_xer_, NULL, TTCN_Typedescriptor_t::OBJID}; + NULL, NULL, &OBJID_xer_, &OBJID_json_, TTCN_Typedescriptor_t::OBJID}; const TTCN_Typedescriptor_t BITSTRING_descr_={"BIT STRING", &BITSTRING_ber_, &BITSTRING_raw_, NULL, &BITSTRING_xer_, &BITSTRING_json_, TTCN_Typedescriptor_t::DONTCARE}; @@ -1120,10 +1122,10 @@ const TTCN_Typedescriptor_t DEFAULT_descr_={"default", NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t ASN_NULL_descr_={"NULL", &ASN_NULL_ber_, NULL, - NULL, &ASN_NULL_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; + NULL, &ASN_NULL_xer_, &ASN_NULL_json_, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t ASN_ANY_descr_={"ANY", &ASN_ANY_ber_, NULL, - NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + NULL, NULL, &ASN_ANY_json_, TTCN_Typedescriptor_t::DONTCARE}; const TTCN_Typedescriptor_t EXTERNAL_descr_={"EXTERNAL", &EXTERNAL_ber_, NULL, NULL, &EXTERNAL_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; @@ -1141,7 +1143,7 @@ const TTCN_Typedescriptor_t UTF8String_descr_={"UTF8String", &UTF8String_ber_, NULL, NULL, &UTF8String_xer_, NULL, TTCN_Typedescriptor_t::UTF8STRING}; const TTCN_Typedescriptor_t ASN_ROID_descr_={"RELATIVE-OID", &ASN_ROID_ber_, - NULL, NULL, &ASN_ROID_xer_, NULL, TTCN_Typedescriptor_t::ROID}; + NULL, NULL, &ASN_ROID_xer_, &ASN_ROID_json_, TTCN_Typedescriptor_t::ROID}; const TTCN_Typedescriptor_t NumericString_descr_={"NumericString", &NumericString_ber_, NULL, NULL, &NumericString_xer_, NULL, TTCN_Typedescriptor_t::DONTCARE}; diff --git a/core/Basetype.hh b/core/Basetype.hh index fca5d1c..2e49375 100644 --- a/core/Basetype.hh +++ b/core/Basetype.hh @@ -15,6 +15,7 @@ #include "Vector.hh" #ifdef TITAN_RUNTIME_2 #include "Struct_of.hh" +#include "XER.hh" #endif struct ASN_BERdescriptor_t; @@ -25,6 +26,8 @@ struct XERdescriptor_t; struct TTCN_JSONdescriptor_t; class XmlReaderWrap; class Module_Param; +struct embed_values_enc_struct_t; +struct embed_values_dec_struct_t; /** @brief Type descriptor * @@ -204,7 +207,7 @@ public: */ virtual void set_to_present(); /** @} */ - + virtual ~Base_Type() { } #endif @@ -444,15 +447,16 @@ public: * @param p_buf buffer * @param flavor one of XER_flavor values * @param indent indentation level + * @param emb_val embed values data (only relevant for record of types) * @return number of bytes written into the buffer */ VIRTUAL_IF_RUNTIME_2 int XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t* emb_val) const; #ifdef TITAN_RUNTIME_2 virtual int XER_encode_negtest(const Erroneous_descriptor_t* /*p_err_descr*/, const XERdescriptor_t& /*p_td*/, TTCN_Buffer& /*p_buf*/, - unsigned int /*flavor*/, int /*indent*/) const; + unsigned int /*flavor*/, int /*indent*/, embed_values_enc_struct_t* /*emb_val*/) const; #endif /** Decode the current object from the supplied buffer. @@ -482,10 +486,11 @@ public: * @param p_td type descriptor * @param reader Wrapper around the XML processor * @param flavor one of XER_flavor values + * @param emb_val embed values data (only relevant for record of types) * @return number of bytes "consumed" */ VIRTUAL_IF_RUNTIME_2 int XER_decode(const XERdescriptor_t& p_td, - XmlReaderWrap& reader, unsigned int flavor); + XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t* emb_val); /** Return an array of namespace declarations. * @@ -651,15 +656,17 @@ protected: } *val_ptr; Erroneous_descriptor_t* err_descr; - /** Stores the indices of elements that are referenced by 'out' and 'inout' parameters. - * These elements must not be deleted.*/ - Vector refd_indices; - - /** Cached maximum value of \a refd_indices (default: -1).*/ - int max_refd_index; + struct refd_index_struct { + /** Stores the indices of elements that are referenced by 'out' and 'inout' parameters. + * These elements must not be deleted.*/ + Vector refd_indices; + + /** Cached maximum value of \a refd_indices (default: -1).*/ + int max_refd_index; + } *refd_ind_ptr; static boolean compare_function(const Record_Of_Type *left_ptr, int left_index, const Record_Of_Type *right_ptr, int right_index); - Record_Of_Type() : val_ptr(NULL), err_descr(NULL), max_refd_index(-1) {} + Record_Of_Type() : val_ptr(NULL), err_descr(NULL), refd_ind_ptr(NULL) {} Record_Of_Type(null_type other_value); Record_Of_Type(const Record_Of_Type& other_value); /// Assignment disabled @@ -765,14 +772,14 @@ public: virtual int TEXT_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, Limit_Token_List&, boolean no_err=FALSE, boolean first_call=TRUE); virtual int XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent) const; + unsigned int flavor, int indent, embed_values_enc_struct_t*) const; virtual int XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, - const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned flavor, int indent) const; + const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned flavor, int indent, embed_values_enc_struct_t*) const; /// Helper for XER_encode_negtest int encode_element(int i, const Erroneous_values_t* err_vals, const Erroneous_descriptor_t* emb_descr, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; - virtual int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int); + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t* emb_val) const; + virtual int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int, embed_values_dec_struct_t*); virtual boolean isXerAttribute() const; virtual boolean isXmlValueList() const; @@ -905,11 +912,12 @@ public: virtual int TEXT_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, Limit_Token_List&, boolean no_err=FALSE, boolean first_call=TRUE); virtual int XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent) const; + unsigned int flavor, int indent, embed_values_enc_struct_t*) const; virtual int XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent) const; - virtual int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int); + unsigned int flavor, int indent, embed_values_enc_struct_t*) const; + virtual int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, + unsigned int, embed_values_dec_struct_t*); /// @{ /// Methods overridden in the derived (generated) class virtual int get_xer_num_attr() const { return 0; /* default */ } @@ -932,7 +940,7 @@ public: private: /// Helper for XER_encode_negtest int encode_field(int i, const Erroneous_values_t* err_vals, const Erroneous_descriptor_t* emb_descr, - TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent, embed_values_enc_struct_t* emb_val) const; }; //////////////////////////////////////////////////////////////////////////////// @@ -978,8 +986,9 @@ public: virtual int TEXT_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, Limit_Token_List&, boolean no_err=FALSE, boolean first_call=TRUE); virtual int XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent) const; - virtual int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int); + unsigned int flavor, int indent, embed_values_enc_struct_t*) const; + virtual int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, + unsigned int, embed_values_dec_struct_t*); /** Encodes accordingly to the JSON encoding rules. * Returns the length of the encoded data. */ diff --git a/core/Bitstring.cc b/core/Bitstring.cc index 513bc29..d55b1fa 100644 --- a/core/Bitstring.cc +++ b/core/Bitstring.cc @@ -612,10 +612,10 @@ void BITSTRING::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer, p_buf, XER_coding, 0); + XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); break;} case TTCN_EncDec::CT_JSON: { - TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); + TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal ("No JSON descriptor available for type '%s'.", p_td.name); @@ -665,7 +665,7 @@ void BITSTRING::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, , p_td.name); break;} case TTCN_EncDec::CT_XER: { - TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); + TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); XmlReaderWrap reader(p_buf); int success = reader.Read(); @@ -674,7 +674,7 @@ void BITSTRING::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -1008,7 +1008,7 @@ int BITSTRING::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff, } int BITSTRING::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if(!is_bound()) { TTCN_EncDec_ErrorContext::error @@ -1032,7 +1032,7 @@ int BITSTRING::XER_encode(const XERdescriptor_t& p_td, } int BITSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor) + unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int success = reader.Ok(), depth = -1, type; diff --git a/core/Bitstring.hh b/core/Bitstring.hh index ed25023..f106161 100644 --- a/core/Bitstring.hh +++ b/core/Bitstring.hh @@ -172,8 +172,8 @@ public: int RAW_decode(const TTCN_Typedescriptor_t& , TTCN_Buffer&, int, raw_order_t, boolean no_err=FALSE, int sel_field=-1, boolean first_call=TRUE); - int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int) const; - int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int); + int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int, embed_values_enc_struct_t*) const; + int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int, embed_values_dec_struct_t*); /** Encodes accordingly to the JSON encoding rules. * Returns the length of the encoded data. */ diff --git a/core/Boolean.cc b/core/Boolean.cc index 80bc0ec..210ff85 100644 --- a/core/Boolean.cc +++ b/core/Boolean.cc @@ -204,7 +204,7 @@ void BOOLEAN::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer, p_buf, XER_coding, 0); + XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); break;} case TTCN_EncDec::CT_JSON: { TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); @@ -275,7 +275,7 @@ void BOOLEAN::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, , p_td.name); break;} case TTCN_EncDec::CT_XER: { - TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); + TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); XmlReaderWrap reader(p_buf); for (int success = reader.Read(); success==1; success=reader.Read()) { @@ -283,7 +283,7 @@ void BOOLEAN::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -575,7 +575,7 @@ int BOOLEAN::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff, } int BOOLEAN::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if(!is_bound()) { TTCN_EncDec_ErrorContext::error @@ -608,7 +608,7 @@ int BOOLEAN::XER_encode(const XERdescriptor_t& p_td, } int BOOLEAN::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor) + unsigned int flavor, embed_values_dec_struct_t*) { const boolean exer = is_exer(flavor); int XMLValueList = !exer && is_record_of(flavor); diff --git a/core/Boolean.hh b/core/Boolean.hh index 2a1c07b..0807ea5 100644 --- a/core/Boolean.hh +++ b/core/Boolean.hh @@ -102,9 +102,9 @@ public: int TEXT_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, Limit_Token_List&, boolean no_err=FALSE, boolean first_call=TRUE); int XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor); + unsigned int flavor, embed_values_dec_struct_t*); /** Encodes accordingly to the JSON encoding rules. * Returns the length of the encoded data. */ diff --git a/core/Charstring.cc b/core/Charstring.cc index c0cbe33..180fc91 100644 --- a/core/Charstring.cc +++ b/core/Charstring.cc @@ -731,7 +731,7 @@ void CHARSTRING::encode(const TTCN_Typedescriptor_t& p_td, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer, p_buf, XER_coding, 0); + XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); p_buf.put_c('\n'); break;} case TTCN_EncDec::CT_JSON: { @@ -804,7 +804,7 @@ void CHARSTRING::decode(const TTCN_Typedescriptor_t& p_td, , p_td.name); break;} case TTCN_EncDec::CT_XER: { - TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); + TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); XmlReaderWrap reader(p_buf); int success = reader.Read(); @@ -813,7 +813,7 @@ void CHARSTRING::decode(const TTCN_Typedescriptor_t& p_td, if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -1145,7 +1145,7 @@ extern const char cb64[]= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int CHARSTRING::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if(!is_bound()) { TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, @@ -1270,7 +1270,7 @@ unsigned int xlate(cbyte*in, int phase, unsigned char*dest) { } int CHARSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor) { + unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int success = reader.Ok(), depth = -1; diff --git a/core/Charstring.hh b/core/Charstring.hh index 22a2c56..4ca62b4 100644 --- a/core/Charstring.hh +++ b/core/Charstring.hh @@ -205,8 +205,8 @@ public: TTCN_Buffer&) const; int TEXT_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, Limit_Token_List&, boolean no_err=FALSE, boolean first_call=TRUE); - int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int) const; - int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int); + int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int, embed_values_enc_struct_t*) const; + int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int, embed_values_dec_struct_t*); /** Returns the charstring in the format a string would appear in C or TTCN-3 code. * Inserts double quotation marks to the beginning and end of the string and diff --git a/core/Float.cc b/core/Float.cc index 5a3d83d..50c1c91 100644 --- a/core/Float.cc +++ b/core/Float.cc @@ -290,7 +290,7 @@ void FLOAT::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer, p_buf, XER_coding, 0); + XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); break;} case TTCN_EncDec::CT_JSON: { TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); @@ -343,7 +343,7 @@ void FLOAT::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, , p_td.name); break;} case TTCN_EncDec::CT_XER: { - TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); + TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); XmlReaderWrap reader(p_buf); for (int success = reader.Read(); success==1; success=reader.Read()) { @@ -351,7 +351,7 @@ void FLOAT::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -765,7 +765,7 @@ int FLOAT::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff, } int FLOAT::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if(!is_bound()) { TTCN_EncDec_ErrorContext::error( @@ -794,7 +794,7 @@ int FLOAT::XER_encode(const XERdescriptor_t& p_td, } int FLOAT::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor) + unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int success = reader.Ok(), depth = -1; diff --git a/core/Float.hh b/core/Float.hh index 76e32b4..013d39d 100644 --- a/core/Float.hh +++ b/core/Float.hh @@ -136,9 +136,9 @@ public: int sel_field=-1, boolean first_call=TRUE); int XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor); + unsigned int flavor, embed_values_dec_struct_t*); /** Encodes accordingly to the JSON encoding rules. * Returns the length of the encoded data. */ diff --git a/core/Hexstring.cc b/core/Hexstring.cc index 04c6746..27c7e4a 100644 --- a/core/Hexstring.cc +++ b/core/Hexstring.cc @@ -623,7 +623,7 @@ void HEXSTRING::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer, p_buf, XER_coding, 0); + XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); break;} case TTCN_EncDec::CT_JSON: { TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); @@ -665,7 +665,7 @@ void HEXSTRING::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, " message was received", p_td.name); break;} case TTCN_EncDec::CT_XER: { - TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); + TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); XmlReaderWrap reader(p_buf); int success = reader.Read(); @@ -674,12 +674,12 @@ void HEXSTRING::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} case TTCN_EncDec::CT_JSON: { - TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); + TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name); if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal ("No JSON descriptor available for type '%s'.", p_td.name); @@ -790,7 +790,7 @@ extern char base64_decoder_table[256]; extern const char cb64[]; int HEXSTRING::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if(!is_bound()) { TTCN_EncDec_ErrorContext::error @@ -864,7 +864,7 @@ Because of this, the bit shifting is different. The first three bytes */ int HEXSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor) + unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int success = reader.Ok(), depth = -1, type; diff --git a/core/Hexstring.hh b/core/Hexstring.hh index c4392ab..1fd91e8 100644 --- a/core/Hexstring.hh +++ b/core/Hexstring.hh @@ -125,9 +125,9 @@ public: int RAW_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, int, raw_order_t, boolean no_err=FALSE, int sel_field=-1, boolean first_call=TRUE); int XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent) const; + unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor); + unsigned int flavor, embed_values_dec_struct_t*); /** Encodes accordingly to the JSON encoding rules. * Returns the length of the encoded data. */ diff --git a/core/Integer.cc b/core/Integer.cc index 331cd94..b997527 100644 --- a/core/Integer.cc +++ b/core/Integer.cc @@ -715,7 +715,7 @@ void INTEGER::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer, p_buf, XER_coding, 0); + XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); break;} case TTCN_EncDec::CT_JSON: { TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); @@ -794,7 +794,7 @@ void INTEGER::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -1265,7 +1265,7 @@ int INTEGER::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff, } int INTEGER::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent) const + unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if (!is_bound()) { TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, @@ -1295,7 +1295,7 @@ int INTEGER::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, } int INTEGER::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor) + unsigned int flavor, embed_values_dec_struct_t*) { const boolean exer = is_exer(flavor); int depth = -1, success = reader.Ok(), type; diff --git a/core/Integer.hh b/core/Integer.hh index 1e48b62..bf6ec35 100644 --- a/core/Integer.hh +++ b/core/Integer.hh @@ -161,11 +161,11 @@ public: /** @brief Encode according to XML Encoding Rules. **/ int XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, - int indent) const; + int indent, embed_values_enc_struct_t*) const; /** @brief Decode according to XML Encoding Rules. **/ int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor); + unsigned int flavor, embed_values_dec_struct_t*); /** Encodes accordingly to the JSON encoding rules. * Returns the length of the encoded data. */ diff --git a/core/JSON.cc b/core/JSON.cc index 59b62db..ad429c4 100644 --- a/core/JSON.cc +++ b/core/JSON.cc @@ -47,3 +47,13 @@ const TTCN_JSONdescriptor_t TeletexString_json_ = { false, NULL, false, NULL }; const TTCN_JSONdescriptor_t VideotexString_json_ = { false, NULL, false, NULL }; const TTCN_JSONdescriptor_t VisibleString_json_ = { false, NULL, false, NULL }; + +const TTCN_JSONdescriptor_t ASN_NULL_json_ = { false, NULL, false, NULL }; + +const TTCN_JSONdescriptor_t OBJID_json_ = { false, NULL, false, NULL }; + +const TTCN_JSONdescriptor_t ASN_ROID_json_ = { false, NULL, false, NULL }; + +const TTCN_JSONdescriptor_t ASN_ANY_json_ = { false, NULL, false, NULL }; + +const TTCN_JSONdescriptor_t ENUMERATED_json_ = { false, NULL, false, NULL }; diff --git a/core/JSON.hh b/core/JSON.hh index 39cbec4..6c9357d 100644 --- a/core/JSON.hh +++ b/core/JSON.hh @@ -64,6 +64,11 @@ extern const TTCN_JSONdescriptor_t IA5String_json_; extern const TTCN_JSONdescriptor_t TeletexString_json_; extern const TTCN_JSONdescriptor_t VideotexString_json_; extern const TTCN_JSONdescriptor_t VisibleString_json_; +extern const TTCN_JSONdescriptor_t ASN_NULL_json_; +extern const TTCN_JSONdescriptor_t OBJID_json_; +extern const TTCN_JSONdescriptor_t ASN_ROID_json_; +extern const TTCN_JSONdescriptor_t ASN_ANY_json_; +extern const TTCN_JSONdescriptor_t ENUMERATED_json_; /** JSON decoder error codes */ enum json_decode_error { diff --git a/core/Makefile b/core/Makefile index bb6ac4d..ff35320 100644 --- a/core/Makefile +++ b/core/Makefile @@ -78,7 +78,8 @@ LoggerPluginManager.cc LegacyLogger.cc LoggingBits.cc \ Module_list.cc Objid.cc Octetstring.cc Parallel_main.cc Port.cc RAW.cc \ Runtime.cc Single_main.cc Snapshot.cc Struct_of.cc Template.cc TEXT.cc \ Textbuf.cc Timer.cc Param_Types.cc Universal_charstring.cc \ -Verdicttype.cc XER.cc XmlReader.cc TitanLoggerControlImpl.cc TCov.cc JSON.cc $(RT2_SOURCES) +Verdicttype.cc XER.cc XmlReader.cc TitanLoggerControlImpl.cc TCov.cc JSON.cc \ +Profiler.cc $(RT2_SOURCES) # Keep GENERATED_SOURCES at the beginning. This may speed up parallel builds # by starting early the compilation of the largest files. @@ -156,7 +157,7 @@ Port.hh Event_Handler.hh Struct_of.hh Array.hh Optional.hh Textbuf.hh Encdec.hh Module_list.hh Parameters.h Addfunc.hh RAW.hh BER.hh TEXT.hh ASN_Null.hh \ ASN_Any.hh ASN_External.hh ASN_EmbeddedPDV.hh ASN_CharacterString.hh XER.hh \ XmlReader.hh cversion.h TitanLoggerControl.ttcn TitanLoggerApi.xsd Vector.hh \ -JSON.hh +JSON.hh Profiler.hh # Copied during "make install" ifdef REGEX_DIR diff --git a/core/Objid.cc b/core/Objid.cc index 00d37ba..79fe281 100644 --- a/core/Objid.cc +++ b/core/Objid.cc @@ -264,7 +264,16 @@ void OBJID::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer, p_buf, XER_coding, 0); + XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); + break;} + case TTCN_EncDec::CT_JSON: { + TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); + if(!p_td.json) + TTCN_EncDec_ErrorContext::error_internal + ("No JSON descriptor available for type '%s'.", p_td.name); + JSON_Tokenizer tok(va_arg(pvar, int) != 0); + JSON_encode(p_td, tok); + p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer()); break;} default: TTCN_error("Unknown coding method requested to encode type '%s'", @@ -293,7 +302,7 @@ void OBJID::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, ("No RAW descriptor available for type '%s'.", p_td.name); break;} case TTCN_EncDec::CT_XER: { - TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); + TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); XmlReaderWrap reader(p_buf); int success = reader.Read(); @@ -302,10 +311,23 @@ void OBJID::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} + case TTCN_EncDec::CT_JSON: { + TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name); + if(!p_td.json) + TTCN_EncDec_ErrorContext::error_internal + ("No JSON descriptor available for type '%s'.", p_td.name); + JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len()); + if(JSON_decode(p_td, tok, false)<0) + ec.error(TTCN_EncDec::ET_INCOMPL_MSG, + "Can not decode type '%s', because invalid or incomplete" + " message was received" + , p_td.name); + p_buf.set_pos(tok.get_buf_pos()); + break;} default: TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name); @@ -446,7 +468,7 @@ boolean OBJID::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, int OBJID::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent ) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if(!is_bound()) { TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, @@ -478,8 +500,33 @@ int OBJID::XER_encode(const XERdescriptor_t& p_td, return (int)p_buf.get_len() - encoded_length; } +void OBJID::from_string(char* p_str) +{ + // Count dots to find number of components. (1 dot = 2 components, etc.) + unsigned comps = 1; + const char *p; + for (p = p_str; *p != 0; ++p) { + if (*p == '.') ++comps; + } + // p now points at the end of the string. If it was empty, then there were + // no components; compensate the fact that we started at 1. + init_struct((p != p_str) ? comps : 0); + + char *beg, *end = 0; + comps = 0; + for (beg = p_str; beg < p; ++beg) { + errno = 0; + long ret = strtol(beg, &end, 10); + if (errno) break; + + // TODO check value for too big ? + (*this)[comps++] = ret; + beg = end; // move to the dot; will move past it when incremented + } +} + int OBJID::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor) + unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int success = reader.Ok(), depth = -1; @@ -497,27 +544,8 @@ int OBJID::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "Bogus object identifier"); return 0; } - // Count dots to find number of components. (1 dot = 2 components, etc.) - unsigned comps = 1; - const char *p; - for (p = val; *p != 0; ++p) { - if (*p == '.') ++comps; - } - // p now points at the end of the string. If it was empty, then there were - // no components; compensate the fact that we started at 1. - init_struct((p != val) ? comps : 0); - - char *beg, *end = 0; - comps = 0; - for (beg = val; beg < p; ++beg) { - errno = 0; - long ret = strtol(beg, &end, 10); - if (errno) break; - - // TODO check value for too big ? - (*this)[comps++] = ret; - beg = end; // move to the dot; will move past it when incremented - } + + from_string(val); xmlFree(val); } @@ -532,6 +560,69 @@ int OBJID::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, return 1; // decode successful } +int OBJID::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const +{ + if (!is_bound()) { + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, + "Encoding an unbound object identifier value."); + return -1; + } + + char* objid_str = mcopystrn("\"", 1); + for (int i = 0; i < val_ptr->n_components; ++i) { + objid_str = mputprintf(objid_str, "%s" OBJID_FMT, (i > 0 ? "." : ""), val_ptr->components_ptr[i]); + } + objid_str = mputstrn(objid_str, "\"", 1); + int enc_len = p_tok.put_next_token(JSON_TOKEN_STRING, objid_str); + Free(objid_str); + return enc_len; +} + +int OBJID::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent) +{ + json_token_t token = JSON_TOKEN_NONE; + char* value = 0; + size_t value_len = 0; + boolean error = false; + int dec_len = 0; + boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length(); + if (use_default) { + // No JSON data in the buffer -> use default value + value = (char*)p_td.json->default_value; + value_len = strlen(value); + } else { + dec_len = p_tok.get_next_token(&token, &value, &value_len); + } + if (JSON_TOKEN_ERROR == token) { + JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, ""); + return JSON_ERROR_FATAL; + } + else if (JSON_TOKEN_STRING == token || use_default) { + if (use_default || (value_len > 2 && value[0] == '\"' && value[value_len - 1] == '\"')) { + if (!use_default) { + // The default value doesn't have quotes around it + value_len -= 2; + ++value; + } + // need a null-terminated string + char* value2 = mcopystrn(value, value_len); + from_string(value2); + Free(value2); + } + } + else { + return JSON_ERROR_INVALID_TOKEN; + } + + if (error) { + JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "object identifier"); + if (p_silent) { + clean_up(); + } + return JSON_ERROR_FATAL; + } + return dec_len; +} void OBJID_template::clean_up() { diff --git a/core/Objid.hh b/core/Objid.hh index c5828b5..b2b7489 100644 --- a/core/Objid.hh +++ b/core/Objid.hh @@ -27,6 +27,10 @@ class OBJID : public Base_Type { void init_struct(int n_components); void copy_value(); + + /** Initializes the object identifier with a string containing the components + * separated by dots. */ + void from_string(char* p_str); public: typedef unsigned int objid_element; @@ -83,9 +87,17 @@ public: boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); int XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor); + unsigned int flavor, embed_values_dec_struct_t*); + + /** Encodes accordingly to the JSON encoding rules. + * Returns the length of the encoded data. */ + int JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const; + + /** Decodes accordingly to the JSON decoding rules. + * Returns the length of the encoded data. */ + int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); }; // objid template class diff --git a/core/Octetstring.cc b/core/Octetstring.cc index 948c225..644ca50 100644 --- a/core/Octetstring.cc +++ b/core/Octetstring.cc @@ -573,7 +573,7 @@ void OCTETSTRING::encode(const TTCN_Typedescriptor_t& p_td, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer, p_buf, XER_coding, 0); + XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); break;} case TTCN_EncDec::CT_JSON: { TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name); @@ -645,7 +645,7 @@ void OCTETSTRING::decode(const TTCN_Typedescriptor_t& p_td, , p_td.name); break;} case TTCN_EncDec::CT_XER: { - TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); + TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); XmlReaderWrap reader(p_buf); int success = reader.Read(); @@ -654,7 +654,7 @@ void OCTETSTRING::decode(const TTCN_Typedescriptor_t& p_td, if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -849,7 +849,7 @@ extern unsigned int xlate(cbyte* in, int phase, unsigned char* dest); extern const char cb64[]; int OCTETSTRING::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if(!is_bound()) { TTCN_EncDec_ErrorContext::error @@ -894,7 +894,7 @@ int OCTETSTRING::XER_encode(const XERdescriptor_t& p_td, } int OCTETSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor) + unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int success = reader.Ok(), depth = -1, type; diff --git a/core/Octetstring.hh b/core/Octetstring.hh index 8c8e9b4..bb1428a 100644 --- a/core/Octetstring.hh +++ b/core/Octetstring.hh @@ -150,9 +150,9 @@ public: int TEXT_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, Limit_Token_List&, boolean no_err=FALSE, boolean first_call=TRUE); int XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent) const; + unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor); + unsigned int flavor, embed_values_dec_struct_t*); /** Encodes accordingly to the JSON encoding rules. * Returns the length of the encoded data. */ diff --git a/core/Optional.hh b/core/Optional.hh index 7c47aac..85e1475 100644 --- a/core/Optional.hh +++ b/core/Optional.hh @@ -26,19 +26,23 @@ enum optional_sel { OPTIONAL_UNBOUND, OPTIONAL_OMIT, OPTIONAL_PRESENT }; template class OPTIONAL : public Base_Type { + /** The value, if present (owned by OPTIONAL) + * In Runtime2 the pointer is null, when the value is not present. + * In Runtime1 its presence is indicated by the optional_selection member. */ + T_type *optional_value; + /** Specifies the state of the optional field - * @tricky The optional value can be modified through parameter references, + * @tricky In Runtime2 the optional value can be modified through parameter references, * in which case this member variable will not be updated. Always use the function * get_selection() instead of directly referencing this variable. */ - optional_sel optional_selection; - - /** The value, if present (owned by OPTIONAL) */ - T_type *optional_value; + optional_sel optional_selection; +#ifdef TITAN_RUNTIME_2 /** Stores the number of elements referenced by 'out' and 'inout' parameters, - * if the optional field is a record of/set of/array. + * if the optional field is a record of/set of/array (only in Runtime2). * If at least one element is referenced, the value must not be deleted. */ - int param_refs; + int param_refs; +#endif /** Set the optional value to present. * If the value was already present, does nothing. @@ -55,9 +59,10 @@ public: void set_to_present() { if (optional_selection != OPTIONAL_PRESENT) { optional_selection = OPTIONAL_PRESENT; - if (optional_value == NULL) { +#ifdef TITAN_RUNTIME_2 + if (optional_value == NULL) +#endif optional_value = new T_type; - } } } @@ -72,6 +77,7 @@ public: inline #endif void set_to_omit() { +#ifdef TITAN_RUNTIME_2 if (is_present()) { if (param_refs > 0) { optional_value->clean_up(); @@ -81,12 +87,21 @@ public: optional_value = NULL; } } +#else + if (optional_selection == OPTIONAL_PRESENT) { + delete optional_value; + } +#endif optional_selection = OPTIONAL_OMIT; } public: /// Default constructor creates an unbound object - OPTIONAL() : optional_selection(OPTIONAL_UNBOUND), optional_value(NULL), param_refs(0) { } + OPTIONAL() : optional_value(NULL), optional_selection(OPTIONAL_UNBOUND) +#ifdef TITAN_RUNTIME_2 + , param_refs(0) +#endif + { } /// Construct an optional object set to omit. /// @p other_value must be OMIT_VALUE, or else dynamic testcase error. @@ -104,12 +119,21 @@ public: /// Construct from an object of different type template OPTIONAL(const T_tmp& other_value) - : optional_selection(OPTIONAL_PRESENT), - optional_value(new T_type(other_value)), - param_refs(0) { } + : optional_value(new T_type(other_value)) + , optional_selection(OPTIONAL_PRESENT) +#ifdef TITAN_RUNTIME_2 + , param_refs(0) +#endif + { } - ~OPTIONAL() - { if (NULL != optional_value) delete optional_value; } + ~OPTIONAL() { +#ifdef TITAN_RUNTIME_2 + if (NULL != optional_value) +#else + if (optional_selection == OPTIONAL_PRESENT) +#endif + delete optional_value; + } void clean_up(); @@ -161,12 +185,20 @@ public: { return is_equal(other_value); } #endif +#ifdef TITAN_RUNTIME_2 boolean is_bound() const; +#else + inline boolean is_bound() const { return optional_selection != OPTIONAL_UNBOUND; } +#endif boolean is_value() const { return optional_selection == OPTIONAL_PRESENT && optional_value->is_value(); } /** Whether the optional value is present. * @return \c true if optional_selection is OPTIONAL_PRESENT, else \c false */ +#ifdef TITAN_RUNTIME_2 boolean is_present() const; +#else + inline boolean is_present() const { return optional_selection==OPTIONAL_PRESENT; } +#endif #ifdef TITAN_RUNTIME_2 /** @name override virtual functions of Base_Type @@ -207,9 +239,14 @@ public: */ boolean ispresent() const; +#ifdef TITAN_RUNTIME_2 /** @tricky Calculates and returns the actual state of the optional object, - * not just the optional_selection member. */ + * not just the optional_selection member. + * (Only needed in Runtime2, in Runtime1 optional_selection is always up to date.) */ optional_sel get_selection() const; +#else + inline optional_sel get_selection() const { return optional_selection; } +#endif void log() const; void set_param(Module_Param& param); @@ -221,10 +258,12 @@ public: raw_order_t top_bit_ord, boolean no_err=FALSE, int sel_field=-1, boolean first_call=TRUE); #endif - int XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsigned int flavor, int indent) const; + int XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsigned int flavor, + int indent, embed_values_enc_struct_t* emb_val) const; #ifdef TITAN_RUNTIME_2 int XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, - const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent) const; + const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, + int indent, embed_values_enc_struct_t* emb_val) const; #endif /** Used during XML decoding, in case this object is an AnyElement field in a record. * Determines whether XER_decode() should be called or this field should be omitted. @@ -236,7 +275,8 @@ public: * @param next_field_name name of the next field in the record, or null if this is the last one * @param parent_tag_closed true, if the record's XML tag is closed (is an empty element)*/ bool XER_check_any_elem(XmlReaderWrap& reader, const char* next_field_name, bool parent_tag_closed); - int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor); + int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, + unsigned int flavor, embed_values_dec_struct_t* emb_val); char ** collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const; @@ -274,16 +314,18 @@ public: * Returns the length of the decoded data. */ int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean); +#ifdef TITAN_RUNTIME_2 /** Called before an element of an optional record of/set of is indexed and passed as an - * 'inout' or 'out' parameter to a function. + * 'inout' or 'out' parameter to a function (only in Runtime2). * Sets the optional value to present (this would be done by the indexing operation * anyway) and redirects the call to the optional value. */ void add_refd_index(int index); /** Called after an element of an optional record of/set of is passed as an - * 'inout' or 'out' parameter to a function. + * 'inout' or 'out' parameter to a function (only in Runtime2). * Redirects the call to the optional value. */ void remove_refd_index(int index); +#endif /** Called before an element of an optional record of/set of is passed as an * 'inout' or 'out' parameter to a function. Returns the size of the record of/ @@ -302,7 +344,11 @@ public: template Base_Type* OPTIONAL::get_opt_value() { +#ifdef TITAN_RUNTIME_2 if (!is_present()) +#else + if (optional_selection!=OPTIONAL_PRESENT) +#endif TTCN_error("Internal error: get_opt_value() called on a non-present optional field."); return optional_value; } @@ -310,7 +356,11 @@ Base_Type* OPTIONAL::get_opt_value() template const Base_Type* OPTIONAL::get_opt_value() const { +#ifdef TITAN_RUNTIME_2 if (!is_present()) +#else + if (optional_selection!=OPTIONAL_PRESENT) +#endif TTCN_error("Internal error: get_opt_value() const called on a non-present optional field."); return optional_value; } @@ -318,20 +368,35 @@ const Base_Type* OPTIONAL::get_opt_value() const template boolean OPTIONAL::is_seof() const { - return (is_present()) ? optional_value->is_seof() : T_type().is_seof(); + return +#ifdef TITAN_RUNTIME_2 + (is_present()) +#else + (optional_selection==OPTIONAL_PRESENT) +#endif + ? optional_value->is_seof() : T_type().is_seof(); } template const TTCN_Typedescriptor_t* OPTIONAL::get_descriptor() const { - return (is_present()) ? optional_value->get_descriptor() : T_type().get_descriptor(); + return +#ifdef TITAN_RUNTIME_2 + (is_present()) +#else + (optional_selection==OPTIONAL_PRESENT) +#endif + ? optional_value->get_descriptor() : T_type().get_descriptor(); } #endif template OPTIONAL::OPTIONAL(template_sel other_value) - : optional_selection(OPTIONAL_OMIT), optional_value(NULL), param_refs(0) + : optional_value(NULL), optional_selection(OPTIONAL_OMIT) +#ifdef TITAN_RUNTIME_2 + , param_refs(0) +#endif { if (other_value != OMIT_VALUE) TTCN_error("Setting an optional field to an invalid value."); @@ -340,9 +405,11 @@ OPTIONAL::OPTIONAL(template_sel other_value) template OPTIONAL::OPTIONAL(const OPTIONAL& other_value) : Base_Type(other_value) - , optional_selection(other_value.optional_selection) , optional_value(NULL) + , optional_selection(other_value.optional_selection) +#ifdef TITAN_RUNTIME_2 , param_refs(0) +#endif { switch (other_value.optional_selection) { case OPTIONAL_PRESENT: @@ -357,7 +424,10 @@ OPTIONAL::OPTIONAL(const OPTIONAL& other_value) template template OPTIONAL::OPTIONAL(const OPTIONAL& other_value) - : optional_selection(other_value.get_selection()), optional_value(NULL), param_refs(0) + : optional_value(NULL), optional_selection(other_value.get_selection()) +#ifdef TITAN_RUNTIME_2 + , param_refs(0) +#endif { switch (other_value.get_selection()) { case OPTIONAL_PRESENT: @@ -373,6 +443,7 @@ OPTIONAL::OPTIONAL(const OPTIONAL& other_value) template void OPTIONAL::clean_up() { +#ifdef TITAN_RUNTIME_2 if (is_present()) { if (param_refs > 0) { optional_value->clean_up(); @@ -382,6 +453,11 @@ void OPTIONAL::clean_up() optional_value = NULL; } } +#else + if (OPTIONAL_PRESENT == optional_selection) { + delete optional_value; + } +#endif optional_selection = OPTIONAL_UNBOUND; } @@ -399,9 +475,13 @@ OPTIONAL& OPTIONAL::operator=(const OPTIONAL& other_value) { switch (other_value.optional_selection) { case OPTIONAL_PRESENT: - optional_selection = OPTIONAL_PRESENT; +#ifdef TITAN_RUNTIME_2 if (NULL == optional_value) { +#else + if (optional_selection != OPTIONAL_PRESENT) { +#endif optional_value = new T_type(*other_value.optional_value); + optional_selection = OPTIONAL_PRESENT; } else *optional_value = *other_value.optional_value; break; case OPTIONAL_OMIT: @@ -420,9 +500,13 @@ OPTIONAL::operator=(const OPTIONAL& other_value) { switch (other_value.get_selection()) { case OPTIONAL_PRESENT: - optional_selection = OPTIONAL_PRESENT; +#ifdef TITAN_RUNTIME_2 if (NULL == optional_value) { +#else + if (optional_selection != OPTIONAL_PRESENT) { +#endif optional_value = new T_type((const T_tmp&)other_value); + optional_selection = OPTIONAL_PRESENT; } else *optional_value = (const T_tmp&)other_value; break; case OPTIONAL_OMIT: @@ -439,9 +523,13 @@ template template OPTIONAL& OPTIONAL::operator=(const T_tmp& other_value) { - optional_selection = OPTIONAL_PRESENT; +#ifdef TITAN_RUNTIME_2 if (NULL == optional_value) { +#else + if (optional_selection != OPTIONAL_PRESENT) { +#endif optional_value = new T_type(other_value); + optional_selection = OPTIONAL_PRESENT; } else *optional_value = other_value; return *this; } @@ -449,28 +537,52 @@ OPTIONAL::operator=(const T_tmp& other_value) template boolean OPTIONAL::is_equal(template_sel other_value) const { +#ifdef TITAN_RUNTIME_2 if (!is_bound()) { +#else + if (optional_selection == OPTIONAL_UNBOUND) { +#endif if (other_value == UNINITIALIZED_TEMPLATE) return TRUE; TTCN_error("The left operand of comparison is an unbound optional value."); } if (other_value != OMIT_VALUE) TTCN_error("Internal error: The right operand " "of comparison is an invalid value."); - return !is_present(); + return +#ifdef TITAN_RUNTIME_2 + !is_present(); +#else + optional_selection == OPTIONAL_OMIT; +#endif } template boolean OPTIONAL::is_equal(const OPTIONAL& other_value) const { +#ifdef TITAN_RUNTIME_2 if (!is_bound()) { - if (!other_value.is_bound()) return TRUE; + if (!other_value.is_bound()) +#else + if (optional_selection == OPTIONAL_UNBOUND) { + if (other_value.optional_selection == OPTIONAL_UNBOUND) +#endif + return TRUE; TTCN_error("The left operand of " "comparison is an unbound optional value."); } +#ifdef TITAN_RUNTIME_2 if (!other_value.is_bound()) +#else + if (other_value.optional_selection == OPTIONAL_UNBOUND) +#endif TTCN_error("The right operand of comparison is an unbound optional value."); +#ifdef TITAN_RUNTIME_2 boolean present = is_present(); if (present != other_value.is_present()) return FALSE; else if (present) +#else + if (optional_selection != other_value.optional_selection) return FALSE; + else if (optional_selection == OPTIONAL_PRESENT) +#endif return *optional_value == *other_value.optional_value; else return TRUE; } @@ -478,7 +590,11 @@ boolean OPTIONAL::is_equal(const OPTIONAL& other_value) const template template boolean OPTIONAL::is_equal(const T_tmp& other_value) const { +#ifdef TITAN_RUNTIME_2 switch (get_selection()) { +#else + switch (optional_selection) { +#endif case OPTIONAL_PRESENT: return *optional_value == other_value; case OPTIONAL_OMIT: @@ -492,20 +608,37 @@ boolean OPTIONAL::is_equal(const T_tmp& other_value) const template template boolean OPTIONAL::is_equal(const OPTIONAL& other_value) const { +#ifdef TITAN_RUNTIME_2 if (!is_bound()) { - if (!other_value.is_bound()) return TRUE; + if (!other_value.is_bound()) +#else + optional_sel other_selection = other_value.get_selection(); + if (optional_selection == OPTIONAL_UNBOUND) { + if (other_selection == OPTIONAL_UNBOUND) +#endif + return TRUE; TTCN_error("The left operand of " "comparison is an unbound optional value."); } - if (!other_value.is_bound()) TTCN_error("The right operand of " - "comparison is an unbound optional value."); +#ifdef TITAN_RUNTIME_2 + if (!other_value.is_bound()) +#else + if (other_selection == OPTIONAL_UNBOUND) +#endif + TTCN_error("The right operand of comparison is an unbound optional value."); +#ifdef TITAN_RUNTIME_2 boolean present = is_present(); if (present != other_value.is_present()) return FALSE; else if (present) +#else + if (optional_selection != other_selection) return FALSE; + else if (optional_selection == OPTIONAL_PRESENT) +#endif return *optional_value == (const T_tmp&)other_value; else return TRUE; } +#ifdef TITAN_RUNTIME_2 template boolean OPTIONAL::is_bound() const { @@ -535,6 +668,7 @@ boolean OPTIONAL::is_present() const return FALSE; } } +#endif template boolean OPTIONAL::ispresent() const @@ -543,19 +677,24 @@ boolean OPTIONAL::ispresent() const case OPTIONAL_PRESENT: return TRUE; case OPTIONAL_OMIT: +#ifdef TITAN_RUNTIME_2 if (NULL != optional_value) { return optional_value->is_bound(); } +#endif return FALSE; default: +#ifdef TITAN_RUNTIME_2 if (NULL != optional_value && optional_value->is_bound()) { return TRUE; } +#endif TTCN_error("Using an unbound optional field."); - return FALSE; } + return FALSE; } +#ifdef TITAN_RUNTIME_2 template optional_sel OPTIONAL::get_selection() const { @@ -568,11 +707,16 @@ optional_sel OPTIONAL::get_selection() const } return OPTIONAL_UNBOUND; } +#endif template void OPTIONAL::log() const { +#ifdef TITAN_RUNTIME_2 switch (get_selection()) { +#else + switch (optional_selection) { +#endif case OPTIONAL_PRESENT: optional_value->log(); break; @@ -600,7 +744,11 @@ void OPTIONAL::set_param(Module_Param& param) { template void OPTIONAL::encode_text(Text_Buf& text_buf) const { +#ifdef TITAN_RUNTIME_2 switch (get_selection()) { +#else + switch (optional_selection) { +#endif case OPTIONAL_OMIT: text_buf.push_int((RInt)FALSE); break; @@ -625,7 +773,11 @@ void OPTIONAL::decode_text(Text_Buf& text_buf) template int OPTIONAL::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const { +#ifdef TITAN_RUNTIME_2 switch(get_selection()) { +#else + switch(optional_selection) { +#endif case OPTIONAL_PRESENT: return optional_value->JSON_encode(p_td, p_tok); case OPTIONAL_OMIT: @@ -640,33 +792,36 @@ int OPTIONAL::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokeni template int OPTIONAL::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent) { + // try the optional value first + set_to_present(); size_t buf_pos = p_tok.get_buf_pos(); - json_token_t token = JSON_TOKEN_NONE; - int dec_len = p_tok.get_next_token(&token, NULL, NULL); - if (JSON_TOKEN_ERROR == token) { - JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, ""); - dec_len = JSON_ERROR_FATAL; - } - else if (JSON_TOKEN_LITERAL_NULL == token) { - set_to_omit(); + int dec_len = optional_value->JSON_decode(p_td, p_tok, p_silent); + if (JSON_ERROR_FATAL == dec_len) { + if (p_silent) { + clean_up(); + } else { + set_to_omit(); + } } - else { - // read the token again - set_to_present(); + else if (JSON_ERROR_INVALID_TOKEN == dec_len) { + // invalid token, rewind the buffer and check if it's a "null" (= omit) + // this needs to be checked after the optional value, because it might also be + // able to decode a "null" value p_tok.set_buf_pos(buf_pos); - int ret_val = optional_value->JSON_decode(p_td, p_tok, p_silent); - if (0 > ret_val) { - if (p_silent) { - clean_up(); - } else { - set_to_omit(); - } + json_token_t token = JSON_TOKEN_NONE; + dec_len = p_tok.get_next_token(&token, NULL, NULL); + if (JSON_TOKEN_LITERAL_NULL == token) { + set_to_omit(); + } + else { + // cannot get JSON_TOKEN_ERROR here, that was already checked by the optional value + dec_len = JSON_ERROR_INVALID_TOKEN; } - dec_len = ret_val; } return dec_len; } +#ifdef TITAN_RUNTIME_2 template void OPTIONAL::add_refd_index(int index) { @@ -681,15 +836,7 @@ void OPTIONAL::remove_refd_index(int index) --param_refs; optional_value->remove_refd_index(index); } - -template -int OPTIONAL::size_of() -{ - if (!is_present()) { - return 0; - } - return optional_value->size_of(); -} +#endif template OPTIONAL::operator T_type&() @@ -701,7 +848,11 @@ OPTIONAL::operator T_type&() template OPTIONAL::operator const T_type&() const { +#ifdef TITAN_RUNTIME_2 if (!is_present()) +#else + if (optional_selection != OPTIONAL_PRESENT) +#endif TTCN_error("Using the value of an optional field containing omit."); return *optional_value; } @@ -712,7 +863,11 @@ OPTIONAL::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const { BER_chk_descr(p_td); +#ifdef TITAN_RUNTIME_2 switch (get_selection()) { +#else + switch (optional_selection) { +#endif case OPTIONAL_PRESENT: return optional_value->BER_encode_TLV(p_td, p_coding); case OPTIONAL_OMIT: @@ -729,7 +884,11 @@ OPTIONAL::BER_encode_TLV_negtest(const Erroneous_descriptor_t* p_err_des const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const { BER_chk_descr(p_td); +#ifdef TITAN_RUNTIME_2 switch (get_selection()) { +#else + switch (optional_selection) { +#endif case OPTIONAL_PRESENT: return optional_value->BER_encode_TLV_negtest(p_err_descr, p_td, p_coding); case OPTIONAL_OMIT: @@ -752,11 +911,15 @@ int OPTIONAL::RAW_decode(const TTCN_Typedescriptor_t& p_td, template int -OPTIONAL::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsigned int flavor, int indent) const +OPTIONAL::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsigned int flavor, int indent, embed_values_enc_struct_t* emb_val) const { +#ifdef TITAN_RUNTIME_2 switch (get_selection()) { +#else + switch (optional_selection) { +#endif case OPTIONAL_PRESENT: - return optional_value->XER_encode(p_td, buf, flavor, indent); + return optional_value->XER_encode(p_td, buf, flavor, indent, emb_val); case OPTIONAL_OMIT: return 0; // nothing to do ! default: @@ -770,11 +933,12 @@ OPTIONAL::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsi template int OPTIONAL::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, - const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsigned int flavor, int indent) const + const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsigned int flavor, int indent, + embed_values_enc_struct_t* emb_val) const { switch (get_selection()) { case OPTIONAL_PRESENT: - return optional_value->XER_encode_negtest(p_err_descr, p_td, buf, flavor, indent); + return optional_value->XER_encode_negtest(p_err_descr, p_td, buf, flavor, indent, emb_val); case OPTIONAL_OMIT: return 0; // nothing to do ! default: @@ -819,7 +983,8 @@ OPTIONAL::XER_check_any_elem(XmlReaderWrap& reader, const char* next_fie template int -OPTIONAL::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor) +OPTIONAL::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, + unsigned int flavor, embed_values_dec_struct_t* emb_val) { int exer = is_exer(flavor); for (int success = reader.Ok(); success==1; success=reader.Read()) { @@ -841,7 +1006,7 @@ OPTIONAL::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, if (!check_namespace((const char*)reader.NamespaceUri(), p_td)) break; set_to_present(); - optional_value->XER_decode(p_td, reader, flavor); + optional_value->XER_decode(p_td, reader, flavor, emb_val); goto finished; } else break; @@ -858,7 +1023,7 @@ OPTIONAL::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, found_it: set_to_present(); //success = reader.Read(); // move to next thing TODO should it loop till an element ? - optional_value->XER_decode(p_td, reader, flavor); + optional_value->XER_decode(p_td, reader, flavor, emb_val); } else break; // it's not us, bail @@ -881,7 +1046,11 @@ finished: template char ** OPTIONAL::collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const { +#ifdef TITAN_RUNTIME_2 switch (get_selection()) { +#else + switch (optional_selection) { +#endif case OPTIONAL_PRESENT: return optional_value->collect_ns(p_td, num, def_ns); case OPTIONAL_OMIT: @@ -921,8 +1090,12 @@ template void OPTIONAL::BER_decode_opentypes(TTCN_Type_list& p_typelist, unsigned L_form) { +#ifdef TITAN_RUNTIME_2 if (is_present()) { optional_selection = OPTIONAL_PRESENT; +#else + if (optional_selection==OPTIONAL_PRESENT) { +#endif optional_value->BER_decode_opentypes(p_typelist, L_form); } } @@ -933,7 +1106,7 @@ template int OPTIONAL::TEXT_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff) const { - if (get_selection()) + if (is_present()) return optional_value->TEXT_encode(p_td, buff); TTCN_error("Internal error: TEXT encoding an unbound/omit optional field."); return 0; @@ -943,7 +1116,7 @@ template int OPTIONAL::TEXT_encode_negtest(const Erroneous_descriptor_t* p_err_descr, const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff) const { - if (get_selection()) + if (is_present()) return optional_value->TEXT_encode_negtest(p_err_descr, p_td, buff); TTCN_error("Internal error: TEXT encoding an unbound/omit optional field."); return 0; diff --git a/core/Profiler.cc b/core/Profiler.cc new file mode 100644 index 0000000..860e5c8 --- /dev/null +++ b/core/Profiler.cc @@ -0,0 +1,839 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2015 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// + +#include "Profiler.hh" +#include +#include +#include +#include +#include "JSON_Tokenizer.hh" +#include "memory.h" +#include "Runtime.hh" + +//////////////////////////////////// +////////// TTCN3_Profiler ////////// +//////////////////////////////////// + +TTCN3_Profiler ttcn3_prof; + +TTCN3_Profiler::TTCN3_Profiler() +: disable_profiler(FALSE), disable_coverage(FALSE), aggregate_data(FALSE) +, disable_stats(FALSE) +{ + database_filename = mcopystr("profiler.db"); + stats_filename = mcopystr("profiler.stats"); + reset(); +} + +TTCN3_Profiler::~TTCN3_Profiler() +{ + if (!disable_profiler || !disable_coverage) { + import_data(); + export_data(); + if (!disable_stats && (TTCN_Runtime::is_single() || TTCN_Runtime::is_hc())) { + print_stats(); + } + } + for (size_t i = 0; i < profiler_db.size(); ++i) { + Free(profiler_db[i].filename); + for (size_t j = 0; j < profiler_db[i].functions.size(); ++j) { + Free(profiler_db[i].functions[j].name); + } + } + Free(database_filename); + Free(stats_filename); +} + +void TTCN3_Profiler::set_disable_profiler(boolean p_disable_profiler) +{ + disable_profiler = p_disable_profiler; +} + +void TTCN3_Profiler::set_disable_coverage(boolean p_disable_coverage) +{ + disable_coverage = p_disable_coverage; +} + +void TTCN3_Profiler::set_database_filename(const char* p_database_filename) +{ + Free(database_filename); + database_filename = mcopystr(p_database_filename); +} + +void TTCN3_Profiler::set_aggregate_data(boolean p_aggregate_data) +{ + aggregate_data = p_aggregate_data; +} + +void TTCN3_Profiler::set_stats_filename(const char* p_stats_filename) +{ + Free(stats_filename); + stats_filename = mcopystr(p_stats_filename); +} + +void TTCN3_Profiler::set_disable_stats(boolean p_disable_stats) +{ + disable_stats = p_disable_stats; +} + +boolean TTCN3_Profiler::is_profiler_disabled() const +{ + return disable_profiler; +} + +#define IMPORT_FORMAT_ERROR(cond) \ + if (cond) { \ + TTCN_warning("Database format is invalid. Profiler and/or code coverage data will not be loaded."); \ + return; \ + } + +void TTCN3_Profiler::init_data_file() +{ + // delete the database file (from the previous run) if data aggregation is not set + if (!aggregate_data && (!disable_profiler || !disable_coverage)) { + remove(database_filename); + } +} + +void TTCN3_Profiler::import_data() +{ + // open the file, if it exists + FILE* file = fopen(database_filename, "r"); + if (NULL == file) { + return; + } + + // get the file size + fseek(file, 0, SEEK_END); + int file_size = ftell(file); + rewind(file); + + // read the entire file into a character buffer + char* buffer = (char*)Malloc(file_size); + fread(buffer, 1, file_size, file); + + // initialize a JSON tokenizer with the buffer + JSON_Tokenizer json(buffer, file_size); + Free(buffer); + + // attempt to read tokens from the buffer + // if the format is invalid, abort the importing process + json_token_t token = JSON_TOKEN_NONE; + char* value = NULL; + size_t value_len = 0; + + // start of main array + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_START != token); + + // read objects (one for each TTCN-3 file), until the main array end mark is reached + json.get_next_token(&token, NULL, NULL); + while (JSON_TOKEN_OBJECT_START == token) { + size_t file_index = 0; + + // file name: + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 4 || + 0 != strncmp(value, "file", value_len)); + + // read the file name and see if its record already exists + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_STRING != token); + for (file_index = 0; file_index < profiler_db.size(); ++file_index) { + if (strlen(profiler_db[file_index].filename) == value_len - 2 && + 0 == strncmp(profiler_db[file_index].filename, value + 1, value_len - 2)) { + break; + } + } + + // insert a new element if the file was not found + if (profiler_db.size() == file_index) { + profiler_db_item_t item; + item.filename = mcopystrn(value + 1, value_len - 2); + profiler_db.push_back(item); + } + + // functions: + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 9 || + 0 != strncmp(value, "functions", value_len)); + + // read and store the functions (an array of objects, same as before) + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_START != token); + json.get_next_token(&token, NULL, NULL); + while (JSON_TOKEN_OBJECT_START == token) { + size_t function_index = 0; + + // function name: + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 4 || + 0 != strncmp(value, "name", value_len)); + + // read the function name, it will be checked later + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_STRING != token); + char* function_name = mcopystrn(value + 1, value_len - 2); + + // function start line: + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 10 || + 0 != strncmp(value, "start line", value_len)); + + // read the start line and check if the function already exists + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token); + int start_line = atoi(value); + for (function_index = 0; function_index < profiler_db[file_index].functions.size(); ++function_index) { + if (profiler_db[file_index].functions[function_index].lineno == start_line && + 0 == strcmp(profiler_db[file_index].functions[function_index].name, function_name)) { + break; + } + } + + // insert a new element if the function was not found + if (profiler_db[file_index].functions.size() == function_index) { + profiler_db_item_t::profiler_function_data_t func_data; + func_data.name = function_name; + func_data.lineno = start_line; + func_data.exec_count = 0; + func_data.total_time = 0.0; + profiler_db[file_index].functions.push_back(func_data); + } + + if (!disable_coverage) { + // function execution count: + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 15 || + 0 != strncmp(value, "execution count", value_len)); + + // read the execution count and add it to the current data + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token); + profiler_db[file_index].functions[function_index].exec_count += atoi(value); + } + + if (!disable_profiler) { + // total function execution time: + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 10 || + 0 != strncmp(value, "total time", value_len)); + + // read the total time and add it to the current data + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token); + profiler_db[file_index].functions[function_index].total_time += atof(value); + } + + // end of the function's object + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_END != token); + + // read the next token (either the start of another object or the function array end) + json.get_next_token(&token, NULL, NULL); + } + + // function array end + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_END != token); + + // lines: + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 5 || + 0 != strncmp(value, "lines", value_len)); + + // read and store the lines (an array of objects, same as before) + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_START != token); + json.get_next_token(&token, NULL, NULL); + while (JSON_TOKEN_OBJECT_START == token) { + + // line number: + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 6 || + 0 != strncmp(value, "number", value_len)); + + // read the line number and check if the line already exists + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token); + int lineno = atoi(value); + IMPORT_FORMAT_ERROR(lineno < 0); + size_t line_no = lineno; + if (line_no >= profiler_db[file_index].lines.size()) { + for (size_t i = profiler_db[file_index].lines.size(); i <= line_no; ++i) { + profiler_db_item_t::profiler_line_data_t line_data; + line_data.total_time = 0.0; + line_data.exec_count = 0; + profiler_db[file_index].lines.push_back(line_data); + } + } + + if (!disable_coverage) { + // line execution count: + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 15 || + 0 != strncmp(value, "execution count", value_len)); + + // read the execution count and add it to the current data + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token); + profiler_db[file_index].lines[line_no].exec_count += atoi(value); + } + + if (!disable_profiler) { + // total line execution time: + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 10 || + 0 != strncmp(value, "total time", value_len)); + + // read the total time and add it to the current data + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NUMBER != token); + profiler_db[file_index].lines[line_no].total_time += atof(value); + } + + // end of the line's object + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_END != token); + + // read the next token (either the start of another object or the line array end) + json.get_next_token(&token, NULL, NULL); + } + + // line array end + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_END != token); + + // end of the file's object + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_END != token); + + // read the next token (either the start of another object or the main array end) + json.get_next_token(&token, NULL, NULL); + } + + // main array end + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_END != token); +} + +void TTCN3_Profiler::export_data() +{ + // nothing to export if the database is empty + if (profiler_db.empty()) { + return; + } + + // check whether the file can be opened for writing + FILE* file = fopen(database_filename, "w"); + if (NULL == file) { + TTCN_warning("Could not open file '%s' for writing. Profiler and/or code coverage " + "data will not be saved.", database_filename); + return; + } + + // use the JSON tokenizer to create a JSON document from the database + JSON_Tokenizer json(true); + + // main array, contains an element for each file + json.put_next_token(JSON_TOKEN_ARRAY_START, NULL); + for (size_t i = 0; i < profiler_db.size(); ++i) { + + // each file's data is stored in an object + json.put_next_token(JSON_TOKEN_OBJECT_START, NULL); + + // store the file name + json.put_next_token(JSON_TOKEN_NAME, "file"); + char* file_name_str = mprintf("\"%s\"", profiler_db[i].filename); + json.put_next_token(JSON_TOKEN_STRING, file_name_str); + Free(file_name_str); + + // store the function data in an array (one element for each function) + json.put_next_token(JSON_TOKEN_NAME, "functions"); + json.put_next_token(JSON_TOKEN_ARRAY_START, NULL); + for (size_t j = 0; j < profiler_db[i].functions.size(); ++j) { + + // the data is stored in an object for each function + json.put_next_token(JSON_TOKEN_OBJECT_START, NULL); + + // store the function name + json.put_next_token(JSON_TOKEN_NAME, "name"); + char* func_name_str = mprintf("\"%s\"", profiler_db[i].functions[j].name); + json.put_next_token(JSON_TOKEN_STRING, func_name_str); + Free(func_name_str); + + // store the function start line + json.put_next_token(JSON_TOKEN_NAME, "start line"); + char* start_line_str = mprintf("%d", profiler_db[i].functions[j].lineno); + json.put_next_token(JSON_TOKEN_NUMBER, start_line_str); + Free(start_line_str); + + if (!disable_coverage) { + // store the function execution count + json.put_next_token(JSON_TOKEN_NAME, "execution count"); + char* exec_count_str = mprintf("%d", profiler_db[i].functions[j].exec_count); + json.put_next_token(JSON_TOKEN_NUMBER, exec_count_str); + Free(exec_count_str); + } + + if (!disable_profiler) { + // store the function's total execution time + json.put_next_token(JSON_TOKEN_NAME, "total time"); + char* exec_count_str = mprintf("%.6lf", profiler_db[i].functions[j].total_time); + json.put_next_token(JSON_TOKEN_NUMBER, exec_count_str); + Free(exec_count_str); + } + + // end of function object + json.put_next_token(JSON_TOKEN_OBJECT_END, NULL); + } + + // end of function data array + json.put_next_token(JSON_TOKEN_ARRAY_END, NULL); + + // store the line data in an array (one element for each line with useful data) + json.put_next_token(JSON_TOKEN_NAME, "lines"); + json.put_next_token(JSON_TOKEN_ARRAY_START, NULL); + for (size_t j = 0; j < profiler_db[i].lines.size(); ++j) { + if (0.0 != profiler_db[i].lines[j].total_time || + 0 != profiler_db[i].lines[j].exec_count) { + + // store line data in an object + json.put_next_token(JSON_TOKEN_OBJECT_START, NULL); + + // store the line number + json.put_next_token(JSON_TOKEN_NAME, "number"); + char* line_number_str = mprintf("%lu", j); + json.put_next_token(JSON_TOKEN_NUMBER, line_number_str); + Free(line_number_str); + + if (!disable_coverage) { + // store the line execution count + json.put_next_token(JSON_TOKEN_NAME, "execution count"); + char* exec_count_str = mprintf("%d", profiler_db[i].lines[j].exec_count); + json.put_next_token(JSON_TOKEN_NUMBER, exec_count_str); + Free(exec_count_str); + } + + if (!disable_profiler) { + // store the line's total execution time + json.put_next_token(JSON_TOKEN_NAME, "total time"); + char* exec_count_str = mprintf("%.6lf", profiler_db[i].lines[j].total_time); + json.put_next_token(JSON_TOKEN_NUMBER, exec_count_str); + Free(exec_count_str); + } + + // end of this line's object + json.put_next_token(JSON_TOKEN_OBJECT_END, NULL); + } + } + + // end of line data array + json.put_next_token(JSON_TOKEN_ARRAY_END, NULL); + + // end of this file's object + json.put_next_token(JSON_TOKEN_OBJECT_END, NULL); + } + + // end of main array + json.put_next_token(JSON_TOKEN_ARRAY_END, NULL); + + // write the JSON document into the file + fprintf(file, "%s\n", json.get_buffer()); + fclose(file); +} + +void TTCN3_Profiler::print_stats() +{ + if (profiler_db.empty()) { + return; + } + + // title + char* title_str = mprintf( + "##################################################\n" + "%s## TTCN-3 %s%s%sstatistics ##%s\n" + "##################################################\n\n\n" + , disable_profiler ? "#######" : (disable_coverage ? "#########" : "") + , disable_profiler ? "" : "profiler " + , (disable_profiler || disable_coverage) ? "" : "and " + , disable_coverage ? "" : "code coverage " + , disable_profiler ? "######" : (disable_coverage ? "#########" : "")); + + // line data + char* line_data_str = mprintf( + "-------------------------------------------------\n" + "%s- Code line data (%s%s%s) -%s\n" + "-------------------------------------------------\n" + , disable_profiler ? "-------" : (disable_coverage ? "---------" : "") + , disable_profiler ? "" : "total time" + , (disable_profiler || disable_coverage) ? "" : " / " + , disable_coverage ? "" : "execution count" + , disable_profiler ? "------" : (disable_coverage ? "---------" : "")); + + // average time / exec count for lines + char* line_avg_str = NULL; + if (!disable_coverage && !disable_profiler) { + line_avg_str = mcopystr( + "-------------------------------------------------\n" + "- Average time / execution count for code lines -\n" + "-------------------------------------------------\n"); + } + + // function data + char* func_data_str = mprintf( + "------------------------------------------------\n" + "%s- Function data (%s%s%s) -%s\n" + "------------------------------------------------\n" + , disable_profiler ? "-------" : (disable_coverage ? "---------" : "") + , disable_profiler ? "" : "total time" + , (disable_profiler || disable_coverage) ? "" : " / " + , disable_coverage ? "" : "execution count" + , disable_profiler ? "------" : (disable_coverage ? "---------" : "")); + + // average time / exec count for functions + char* func_avg_str = NULL; + if (!disable_coverage && !disable_profiler) { + func_avg_str = mcopystr( + "------------------------------------------------\n" + "- Average time / execution count for functions -\n" + "------------------------------------------------\n"); + } + + // cycle through the database and gather the necessary data + for (size_t i = 0; i < profiler_db.size(); ++i) { + if (i > 0) { + // add separators between files + line_data_str = mputstr(line_data_str, "-------------------------------------------------\n"); + func_data_str = mputstr(func_data_str, "------------------------------------------------\n"); + if (!disable_profiler && !disable_coverage) { + line_avg_str = mputstr(line_avg_str, "-------------------------------------------------\n"); + func_avg_str = mputstr(func_avg_str, "------------------------------------------------\n"); + } + } + + // lines + for (size_t j = 0; j < profiler_db[i].lines.size(); ++j) { + if (0.0 != profiler_db[i].lines[j].total_time || + 0 != profiler_db[i].lines[j].exec_count) { + if (!disable_profiler) { + line_data_str = mputprintf(line_data_str, "%.6lfs", profiler_db[i].lines[j].total_time); + if (!disable_coverage) { + line_data_str = mputstrn(line_data_str, "\t/\t", 3); + line_avg_str = mputprintf(line_avg_str, "%.6lfs", + profiler_db[i].lines[j].total_time / profiler_db[i].lines[j].exec_count); + } + } + if (!disable_coverage) { + line_data_str = mputprintf(line_data_str, "%d", profiler_db[i].lines[j].exec_count); + } + + // line specification (including function name for the function's start line) + char* line_spec_str = mprintf("\t%s:%lu", profiler_db[i].filename, j); + int func = get_function(i, j); + if (-1 != func) { + line_spec_str = mputprintf(line_spec_str, " [%s]", profiler_db[i].functions[func].name); + } + line_spec_str = mputstrn(line_spec_str, "\n", 1); + + // add the line spec string to the other strings + line_data_str = mputstr(line_data_str, line_spec_str); + if (!disable_profiler && !disable_coverage) { + line_avg_str = mputstr(line_avg_str, line_spec_str); + } + } + } + + // functions + for (size_t j = 0; j < profiler_db[i].functions.size(); ++j) { + if (!disable_profiler) { + func_data_str = mputprintf(func_data_str, "%.6lfs", profiler_db[i].functions[j].total_time); + if (!disable_coverage) { + func_data_str = mputstrn(func_data_str, "\t/\t", 3); + func_avg_str = mputprintf(func_avg_str, "%.6lfs", + profiler_db[i].functions[j].total_time / profiler_db[i].functions[j].exec_count); + } + } + if (!disable_coverage) { + func_data_str = mputprintf(func_data_str, "%d", profiler_db[i].functions[j].exec_count); + } + + // functions specification + char* func_spec_str = mprintf("\t%s:%d [%s]\n", profiler_db[i].filename, + profiler_db[i].functions[j].lineno, profiler_db[i].functions[j].name); + + // add the line spec string to the other strings + func_data_str = mputstr(func_data_str, func_spec_str); + if (!disable_profiler && !disable_coverage) { + func_avg_str = mputstr(func_avg_str, func_spec_str); + } + } + } + + // add new lines at the end of each segment + line_data_str = mputstrn(line_data_str, "\n", 1); + func_data_str = mputstrn(func_data_str, "\n", 1); + if (!disable_profiler && !disable_coverage) { + line_avg_str = mputstrn(line_avg_str, "\n", 1); + func_avg_str = mputstrn(func_avg_str, "\n", 1); + } + + // write the statistics to the specified file + FILE* file = fopen(stats_filename, "w"); + if (NULL == file) { + TTCN_warning("Could not open file '%s' for writing. Profiler and/or code coverage " + "statistics will not be saved.", stats_filename); + return; + } + fprintf(file, "%s%s%s%s%s" + , title_str, line_data_str + , (disable_profiler || disable_coverage) ? "" : line_avg_str + , func_data_str, (disable_profiler || disable_coverage) ? "" : func_avg_str); + fclose(file); +} + +void TTCN3_Profiler::reset() +{ + prev_time = 0.0; + prev_file = NULL; + prev_line = -1; + prev_stack_len = 0; +} + +double TTCN3_Profiler::get_time() +{ + timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec + tv.tv_usec / 1000000.0; +} + +void TTCN3_Profiler::enter_function(const char* filename, int lineno, const char* function_name) +{ + if (disable_profiler && disable_coverage) { + return; + } + + // Note that the execution time of the last line in a function + // is measured by using the stack depth. + execute_line(filename, lineno); + + int element = get_element(filename); + + // store function data + int func = get_function(element, lineno); + if (-1 == func) { + create_function(element, lineno, function_name); + func = profiler_db[element].functions.size() - 1; + } + + if (!disable_coverage) { + ++profiler_db[element].functions[func].exec_count; + } +} + +void TTCN3_Profiler::execute_line(const char* filename, int lineno) +{ + if (disable_profiler && disable_coverage) { + return; + } + + if (!disable_profiler) { + double currentTime = get_time(); + + // prev line should not be measured, because it is still running: we are in longer stack level + if (0.0 == prev_time || TTCN3_Stack_Depth::depth() > prev_stack_len) { + // add prev timer to call stack: + TTCN3_Stack_Depth::add_stack(prev_stack_len, prev_file, filename, prev_line, lineno); + } + else { + // if stack level is the same or higher: current line should be measured: + double elapsed = currentTime - prev_time; + + // add the elapsed time to the time of the previous line: + add_line_time(elapsed, get_element(prev_file), prev_line); + + TTCN3_Stack_Depth::update_stack_elapsed(elapsed); + } + } + + // several instructions could be in the same line, only count the line once + if (!disable_coverage && (lineno != prev_line || NULL == prev_file || + 0 != strcmp(prev_file, filename))) { + int element = get_element(filename); + + // make sure the line exists in the database + create_lines(element, lineno); + + // increase line execution count + ++profiler_db[element].lines[lineno].exec_count; + } + + // store the current location as previous for the next call + set_prev(disable_profiler ? -1 : TTCN3_Stack_Depth::depth(), filename, lineno); +} + +int TTCN3_Profiler::get_element(const char* filename) +{ + for (size_t i = 0; i < profiler_db.size(); ++i) { + if (0 == strcmp(profiler_db[i].filename, filename)) { + return i; + } + } + + profiler_db_item_t item; + item.filename = mcopystr(filename); + profiler_db.push_back(item); + return profiler_db.size() - 1; +} + +int TTCN3_Profiler::get_function(int element, int lineno) +{ + for (size_t i = 0; i < profiler_db[element].functions.size(); ++i) { + if (profiler_db[element].functions[i].lineno == lineno) { + return i; + } + } + return -1; +} + +void TTCN3_Profiler::create_function(int element, int lineno, const char* function_name) +{ + profiler_db_item_t::profiler_function_data_t func_data; + func_data.lineno = lineno; + func_data.total_time = 0.0; + func_data.exec_count = 0; + func_data.name = mcopystr(function_name); + profiler_db[element].functions.push_back(func_data); +} + +void TTCN3_Profiler::create_lines(int element, int lineno) +{ + // set 0 for the unknown lines + size_t line_no = lineno; + if (profiler_db[element].lines.size() <= line_no) { + for (size_t i = profiler_db[element].lines.size(); i <= line_no; ++i) { + profiler_db_item_t::profiler_line_data_t line_data; + line_data.total_time = 0.0; + line_data.exec_count = 0; + profiler_db[element].lines.push_back(line_data); + } + } +} + +void TTCN3_Profiler::add_line_time(double elapsed, int element, int lineno) +{ + if (-1 == lineno) { + return; + } + + // ensure the line data exists + create_lines(element, lineno); + + // increase the time of the line in the current file: + profiler_db[element].lines[lineno].total_time += elapsed; +} + +void TTCN3_Profiler::add_function_time(double elapsed, int element, int lineno) +{ + int func = get_function(element, lineno); + if (-1 == func) { + return; + } + profiler_db[element].functions[func].total_time += elapsed; +} + +void TTCN3_Profiler::update_last() +{ + if (0.0 == prev_time) { + return; + } + + double currentTime = get_time(); + double elapsed = currentTime - prev_time; + + int element = get_element(prev_file); + + // add the elapsed time to the time of the previous line: + add_line_time(elapsed, element, prev_line); + TTCN3_Stack_Depth::update_stack_elapsed(elapsed); + + // reset measurement: + prev_time = 0.0; +} + +void TTCN3_Profiler::set_prev(int stack_len, const char* filename, int lineno) +{ + prev_file = filename; + prev_line = lineno; + if (!disable_profiler) { + prev_time = get_time(); + prev_stack_len = stack_len; + } +} + +///////////////////////////////////// +///////// TTCN3_Stack_Depth ///////// +///////////////////////////////////// + +int TTCN3_Stack_Depth::current_depth = -1; +Vector TTCN3_Stack_Depth::call_stack_timer_db; + +TTCN3_Stack_Depth::TTCN3_Stack_Depth() +{ + if (ttcn3_prof.is_profiler_disabled()) { + return; + } + ++current_depth; +} + +TTCN3_Stack_Depth::~TTCN3_Stack_Depth() +{ + if (ttcn3_prof.is_profiler_disabled()) { + return; + } + ttcn3_prof.update_last(); + remove_stack(); + if (0 == current_depth) { + ttcn3_prof.reset(); + } + --current_depth; +} + +void TTCN3_Stack_Depth::add_stack(int stack_len, const char* caller_file, const char* func_file, + int caller_line, int start_line) +{ + call_stack_timer_item_t item; + item.stack_len = stack_len; + item.caller_file = caller_file; + item.func_file = func_file; + item.caller_line = caller_line; + item.start_line = start_line; + item.elapsed = 0.0; + call_stack_timer_db.push_back(item); +} + +void TTCN3_Stack_Depth::remove_stack() +{ + // if stack level is the same or higher: measure the time: + double elapsed = call_stack_timer_db[current_depth].elapsed; + + int element = ttcn3_prof.get_element(call_stack_timer_db[current_depth].func_file); + + // add elapsed time to the total execution time of the previous line: + ttcn3_prof.add_function_time(elapsed, element, call_stack_timer_db[current_depth].start_line); + + ttcn3_prof.set_prev(call_stack_timer_db[current_depth].stack_len, + call_stack_timer_db[current_depth].caller_file, + call_stack_timer_db[current_depth].caller_line); + + call_stack_timer_db.erase_at(current_depth); +} + +void TTCN3_Stack_Depth::update_stack_elapsed(double elapsed) +{ + for(int i = 0; i <= current_depth; i++) { + call_stack_timer_db[i].elapsed += elapsed; + } +} \ No newline at end of file diff --git a/core/Profiler.hh b/core/Profiler.hh new file mode 100644 index 0000000..c84bb97 --- /dev/null +++ b/core/Profiler.hh @@ -0,0 +1,193 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2015 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// + +#ifndef PROFILER_HH +#define PROFILER_HH + +#include "Vector.hh" +#include "Types.h" + +/** This class performs profiling and code coverage on lines and functions in + * TTCN-3 code (requires the -z compiler option). + * Customizable through the configuration file's [PROFILER] section. */ +class TTCN3_Profiler { +public: + + /** Database entry for one file */ + struct profiler_db_item_t { + /** Database entry for one line */ + struct profiler_line_data_t { + /** The line's total execution time */ + double total_time; + /** The number of times this line was executed */ + int exec_count; + }; + /** Database entry for one function (including test cases, alt steps, the control part, etc.) */ + struct profiler_function_data_t { + /** Function name (owned) */ + char* name; + /** Function starting line */ + int lineno; + /** The function's total execution time */ + double total_time; + /** The number of times this function was executed */ + int exec_count; + }; + /** TTCN-3 File name (relative path, owned) */ + char* filename; + /** Contains database entries for all the lines in this file (its index is + * the line number, so there may be empty elements) */ + Vector lines; + /** Contains database entries for all the functions in this file (one entry + * for each function) */ + Vector functions; + }; + + /** Constructor */ + TTCN3_Profiler(); + /** Destructor - adds all gathered data to the database file and prints + * statistics if necessary */ + ~TTCN3_Profiler(); + + /** Enables or disables profiling - called by the config file parser */ + void set_disable_profiler(boolean p_disable_profiler); + /** Enables or disables code coverage - called by the config file parser */ + void set_disable_coverage(boolean p_disable_coverage); + /** Sets the database file name (default is "profiler.db" - called by the config file parser */ + void set_database_filename(const char* p_database_filename); + /** Enables or disables data aggregation - called by the config file parser */ + void set_aggregate_data(boolean p_aggregate_data); + /** Sets the statistics file name (default is "profiler.stats" - called by the config file parser */ + void set_stats_filename(const char* p_stats_filename); + /** Enables or disables the printing of statistics - called by the config file parser */ + void set_disable_stats(boolean p_disable_stats); + + /** Returns true if profiling is disabled */ + boolean is_profiler_disabled() const; + + /** Deletes the database file if data aggregation is not set */ + void init_data_file(); + /** Adds the data from the database file to the local database */ + void import_data(); + /** Writes the local database to the database file (overwrites the file) */ + void export_data(); + + /** Calculates and prints statistics from the gathered data */ + void print_stats(); + + /** Resets data related to the previous location and time (the local database is not changed) */ + void reset(); + /** Returns the current time (in seconds) */ + static double get_time(); + /** Called when a TTCN-3 function starts execution - stores data */ + void enter_function(const char* filename, int lineno, const char* function_name); + /** Called when a TTCN-3 code line starts execution - stores data */ + void execute_line(const char* filename, int lineno); + /** Returns the index of a TTCN-3 file's entry in the local database */ + int get_element(const char* filename); + /** Returns the index of a TTCN-3 function's entry in the database + * @param element index of the file (where the function is declared) + * @param lineno function start line */ + int get_function(int element, int lineno); + /** Creates a new TTCN-3 function entry and inserts it in the database + * @param element file entry's index + * @param lineno function start line + * @param function_name name of the function */ + void create_function(int element, int lineno, const char* function_name); + /** Creates TTCN-3 code line entries up to the given line number */ + void create_lines(int element, int lineno); + /** Adds elapsed time to the specified TTCN-3 code line's total time */ + void add_line_time(double elapsed, int element, int lineno); + /** Adds elapsed time to the specified TTCN-3 function's total time*/ + void add_function_time(double elapsed, int element, int lineno); + /** Called when a TTCN-3 function's execution ends - stores data */ + void update_last(); + /** Stores data related to the previous location */ + void set_prev(int stack_len, const char* filename, int lineno); + +private: + /** Profiling is disabled if true */ + boolean disable_profiler; + /** Code coverage is disabled if true */ + boolean disable_coverage; + /** Contains the database file name */ + char* database_filename; + /** If true, data gathered by previous runs will be added to the data gathered + * in this run */ + boolean aggregate_data; + /** Contains the statistics file name */ + char* stats_filename; + /** Statistics will not be calculated and printed if true */ + boolean disable_stats; + + /** The time measured at the previous TTCN-3 code line */ + double prev_time; + /** Name of the TTCN-3 file, where the last executed line is (not owned) */ + const char* prev_file; + /** The number of the previously executed line */ + int prev_line; + /** The local database */ + Vector profiler_db; + /** The stack length at the previously executed line */ + int prev_stack_len; +}; + +/** The global TTCN3_Profiler object + * + * One instance is created in each process (in parallel mode). + * After construction the configuration file parser may change the profiler's settings. + * The destructor merges its data with that of other processes (and possibly with previous runs) + * through the database file. The last destructor (the one in the Host Controller's process) + * prints the statistics (if enabled). */ +extern TTCN3_Profiler ttcn3_prof; + +/** Helper class for profiling + * + * Its instances depict the current call stack. One instance is created at the start + * of each TTCN-3 function execution, and it's destroyed at the function's end. */ +class TTCN3_Stack_Depth { +public: + /** Entry for one function call in the call stack */ + struct call_stack_timer_item_t { + /** Stack length before the function call */ + int stack_len; + /** File name, where the calling function is declared (not owned) */ + const char* caller_file; + /** File name, where the called function is declared (not owned)*/ + const char* func_file; + /** Calling function's start line */ + int caller_line; + /** Called function's start line */ + int start_line; + /** Time elapsed in this function call */ + double elapsed; + }; + + /** Constructor - increases the stack depth */ + TTCN3_Stack_Depth(); + /** Destructor - decreases the stack depth, updates call times in the profiler */ + ~TTCN3_Stack_Depth(); + + /** Returns the current stack depth */ + static int depth() { return current_depth; } + /** Inserts a new function call entry into the call stack database */ + static void add_stack(int stack_len, const char* caller_file, const char* func_file, + int caller_line, int start_line); + /** Removes the last entry from the call stack database */ + static void remove_stack(); + /** Adds the elapsed time to all entries in the call stack database */ + static void update_stack_elapsed(double elapsed); +private: + /** The current stack depth (starts from 0)*/ + static int current_depth; + /** The call stack database */ + static Vector call_stack_timer_db; +}; + +#endif /* PROFILER_HH */ + diff --git a/core/Template.hh b/core/Template.hh index de50db9..44ccdc4 100644 --- a/core/Template.hh +++ b/core/Template.hh @@ -161,9 +161,11 @@ public: boolean is_omit() const; boolean is_any_or_omit() const; - // Dummy functions, only used in record of/set of value +#ifdef TITAN_RUNTIME_2 + // Dummy functions, only used in record of/set of value in RT2 void add_refd_index(int) {} void remove_refd_index(int) {} +#endif }; #ifndef TITAN_RUNTIME_2 diff --git a/core/Universal_charstring.cc b/core/Universal_charstring.cc index 12a39eb..330f4f2 100644 --- a/core/Universal_charstring.cc +++ b/core/Universal_charstring.cc @@ -1079,7 +1079,7 @@ void UNIVERSAL_CHARSTRING::encode(const TTCN_Typedescriptor_t& p_td, default: // nothing to do break; } - XER_encode(*p_td.xer,p_buf, XER_coding, 0); + XER_encode(*p_td.xer,p_buf, XER_coding, 0, 0); p_buf.put_c('\n'); break; } case TTCN_EncDec::CT_JSON: { @@ -1126,7 +1126,7 @@ void UNIVERSAL_CHARSTRING::decode(const TTCN_Typedescriptor_t& p_td, if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break; } @@ -1486,7 +1486,7 @@ boolean UNIVERSAL_CHARSTRING::BER_decode_TLV extern void xml_escape(const unsigned int c, TTCN_Buffer& p_buf); int UNIVERSAL_CHARSTRING::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if(!is_bound()) { TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, @@ -1799,7 +1799,7 @@ in_word_set (const char *str, unsigned int len) universal_char const uspace = {0,0,0,32}; int UNIVERSAL_CHARSTRING::XER_decode(const XERdescriptor_t& p_td, - XmlReaderWrap& reader, unsigned int flavor) + XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); int success = reader.Ok(), depth = -1; diff --git a/core/Universal_charstring.hh b/core/Universal_charstring.hh index 5185032..62ea9fb 100644 --- a/core/Universal_charstring.hh +++ b/core/Universal_charstring.hh @@ -318,8 +318,8 @@ public: boolean BER_decode_TLV(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, unsigned L_form); - int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int) const; - int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int); + int XER_encode(const XERdescriptor_t&, TTCN_Buffer&, unsigned int, int, embed_values_enc_struct_t*) const; + int XER_decode(const XERdescriptor_t&, XmlReaderWrap& reader, unsigned int, embed_values_dec_struct_t*); /** Decodes UTF-8 into the internal representation (UCS4-BE) * * @param n_octets number of UTF-8 bytes (not characters) diff --git a/core/Verdicttype.cc b/core/Verdicttype.cc index 9cf0f87..e8ba460 100644 --- a/core/Verdicttype.cc +++ b/core/Verdicttype.cc @@ -154,7 +154,7 @@ void VERDICTTYPE::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*p_td.xer, p_buf, XER_coding, 0); + XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0); break;} case TTCN_EncDec::CT_JSON: { TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name); @@ -227,7 +227,7 @@ void VERDICTTYPE::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, if (type==XML_READER_TYPE_ELEMENT) break; } - XER_decode(*p_td.xer, reader, XER_coding); + XER_decode(*p_td.xer, reader, XER_coding, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -253,7 +253,7 @@ void VERDICTTYPE::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, int VERDICTTYPE::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int p_flavor, int p_indent) const + unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const { int encoded_length=(int)p_buf.get_len(); //const boolean e_xer = is_exer(p_flavor); @@ -285,7 +285,7 @@ verdicttype VERDICTTYPE::str_to_verdict(const char *v, boolean silent) } int VERDICTTYPE::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, - unsigned int p_flavor) + unsigned int p_flavor, embed_values_dec_struct_t*) { int rd_ok = 1, type; const int e_xer = is_exer(p_flavor); diff --git a/core/Verdicttype.hh b/core/Verdicttype.hh index ea0fdd8..4ea1a52 100644 --- a/core/Verdicttype.hh +++ b/core/Verdicttype.hh @@ -82,9 +82,9 @@ public: TTCN_EncDec::coding_t p_coding, ...); int XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent) const; + unsigned int flavor, int indent, embed_values_enc_struct_t*) const; int XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, - unsigned int flavor); + unsigned int flavor, embed_values_dec_struct_t*); /** Encodes accordingly to the JSON encoding rules. * Returns the length of the encoded data. */ diff --git a/core/XER.hh b/core/XER.hh index 27c6da5..604ca04 100644 --- a/core/XER.hh +++ b/core/XER.hh @@ -16,6 +16,10 @@ class XmlReaderWrap; class Base_Type; +#ifdef TITAN_RUNTIME_2 +class Record_Of_Type; +class Erroneous_descriptor_t; +#endif class TTCN_Module; /** @defgroup XER XER codec @@ -171,7 +175,7 @@ inline bool is_exerlist(unsigned int f) * Example: * @code * int Foo::XER_encode(const XERdescriptor_t& p_td, - * TTCN_Buffer& p_buf, unsigned int flavor, int indent) const { + * TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { * int canon = is_canonical(flavor); * if (!canon) do_indent(p_buf, indent); * // output the start tag @@ -193,7 +197,7 @@ inline bool is_exerlist(unsigned int f) * * @code * int Foo::XER_encode(const XERdescriptor_t& p_td, - * TTCN_Buffer& p_buf, unsigned int flavor, int indent) const { + * TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { * int canon = is_canonical(flavor); * if (!canon) do_indent(p_buf, indent); * // output an empty element tag @@ -253,6 +257,51 @@ struct XERdescriptor_t const char** ns_uris; }; +/** Information related to the embedded values in XML encoding + * + * Used when a record/set with the EMBED-VALUES coding instruction contains + * one or more record of/set of fields. */ +struct embed_values_enc_struct_t +{ +#ifdef TITAN_RUNTIME_2 + /** Stores the array of embedded values */ + const Record_Of_Type* embval_array; + /** Stores the erroneous descriptor of the embedded values field (for negative tests) */ + const Erroneous_descriptor_t* embval_err; + /** Error value index for the embedded values (for negative tests) */ + int embval_err_val_idx; + /** Erroneous descriptor index for the embedded values (for negative tests) */ + int embval_err_descr_idx; +#else + /** Stores the array of embedded values as a Base_Type (use get_embedded_value + * to retrieve values - temporarily disabled) */ + const Base_Type* embval_array; + /** Stores the size of the embedded value array */ + int embval_size; +#endif + /** Stores the index of the next embedded value to be read */ + int embval_index; +}; + +/** Information related to the embedded values in XML decoding + * + * Used when a record/set with the EMBED-VALUES coding instruction contains + * one or more record of/set of fields. */ +struct embed_values_dec_struct_t +{ +#ifdef TITAN_RUNTIME_2 + /** Stores the array of embedded values */ + Record_Of_Type* embval_array; +#else + /** Stores the array of embedded values as a Base_type (use set_embedded_value + * to insert new values - temporarily disabled) */ + Base_Type* embval_array; +#endif + /** Stores the number of embedded values that are currently in the array, + * and the index where the next one should be inserted */ + int embval_index; +}; + /** Check the name of an XML node against a XER type descriptor. * * @param name the (local, unqualified) name of the XML element diff --git a/core/config_process.l b/core/config_process.l index a1bdde0..4d96260 100644 --- a/core/config_process.l +++ b/core/config_process.l @@ -121,7 +121,7 @@ TTCNSTRINGPARSING_COMPONENT "$#&&&(#TTCNSTRINGPARSING_COMPONENT$#&&^#% " %x SC_commentblock SC_cstring SC_DEFINE %s SC_MODULE_PARAMETERS SC_LOGGING SC_TESTPORT_PARAMETERS SC_EXECUTE SC_GROUPS %s SC_COMPONENTS SC_EXTERNAL_COMMANDS SC_MAIN_CONTROLLER SC_INCLUDE SC_ORDERED_INCLUDE -%s SC_STRING2TTCN_COMPONENT +%s SC_STRING2TTCN_COMPONENT SC_PROFILER %% @@ -185,6 +185,13 @@ TTCNSTRINGPARSING_COMPONENT "$#&&&(#TTCNSTRINGPARSING_COMPONENT$#&&^#% " } } +<*>"["{WS}PROFILER{WS}"]" { + if (YY_START!=SC_commentblock && YY_START!=SC_cstring) { + BEGIN(SC_PROFILER); + return ProfilerKeyword; + } +} + <*>"["{WS}TESTPORT_PARAMETERS{WS}"]" { if (YY_START!=SC_commentblock && YY_START!=SC_cstring) { BEGIN(SC_TESTPORT_PARAMETERS); @@ -493,7 +500,7 @@ ifpresent return IfpresentKeyword; infinity return InfinityKeyword; } - + { true { yylval.bool_val = TRUE; @@ -957,6 +964,16 @@ LOG_ALL { [Dd]elete return Delete; } + +{ + [Dd]isable[Pp]rofiler return DisableProfilerKeyword; + [Dd]isable[Cc]overage return DisableCoverageKeyword; + [Dd]ata[Bb]ase[Ff]ile return DatabaseFileKeyword; + [Aa]ggregate[Dd]ata return AggregateDataKeyword; + [Ss]tatistics[Ff]ile return StatisticsFileKeyword; + [Dd]isable[Ss]tatistics return DisableStatisticsKeyword; +} + control return ControlKeyword; diff --git a/core/config_process.y b/core/config_process.y index dad4009..92c2097 100644 --- a/core/config_process.y +++ b/core/config_process.y @@ -37,6 +37,8 @@ #include "LoggingBits.hh" #include "LoggingParam.hh" +#include "Profiler.hh" + #define YYERROR_VERBOSE #include "config_process.lex.hh" @@ -128,6 +130,7 @@ string_map_t *config_defines; %token ModuleParametersKeyword %token LoggingKeyword +%token ProfilerKeyword %token TestportParametersKeyword %token ExecuteKeyword %token ExternalCommandsKeyword @@ -216,6 +219,12 @@ string_map_t *config_defines; %token Retry %token Delete %token TtcnStringParsingKeyword +%token DisableProfilerKeyword "DisableProfiler" +%token DisableCoverageKeyword "DisableCoverage" +%token DatabaseFileKeyword "DatabaseFile" +%token AggregateDataKeyword "AggregateData" +%token StatisticsFileKeyword "StatisticsFile" +%token DisableStatisticsKeyword "DisableStatistics" %type IntegerValue %type FloatValue @@ -375,6 +384,7 @@ ConfigFile: Section: ModuleParametersSection | LoggingSection + | ProfilerSection | TestportParametersSection | ExecuteSection | ExternalCommandsSection @@ -1660,6 +1670,62 @@ LogEventTypesValue: | Detailed { $$ = TTCN_Logger::LOGEVENTTYPES_SUBCATEGORIES; } ; +/*********************** [PROFILER] ********************************/ + +ProfilerSection: + ProfilerKeyword ProfilerSettings +; + +ProfilerSettings: + /* empty */ +| ProfilerSettings ProfilerSetting optSemiColon +; + +ProfilerSetting: + DisableProfilerSetting +| DisableCoverageSetting +| DatabaseFileSetting +| AggregateDataSetting +| StatisticsFileSetting +| DisableStatisticsSetting +; + +DisableProfilerSetting: + DisableProfilerKeyword AssignmentChar BooleanValue { + ttcn3_prof.set_disable_profiler($3); + } +; + +DisableCoverageSetting: + DisableCoverageKeyword AssignmentChar BooleanValue { + ttcn3_prof.set_disable_coverage($3); + } +; + +DatabaseFileSetting: + DatabaseFileKeyword AssignmentChar StringValue { + ttcn3_prof.set_database_filename($3); + } +; + +AggregateDataSetting: + AggregateDataKeyword AssignmentChar BooleanValue { + ttcn3_prof.set_aggregate_data($3); + } +; + +StatisticsFileSetting: + StatisticsFileKeyword AssignmentChar StringValue { + ttcn3_prof.set_stats_filename($3); + } +; + +DisableStatisticsSetting: + DisableStatisticsKeyword AssignmentChar BooleanValue { + ttcn3_prof.set_disable_stats($3); + } +; + /**************** [TESTPORT_PARAMETERS] ****************************/ TestportParametersSection: @@ -2141,6 +2207,8 @@ boolean process_config_file(const char *file_name) string_map_free(config_defines); config_defines = NULL; + ttcn3_prof.init_data_file(); + return !error_flag; } diff --git a/core2/Basetype2.cc b/core2/Basetype2.cc index 7a21147..c338947 100644 --- a/core2/Basetype2.cc +++ b/core2/Basetype2.cc @@ -176,9 +176,9 @@ int Base_Type::RAW_encode_negtest_raw(RAW_enc_tree&) const } int Base_Type::XER_encode_negtest(const Erroneous_descriptor_t* /*p_err_descr*/, - const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { - return XER_encode(p_td, p_buf, flavor, indent); // ignore erroneous + return XER_encode(p_td, p_buf, flavor, indent, 0); // ignore erroneous } int Base_Type::RAW_encode_negtest(const Erroneous_descriptor_t *, @@ -225,7 +225,7 @@ void Record_Of_Type::clean_up() val_ptr = NULL; } else if (val_ptr->ref_count == 1) { - if (refd_indices.empty()) { + if (NULL == refd_ind_ptr) { for (int elem_count = 0; elem_count < val_ptr->n_elements; elem_count++) { if (val_ptr->value_elements[elem_count] != NULL) { delete val_ptr->value_elements[elem_count]; @@ -247,7 +247,7 @@ void Record_Of_Type::clean_up() } Record_Of_Type::Record_Of_Type(null_type /*other_value*/) -: Base_Type(), val_ptr(new recordof_setof_struct), err_descr(NULL), max_refd_index(-1) +: Base_Type(), val_ptr(new recordof_setof_struct), err_descr(NULL), refd_ind_ptr(NULL) { val_ptr->ref_count = 1; val_ptr->n_elements = 0; @@ -255,13 +255,13 @@ Record_Of_Type::Record_Of_Type(null_type /*other_value*/) } Record_Of_Type::Record_Of_Type(const Record_Of_Type& other_value) -: Base_Type(other_value), val_ptr(NULL), err_descr(other_value.err_descr), max_refd_index(-1) +: Base_Type(other_value), val_ptr(NULL), err_descr(other_value.err_descr), refd_ind_ptr(NULL) { if (!other_value.is_bound()) TTCN_error("Copying an unbound record of/set of value."); // Increment ref_count only if val_ptr is not NULL if (other_value.val_ptr != NULL) { - if (other_value.refd_indices.empty()) { + if (NULL == other_value.refd_ind_ptr) { val_ptr = other_value.val_ptr; val_ptr->ref_count++; } @@ -281,7 +281,7 @@ Record_Of_Type::Record_Of_Type(const Record_Of_Type& other_value) int Record_Of_Type::get_nof_elements() const { int nof_elements = (val_ptr != NULL) ? val_ptr->n_elements : 0; - if (!refd_indices.empty()) { + if (NULL != refd_ind_ptr) { while (nof_elements > 0) { if (is_elem_bound(nof_elements - 1)) { break; @@ -300,23 +300,26 @@ bool Record_Of_Type::is_elem_bound(int index) const int Record_Of_Type::get_max_refd_index() { - if (refd_indices.empty()) { + if (NULL == refd_ind_ptr) { return -1; } - if (-1 == max_refd_index) { - for (size_t i = 0; i < refd_indices.size(); ++i) { - if (refd_indices[i] > max_refd_index) { - max_refd_index = refd_indices[i]; + if (-1 == refd_ind_ptr->max_refd_index) { + for (size_t i = 0; i < refd_ind_ptr->refd_indices.size(); ++i) { + if (refd_ind_ptr->refd_indices[i] > refd_ind_ptr->max_refd_index) { + refd_ind_ptr->max_refd_index = refd_ind_ptr->refd_indices[i]; } } } - return max_refd_index; + return refd_ind_ptr->max_refd_index; } bool Record_Of_Type::is_index_refd(int index) { - for (size_t i = 0; i < refd_indices.size(); ++i) { - if (index == refd_indices[i]) { + if (NULL == refd_ind_ptr) { + return false; + } + for (size_t i = 0; i < refd_ind_ptr->refd_indices.size(); ++i) { + if (index == refd_ind_ptr->refd_indices[i]) { return true; } } @@ -362,7 +365,7 @@ void Record_Of_Type::set_value(const Base_Type* other_value) TTCN_error("Assigning an unbound value of type %s.", other_value->get_descriptor()->name); if (this != other_recof) { - if (refd_indices.empty() && other_recof->refd_indices.empty()) { + if (NULL == refd_ind_ptr && NULL == other_recof->refd_ind_ptr) { clean_up(); val_ptr = other_recof->val_ptr; val_ptr->ref_count++; @@ -733,7 +736,7 @@ void Record_Of_Type::set_size(int new_size) boolean Record_Of_Type::is_bound() const { - if (refd_indices.empty()) { + if (NULL == refd_ind_ptr) { return (val_ptr != NULL); } return (get_nof_elements() != 0); @@ -1020,7 +1023,7 @@ int Record_Of_Type::TEXT_decode(const TTCN_Typedescriptor_t& p_td, break; } sep_found=FALSE; - if (refd_indices.empty()) { + if (NULL == refd_ind_ptr) { val_ptr->value_elements = (Base_Type**)reallocate_pointers( (void**)val_ptr->value_elements, val_ptr->n_elements, val_ptr->n_elements + 1); val_ptr->value_elements[val_ptr->n_elements]=val; @@ -1469,7 +1472,7 @@ int Record_Of_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenize } return JSON_ERROR_FATAL; } - if (refd_indices.empty()) { + if (NULL == refd_ind_ptr) { val_ptr->value_elements = (Base_Type**)reallocate_pointers( (void**)val_ptr->value_elements, val_ptr->n_elements, val_ptr->n_elements + 1); val_ptr->value_elements[val_ptr->n_elements] = val; @@ -1528,7 +1531,7 @@ void Record_Of_Type::encode(const TTCN_Typedescriptor_t& p_td, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*(p_td.xer),p_buf, XER_coding, 0); + XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0); p_buf.put_c('\n'); break;} case TTCN_EncDec::CT_JSON: { @@ -1598,7 +1601,7 @@ void Record_Of_Type::decode(const TTCN_Typedescriptor_t& p_td, for (int success=reader.Read(); success==1; success=reader.Read()) { if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break; } - XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL); + XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -1652,10 +1655,10 @@ static const universal_char sp = { 0,0,0,' ' }; static const universal_char tb = { 0,0,0,9 }; int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent) const + unsigned int flavor, int indent, embed_values_enc_struct_t* emb_val) const { if (err_descr) { - return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent); + return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent, emb_val); } if (val_ptr == 0) TTCN_error( @@ -1745,7 +1748,7 @@ int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, check_namespace_restrictions(p_td, (const char*)cs); } before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, - flavor | ANY_ATTRIBUTES, indent); + flavor | ANY_ATTRIBUTES, indent, 0); p_buf.put_c('\''); p_buf.put_c(' '); @@ -1767,7 +1770,7 @@ int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, UNIVERSAL_CHARSTRING after(len - j, (const universal_char*)(*elem) + j); after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, - flavor | ANY_ATTRIBUTES, indent); + flavor | ANY_ATTRIBUTES, indent, 0); // Put this attribute in a dummy element and walk through it to check its validity TTCN_Buffer check_buf; @@ -1785,9 +1788,15 @@ int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int sub_flavor = flavor | XER_RECOF | (p_td.xer_bits & (XER_LIST)); for (int i = 0; i < nof_elements; ++i) { + if (i > 0 && !own_tag && 0 != emb_val && + emb_val->embval_index < emb_val->embval_array->size_of()) { + emb_val->embval_array->get_at(emb_val->embval_index)->XER_encode( + UNIVERSAL_CHARSTRING_xer_, p_buf, flavor | EMBED_VALUES, indent+1, 0); + ++emb_val->embval_index; + } if (exer && (p_td.xer_bits & XER_LIST) && i>0) p_buf.put_c(' '); get_at(i)->XER_encode(*get_elem_descr()->xer, p_buf, - sub_flavor, indent+own_tag); + sub_flavor, indent+own_tag, emb_val); } if (indenting && nof_elements && !is_exerlist(flavor)) { @@ -1817,7 +1826,7 @@ int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, */ int Record_Of_Type::encode_element(int i, const Erroneous_values_t* ev, const Erroneous_descriptor_t* ed, - TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent, embed_values_enc_struct_t* emb_val) const { int enc_len = p_buf.get_len(); TTCN_EncDec_ErrorContext ec; @@ -1834,7 +1843,7 @@ int Record_Of_Type::encode_element(int i, if (ev->before->type_descr==NULL) TTCN_error( "internal error: erroneous before type descriptor missing"); ev->before->errval->XER_encode(*ev->before->type_descr->xer, - p_buf, sub_flavor, indent); + p_buf, sub_flavor, indent, 0); } } @@ -1854,16 +1863,16 @@ int Record_Of_Type::encode_element(int i, if (ev->value->type_descr==NULL) TTCN_error( "internal error: erroneous value type descriptor missing"); ev->value->errval->XER_encode(*ev->value->type_descr->xer, - p_buf, sub_flavor, indent); + p_buf, sub_flavor, indent, 0); } } // else -> omit } else { ec.set_msg("Component #%d: ", i); if (ed) { - get_at(i)->XER_encode_negtest(ed, *get_elem_descr()->xer, p_buf, sub_flavor, indent); + get_at(i)->XER_encode_negtest(ed, *get_elem_descr()->xer, p_buf, sub_flavor, indent, emb_val); } else { // the "real" encoder - get_at(i)->XER_encode(*get_elem_descr()->xer, p_buf, sub_flavor, indent); + get_at(i)->XER_encode(*get_elem_descr()->xer, p_buf, sub_flavor, indent, emb_val); } } @@ -1878,7 +1887,7 @@ int Record_Of_Type::encode_element(int i, if (ev->after->type_descr==NULL) TTCN_error( "internal error: erroneous after type descriptor missing"); ev->after->errval->XER_encode(*ev->after->type_descr->xer, - p_buf, sub_flavor, indent); + p_buf, sub_flavor, indent, 0); } } @@ -1887,7 +1896,8 @@ int Record_Of_Type::encode_element(int i, // XERSTUFF Record_Of_Type::XER_encode_negtest int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, - const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned flavor, int indent) const + const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned flavor, int indent, + embed_values_enc_struct_t* emb_val) const { if (val_ptr == 0) TTCN_error( "Attempt to XER-encode an unbound record of type %s", get_descriptor()->name); @@ -1949,7 +1959,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr if (ev->before->type_descr==NULL) TTCN_error( "internal error: erroneous before type descriptor missing"); else ev->before->errval->XER_encode(*ev->before->type_descr->xer, - p_buf, flavor, indent); + p_buf, flavor, indent, 0); } } @@ -1960,7 +1970,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr if (ev->value->type_descr==NULL) TTCN_error( "internal error: erroneous value type descriptor missing"); else ev->value->errval->XER_encode(*ev->value->type_descr->xer, - p_buf, flavor, indent); + p_buf, flavor, indent, 0); } } } @@ -2001,7 +2011,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr UNIVERSAL_CHARSTRING before(sp_at, (const universal_char*)(*elem)); before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, - flavor | ANY_ATTRIBUTES, indent); + flavor | ANY_ATTRIBUTES, indent, 0); p_buf.put_c('\''); p_buf.put_c(' '); @@ -2018,7 +2028,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr UNIVERSAL_CHARSTRING after(len - j, (const universal_char*)(*elem) + j); after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, - flavor | ANY_ATTRIBUTES, indent); + flavor | ANY_ATTRIBUTES, indent, 0); } } @@ -2031,7 +2041,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr if (ev->after->type_descr==NULL) TTCN_error( "internal error: erroneous after type descriptor missing"); else ev->after->errval->XER_encode(*ev->after->type_descr->xer, - p_buf, flavor, indent); + p_buf, flavor, indent, 0); } } } @@ -2050,13 +2060,26 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr for (int i = 0; i < nof_elements; ++i) { if (i < p_err_descr->omit_before) continue; + + if (0 != emb_val && i > 0 && !own_tag && + emb_val->embval_index < emb_val->embval_array->size_of()) { + const Erroneous_values_t * ev0_i = NULL; + const Erroneous_descriptor_t* ed0_i = NULL; + if (emb_val->embval_err) { + ev0_i = emb_val->embval_err->next_field_err_values(emb_val->embval_index, emb_val->embval_err_val_idx); + ed0_i = emb_val->embval_err->next_field_emb_descr (emb_val->embval_index, emb_val->embval_err_descr_idx); + } + emb_val->embval_array->encode_element(emb_val->embval_index, ev0_i, ed0_i, + p_buf, flavor | EMBED_VALUES, indent + own_tag, 0); + ++emb_val->embval_index; + } const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(i, values_idx); const Erroneous_descriptor_t* emb_descr = p_err_descr->next_field_emb_descr (i, edescr_idx); - encode_element(i, err_vals, emb_descr, p_buf, sub_flavor, indent+own_tag); + encode_element(i, err_vals, emb_descr, p_buf, sub_flavor, indent+own_tag, emb_val); // omit_after value -1 becomes "very big" if ((unsigned int)i >= (unsigned int)p_err_descr->omit_after) break; @@ -2073,7 +2096,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr } int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td, - XmlReaderWrap& reader, unsigned int flavor) + XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t* emb_val) { int exer = is_exer(flavor); int xerbits = p_td.xer_bits; @@ -2152,7 +2175,7 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td, // The call to the non-const operator[], I mean get_at(), creates // a new element (because it is indexing one past the last element). // Then we call its XER_decode with the temporary XML reader. - get_at(get_nof_elements())->XER_decode(sub_xer, reader2, flavor); + get_at(get_nof_elements())->XER_decode(sub_xer, reader2, flavor, 0); if (flavor & EXIT_ON_ERROR && !is_elem_bound(get_nof_elements() - 1)) { if (1 == get_nof_elements()) { // Failed to decode even the first element @@ -2218,7 +2241,10 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td, } ec_1.set_msg("%d: ", get_nof_elements()); /* The call to the non-const get_at() creates the element */ - get_at(get_nof_elements())->XER_decode(*get_elem_descr()->xer, reader, flavor); + get_at(get_nof_elements())->XER_decode(*get_elem_descr()->xer, reader, flavor, emb_val); + if (0 != emb_val && !own_tag && get_nof_elements() > 1) { + ++emb_val->embval_index; + } } } else if (XML_READER_TYPE_END_ELEMENT == type) { @@ -2231,6 +2257,11 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td, } break; } + else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && get_nof_elements() > 0) { + UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value()); + emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr); + success = reader.Read(); + } else { success = reader.Read(); } @@ -2317,22 +2348,30 @@ void Record_Of_Type::set_implicit_omit() void Record_Of_Type::add_refd_index(int index) { - refd_indices.push_back(index); + if (NULL == refd_ind_ptr) { + refd_ind_ptr = new refd_index_struct; + refd_ind_ptr->max_refd_index = -1; + } + refd_ind_ptr->refd_indices.push_back(index); if (index > get_max_refd_index()) { - max_refd_index = index; + refd_ind_ptr->max_refd_index = index; } } void Record_Of_Type::remove_refd_index(int index) { - for (size_t i = refd_indices.size(); i > 0; --i) { - if (refd_indices[i - 1] == index) { - refd_indices.erase_at(i - 1); + for (size_t i = refd_ind_ptr->refd_indices.size(); i > 0; --i) { + if (refd_ind_ptr->refd_indices[i - 1] == index) { + refd_ind_ptr->refd_indices.erase_at(i - 1); break; } } - if (get_max_refd_index() == index) { - max_refd_index = -1; + if (refd_ind_ptr->refd_indices.empty()) { + delete refd_ind_ptr; + refd_ind_ptr = NULL; + } + else if (get_max_refd_index() == index) { + refd_ind_ptr->max_refd_index = -1; } } @@ -2592,7 +2631,7 @@ void Record_Type::encode(const TTCN_Typedescriptor_t& p_td, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*(p_td.xer),p_buf, XER_coding, 0); + XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0); p_buf.put_c('\n'); break;} case TTCN_EncDec::CT_JSON: { @@ -2678,7 +2717,7 @@ void Record_Type::decode(const TTCN_Typedescriptor_t& p_td, for (int success=reader.Read(); success==1; success=reader.Read()) { if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break; } - XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL); + XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -3851,10 +3890,10 @@ int Record_Type::get_index_byname(const char *name, const char *uri) const { } int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent) const + unsigned int flavor, int indent, embed_values_enc_struct_t*) const { if (err_descr) { - return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent); + return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent, 0); } if (!is_bound()) { TTCN_EncDec_ErrorContext::error @@ -3961,7 +4000,7 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, const Base_Type * const q_uri = get_at(0); if (q_uri->is_present()) { p_buf.put_s(11, (cbyte*)" xmlns:b0='"); - q_uri->XER_encode(*xer_descr(0), p_buf, flavor | XER_LIST, indent+1); + q_uri->XER_encode(*xer_descr(0), p_buf, flavor | XER_LIST, indent+1, 0); p_buf.put_c('\''); } @@ -3973,18 +4012,18 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, sub_len += 3; } const Base_Type* const q_name = get_at(1); - sub_len += q_name->XER_encode(*xer_descr(1), p_buf, flavor | XER_LIST, indent+1); + sub_len += q_name->XER_encode(*xer_descr(1), p_buf, flavor | XER_LIST, indent+1, 0); if (p_td.xer_bits & XER_ATTRIBUTE) p_buf.put_c('\''); } else { // not USE-QNAME if (!exer && (p_td.xer_bits & EMBED_VALUES)) { // The EMBED-VALUES member as an ordinary record of string - sub_len += embed_values->XER_encode(*xer_descr(0), p_buf, flavor, indent+1); + sub_len += embed_values->XER_encode(*xer_descr(0), p_buf, flavor, indent+1, 0); } if (!exer && (p_td.xer_bits & USE_ORDER)) { // The USE-ORDER member as an ordinary record of enumerated - sub_len += use_order->XER_encode(*xer_descr(uo_index), p_buf, flavor, indent+1); + sub_len += use_order->XER_encode(*xer_descr(uo_index), p_buf, flavor, indent+1, 0); } if (exer && (indent==0 || (flavor & DEF_NS_SQUASHED))) // write namespaces for toplevel only @@ -4011,7 +4050,7 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, for (i = start_at; i < first_nonattr; ++i) { boolean is_xer_attr_field = xer_descr(i)->xer_bits & XER_ATTRIBUTE; ec_1.set_msg("%s': ", fld_name(i)); // attr - int tmp_len = get_at(i)->XER_encode(*xer_descr(i), p_buf, flavor, indent+1); + int tmp_len = get_at(i)->XER_encode(*xer_descr(i), p_buf, flavor, indent+1, 0); if (is_xer_attr_field && !exer) sub_len += tmp_len; /* do not add if attribute and EXER */ } @@ -4043,31 +4082,11 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, p_buf.put_s(start_tag_len , (cbyte*)">\n"); } - int expected_embed = (field_cnt - first_nonattr + 1); if (exer && (p_td.xer_bits & EMBED_VALUES)) { - ec_1.set_msg("%s': ", fld_name(0)); - int num_opt; - if ((p_td.xer_bits & USE_NIL) && !get_at(field_cnt-1)->ispresent()) { - expected_embed = 0; //25.2.6 a - } - else if ((num_opt = optional_count())) { - const int * optionals = get_optional_indexes(); - for (int opt_idx = 0; opt_idx < num_opt; ++opt_idx) { - // skip optional attributes - if (optionals[opt_idx] < start_at + num_attributes) continue; - // reduce for each omitted member - if (!get_at(optionals[opt_idx])->is_present()) --expected_embed; - } - } - // Check the correct number of EMBED-VALUES (regular non-attributes + 1) - if (embed_values->size_of() != expected_embed) - TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, - "Wrong number %d of EMBED-VALUEs, expected %d", - embed_values->size_of(), expected_embed); /* write the first string */ - if (expected_embed > 0) { + if (embed_values->size_of() > 0) { sub_len += embed_values->get_at(0)->XER_encode(UNIVERSAL_CHARSTRING_xer_, - p_buf, flavor | EMBED_VALUES, indent+1); + p_buf, flavor | EMBED_VALUES, indent+1, 0); } } @@ -4147,33 +4166,55 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, * pseudo-members for USE-ORDER, etc.) */ // early_to_bed can only be true if exer is true (transitive through nil_attribute) - if (!early_to_bed) for ( i = begin; i < end; ++i ) { - const Base_Type *uoe = 0; // "useOrder enum" - const Enum_Type *enm = 0; // the enum value selecting the field - if (exer && use_order) { - uoe = use_order->get_at(i - begin); - enm = static_cast(uoe); - } - - // "actual" index, may be perturbed by USE-ORDER - int ai = !(exer && (p_td.xer_bits & USE_ORDER)) ? i : - enm->as_int() + useorder_base; - ec_1.set_msg("%s': ", ordered->fld_name(ai)); // non-attr - - const XERdescriptor_t& descr = *ordered->xer_descr(ai); - sub_len += ordered->get_at(ai)->XER_encode(descr, p_buf, - // Pass USE-NIL to the last field (except when USE-ORDER is also in effect, - // because the tag-stripping effect of USE-NIL has been achieved - // by encoding the sub-fields directly). - flavor | ((exer && !use_order && (i == field_cnt-1)) ? (p_td.xer_bits & USE_NIL) : 0), - indent+!omit_tag); - - // Now the next embed-values string (NOT affected by USE-ORDER!) - if (exer && (p_td.xer_bits & EMBED_VALUES) && (i - begin + 1) < expected_embed) { - embed_values->get_at(i - begin + 1)->XER_encode(UNIVERSAL_CHARSTRING_xer_ - , p_buf, flavor | EMBED_VALUES, indent+1); - } - } //for + if (!early_to_bed) { + embed_values_enc_struct_t* emb_val = 0; + if (exer && (p_td.xer_bits & EMBED_VALUES) && embed_values->size_of() > 1) { + emb_val = new embed_values_enc_struct_t; + emb_val->embval_array = embed_values; + emb_val->embval_index = 1; + emb_val->embval_err = 0; + } + + for ( i = begin; i < end; ++i ) { + const Base_Type *uoe = 0; // "useOrder enum" + const Enum_Type *enm = 0; // the enum value selecting the field + if (exer && use_order) { + uoe = use_order->get_at(i - begin); + enm = static_cast(uoe); + } + + // "actual" index, may be perturbed by USE-ORDER + int ai = !(exer && (p_td.xer_bits & USE_ORDER)) ? i : + enm->as_int() + useorder_base; + ec_1.set_msg("%s': ", ordered->fld_name(ai)); // non-attr + + const XERdescriptor_t& descr = *ordered->xer_descr(ai); + sub_len += ordered->get_at(ai)->XER_encode(descr, p_buf, + // Pass USE-NIL to the last field (except when USE-ORDER is also in effect, + // because the tag-stripping effect of USE-NIL has been achieved + // by encoding the sub-fields directly). + flavor | ((exer && !use_order && (i == field_cnt-1)) ? (p_td.xer_bits & USE_NIL) : 0), + indent+!omit_tag, emb_val); + + // Now the next embed-values string (NOT affected by USE-ORDER!) + if (exer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val && + emb_val->embval_index < embed_values->size_of()) { + embed_values->get_at(emb_val->embval_index)->XER_encode(UNIVERSAL_CHARSTRING_xer_ + , p_buf, flavor | EMBED_VALUES, indent+1, 0); + ++emb_val->embval_index; + } + } //for + + if (0 != emb_val) { + if (emb_val->embval_index < embed_values->size_of()) { + ec_1.set_msg("%s': ", fld_name(0)); + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, + "Too many EMBED-VALUEs specified: %d (expected %d or less)", + embed_values->size_of(), emb_val->embval_index); + } + delete emb_val; + } + } // if (!early_to_bed) } // if (QNAME) if (!omit_tag) { @@ -4226,7 +4267,7 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, */ int Record_Type::encode_field(int i, const Erroneous_values_t* err_vals, const Erroneous_descriptor_t* emb_descr, - TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent, embed_values_enc_struct_t* emb_val) const { int enc_len = 0; TTCN_EncDec_ErrorContext ec; @@ -4240,7 +4281,7 @@ int Record_Type::encode_field(int i, if (err_vals->before->type_descr==NULL) TTCN_error( "internal error: erroneous before typedescriptor missing"); enc_len += err_vals->before->errval->XER_encode( - *err_vals->before->type_descr->xer, p_buf, sub_flavor, indent); + *err_vals->before->type_descr->xer, p_buf, sub_flavor, indent, 0); } } @@ -4253,18 +4294,18 @@ int Record_Type::encode_field(int i, if (err_vals->value->type_descr==NULL) TTCN_error( "internal error: erroneous value typedescriptor missing"); enc_len += err_vals->value->errval->XER_encode( - *err_vals->value->type_descr->xer, p_buf, sub_flavor, indent); + *err_vals->value->type_descr->xer, p_buf, sub_flavor, indent, 0); } } // else -> omit } else { ec.set_msg("Component %s: ", fld_name(i)); if (emb_descr) { enc_len += get_at(i)->XER_encode_negtest(emb_descr, *xer_descr(i), p_buf, - sub_flavor, indent); + sub_flavor, indent, emb_val); } else { // the "real" encoder enc_len += get_at(i)->XER_encode(*xer_descr(i), p_buf, - sub_flavor, indent); + sub_flavor, indent, emb_val); } } @@ -4278,7 +4319,7 @@ int Record_Type::encode_field(int i, if (err_vals->after->type_descr==NULL) TTCN_error( "internal error: erroneous after typedescriptor missing"); enc_len += err_vals->after->errval->XER_encode( - *err_vals->after->type_descr->xer, p_buf, sub_flavor, indent); + *err_vals->after->type_descr->xer, p_buf, sub_flavor, indent, 0); } } @@ -4287,7 +4328,8 @@ int Record_Type::encode_field(int i, // XERSTUFF Record_Type::XER_encode_negtest int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, - const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent, + embed_values_enc_struct_t*) const { if (!is_bound()) { TTCN_EncDec_ErrorContext::error @@ -4411,7 +4453,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, if (ev->before->type_descr==NULL) TTCN_error( "internal error: erroneous before typedescriptor missing"); sub_len += ev->before->errval->XER_encode( - *ev->before->type_descr->xer, p_buf, flavor, indent); + *ev->before->type_descr->xer, p_buf, flavor, indent, 0); } } @@ -4424,7 +4466,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, if (ev->value->type_descr==NULL) TTCN_error( "internal error: erroneous value typedescriptor missing"); sub_len += ev->value->errval->XER_encode( - *ev->value->type_descr->xer, p_buf, flavor, indent); + *ev->value->type_descr->xer, p_buf, flavor, indent, 0); } } // else -> omit } else { @@ -4438,7 +4480,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, // the "real" encoder if (q_uri->is_present()) { p_buf.put_s(11, (cbyte*)" xmlns:b0='"); - sub_len += q_uri->XER_encode(*xer_descr(0), p_buf, flavor | XER_LIST, indent+1); + sub_len += q_uri->XER_encode(*xer_descr(0), p_buf, flavor | XER_LIST, indent+1, 0); p_buf.put_c('\''); } } @@ -4454,7 +4496,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, if (ev->after->type_descr==NULL) TTCN_error( "internal error: erroneous after typedescriptor missing"); sub_len += ev->after->errval->XER_encode( - *ev->after->type_descr->xer, p_buf, flavor, indent); + *ev->after->type_descr->xer, p_buf, flavor, indent, 0); } } @@ -4475,7 +4517,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, if (ev->before->type_descr==NULL) TTCN_error( "internal error: erroneous before typedescriptor missing"); sub_len += ev->before->errval->XER_encode( - *ev->before->type_descr->xer, p_buf, flavor, indent); + *ev->before->type_descr->xer, p_buf, flavor, indent, 0); } } @@ -4488,7 +4530,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, if (ev->value->type_descr==NULL) TTCN_error( "internal error: erroneous value typedescriptor missing"); sub_len += ev->value->errval->XER_encode( - *ev->value->type_descr->xer, p_buf, flavor, indent); + *ev->value->type_descr->xer, p_buf, flavor, indent, 0); } } // else -> omit } else { @@ -4503,7 +4545,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, sub_len += 3; } - sub_len += get_at(1)->XER_encode(*xer_descr(1), p_buf, flavor | XER_LIST, indent+1); + sub_len += get_at(1)->XER_encode(*xer_descr(1), p_buf, flavor | XER_LIST, indent+1, 0); } } @@ -4517,7 +4559,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, if (ev->after->type_descr==NULL) TTCN_error( "internal error: erroneous after typedescriptor missing"); sub_len += ev->after->errval->XER_encode( - *ev->after->type_descr->xer, p_buf, flavor, indent); + *ev->after->type_descr->xer, p_buf, flavor, indent, 0); } } @@ -4526,12 +4568,12 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, else { // not USE-QNAME if (!exer && (p_td.xer_bits & EMBED_VALUES)) { // The EMBED-VALUES member as an ordinary record of string - sub_len += embed_values->XER_encode(*xer_descr(0), p_buf, flavor, indent+1); + sub_len += embed_values->XER_encode(*xer_descr(0), p_buf, flavor, indent+1, 0); } if (!exer && (p_td.xer_bits & USE_ORDER)) { // The USE-ORDER member as an ordinary record of enumerated - sub_len += use_order->XER_encode(*xer_descr(uo_index), p_buf, flavor, indent+1); + sub_len += use_order->XER_encode(*xer_descr(uo_index), p_buf, flavor, indent+1, 0); } if (exer && (indent==0 || (flavor & DEF_NS_SQUASHED))) // write namespaces for toplevel only @@ -4572,7 +4614,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, boolean is_xer_attr_field = xer_descr(i)->xer_bits & XER_ATTRIBUTE; ec_1.set_msg("%s': ", fld_name(i)); // attr - tmp_len = encode_field(i, ev, ed, p_buf, flavor, indent + !omit_tag); + tmp_len = encode_field(i, ev, ed, p_buf, flavor, indent + !omit_tag, 0); if (is_xer_attr_field && !exer) sub_len += tmp_len; // do not add if attribute and EXER @@ -4637,31 +4679,11 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, int embed_values_val_idx = 0; int embed_values_descr_idx = 0; - int expected_embed = (field_cnt - first_nonattr + 1); if (exer && (p_td.xer_bits & EMBED_VALUES)) { ed0 = p_err_descr->next_field_emb_descr(0, edescr_idx); - ec_1.set_msg("%s': ", fld_name(0)); - int num_opt; - if ((p_td.xer_bits & USE_NIL) && !get_at(field_cnt-1)->ispresent()) { - expected_embed = 0; //25.2.6 a - } - else if ((num_opt = optional_count()) > 0) { - const int * optionals = get_optional_indexes(); - for (int opt_idx = 0; opt_idx < num_opt; ++opt_idx) { - // skip optional attributes - if (optionals[opt_idx] < start_at + num_attributes) continue; - // reduce for each omitted member - if (!get_at(optionals[opt_idx])->is_present()) --expected_embed; - } - } - // Check the correct number of EMBED-VALUES (regular non-attributes + 1) - if (embed_values->size_of() != expected_embed) - TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, - "Wrong number %d of EMBED-VALUEs, expected %d", - embed_values->size_of(), expected_embed); // write the first string - if (expected_embed > 0) { + if (embed_values->size_of() > 0) { const Erroneous_values_t * ev0_0 = NULL; const Erroneous_descriptor_t* ed0_0 = NULL; if (ed0) { @@ -4669,7 +4691,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, ed0_0 = ed0->next_field_emb_descr (0, embed_values_descr_idx); } sub_len += embed_values->encode_element(0, ev0_0, ed0_0, - p_buf, flavor | EMBED_VALUES, indent+!omit_tag); + p_buf, flavor | EMBED_VALUES, indent+!omit_tag, 0); } } @@ -4757,64 +4779,86 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, // fields of this record; and the USE_ORDER case (with or without USE-NIL). // // early_to_bed can only be true if exer is true (transitive through nil_attribute) - if (!early_to_bed) for ( i = begin; i < end; ++i ) { - - const Base_Type *uoe = 0; // "useOrder enum" - const Enum_Type *enm = 0; // the enum value selecting the field - - // "actual" index, may be perturbed by USE-ORDER. - // We use this value to index the appropriate record. - int ai = i; - - const Erroneous_values_t * ev = NULL; - const Erroneous_descriptor_t* ed = NULL; - if (exer && use_order) { - // If USE-ORDER is in effect, it introduces a level of indirection - // into the indexing of fields: "i" is used to select an element - // of the use_order member (an enum), whose value is used to select - // the field being encoded. - uoe = use_order->get_at(i - begin); - enm = static_cast(uoe); - ai = enm->as_int() + useorder_base; - - // Because it is not guaranteed that ai will increase monotonically, - // we can't use next_field_...(). - ev = p_err_descr->get_field_err_values(ai); - ed = p_err_descr->get_field_emb_descr (ai); - } - else { // not USE-ORDER, sequential access - ev = p_err_descr->next_field_err_values(ai, values_idx); - ed = p_err_descr->next_field_emb_descr (ai, edescr_idx); - } - ec_1.set_msg("%s': ", ordered->fld_name(ai)); // non-attr - - if (ai < p_err_descr->omit_before) continue; - - // omit_after value -1 becomes "very big". - if ((unsigned int)ai > (unsigned int)p_err_descr->omit_after) continue; - // We can't skip all fields with break, because the next ai may be lower - // than omit_after. - - sub_len += ordered->encode_field(ai, ev, ed, p_buf, - // Pass USE-NIL to the last field (except when USE-ORDER is also in effect, - // because the tag-stripping effect of USE-NIL has been achieved - // by encoding the sub-fields directly). - flavor | ((exer && !use_order && (i == field_cnt-1)) ? (p_td.xer_bits & USE_NIL) : 0), - indent + !omit_tag); - - // Now the next embed-values string (NOT affected by USE-ORDER!) - int i1 = i - begin + 1; - if (exer && (p_td.xer_bits & EMBED_VALUES) && i1 < expected_embed) { - const Erroneous_values_t * ev0_i = NULL; - const Erroneous_descriptor_t* ed0_i = NULL; - if (ed0) { - ev0_i = ed0->next_field_err_values(i1, embed_values_val_idx); - ed0_i = ed0->next_field_emb_descr (i1, embed_values_descr_idx); + if (!early_to_bed) { + embed_values_enc_struct_t* emb_val = 0; + if (exer && (p_td.xer_bits & EMBED_VALUES) && embed_values->size_of() > 1) { + emb_val = new embed_values_enc_struct_t; + emb_val->embval_array = embed_values; + emb_val->embval_index = 1; + emb_val->embval_err = ed0; + emb_val->embval_err_val_idx = embed_values_val_idx; + emb_val->embval_err_descr_idx = embed_values_descr_idx; + } + + for ( i = begin; i < end; ++i ) { + + const Base_Type *uoe = 0; // "useOrder enum" + const Enum_Type *enm = 0; // the enum value selecting the field + + // "actual" index, may be perturbed by USE-ORDER. + // We use this value to index the appropriate record. + int ai = i; + + const Erroneous_values_t * ev = NULL; + const Erroneous_descriptor_t* ed = NULL; + if (exer && use_order) { + // If USE-ORDER is in effect, it introduces a level of indirection + // into the indexing of fields: "i" is used to select an element + // of the use_order member (an enum), whose value is used to select + // the field being encoded. + uoe = use_order->get_at(i - begin); + enm = static_cast(uoe); + ai = enm->as_int() + useorder_base; + + // Because it is not guaranteed that ai will increase monotonically, + // we can't use next_field_...(). + ev = p_err_descr->get_field_err_values(ai); + ed = p_err_descr->get_field_emb_descr (ai); + } + else { // not USE-ORDER, sequential access + ev = p_err_descr->next_field_err_values(ai, values_idx); + ed = p_err_descr->next_field_emb_descr (ai, edescr_idx); + } + ec_1.set_msg("%s': ", ordered->fld_name(ai)); // non-attr + + if (ai < p_err_descr->omit_before) continue; + + // omit_after value -1 becomes "very big". + if ((unsigned int)ai > (unsigned int)p_err_descr->omit_after) continue; + // We can't skip all fields with break, because the next ai may be lower + // than omit_after. + + sub_len += ordered->encode_field(ai, ev, ed, p_buf, + // Pass USE-NIL to the last field (except when USE-ORDER is also in effect, + // because the tag-stripping effect of USE-NIL has been achieved + // by encoding the sub-fields directly). + flavor | ((exer && !use_order && (i == field_cnt-1)) ? (p_td.xer_bits & USE_NIL) : 0), + indent + !omit_tag, emb_val); + + // Now the next embed-values string (NOT affected by USE-ORDER!) + if (exer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val && + emb_val->embval_index < embed_values->size_of()) { + const Erroneous_values_t * ev0_i = NULL; + const Erroneous_descriptor_t* ed0_i = NULL; + if (ed0) { + ev0_i = ed0->next_field_err_values(emb_val->embval_index, emb_val->embval_err_val_idx); + ed0_i = ed0->next_field_emb_descr (emb_val->embval_index, emb_val->embval_err_descr_idx); + } + embed_values->encode_element(emb_val->embval_index, ev0_i, ed0_i, + p_buf, flavor | EMBED_VALUES, indent + !omit_tag, 0); + ++emb_val->embval_index; + } + } //for + if (0 != emb_val) { + if (emb_val->embval_index < embed_values->size_of()) { + ec_1.set_msg("%s': ", fld_name(0)); + TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, + "Too many EMBED-VALUEs specified: %d (expected %d or less)", + embed_values->size_of(), emb_val->embval_index); } - embed_values->encode_element(i1, ev0_i, ed0_i, - p_buf, flavor | EMBED_VALUES, indent + !omit_tag); + delete emb_val; } - } //for + } // if (!early_to_bed) } // if (QNAME) @@ -4850,7 +4894,8 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, return (int)p_buf.get_len() - encoded_length; } -int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor) +int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, + unsigned int flavor, embed_values_dec_struct_t*) { bound_flag = TRUE; int exer = is_exer(flavor); @@ -4886,7 +4931,9 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, for (int k = 0; k < first_nonattr; ++k) { if (xer_descr(k)->xer_bits & ANY_ATTRIBUTES) { aa_index = k; - static_cast(get_at(aa_index))->set_size(0); + if (!get_at(aa_index)->is_optional()) { + static_cast(get_at(aa_index))->set_size(0); + } break; // there can be only one, 18.2.2 } } @@ -4951,7 +4998,7 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, // First, the (would-be) attributes (unaffected by USE-ORDER) for (i = 0; i < first_nonattr; i++) { ec_1.set_msg("%s': ", fld_name(i)); - get_at(i)->XER_decode(*xer_descr(i), reader, flavor); + get_at(i)->XER_decode(*xer_descr(i), reader, flavor, 0); } // next field } else if (own_tag || parent_tag) { // EXER and not UNTAGGED: do attributes @@ -4993,7 +5040,7 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, if (field_index != -1) { // There is a field. Let it decode the attribute. ec_1.set_msg("%s': ", fld_name(field_index)); - get_at(field_index)->XER_decode(*xer_descr(field_index), reader, flavor); + get_at(field_index)->XER_decode(*xer_descr(field_index), reader, flavor, 0); continue; } @@ -5031,7 +5078,16 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, TTCN_EncDec_ErrorContext ec_2("Attribute %d: ", num_aa); // We have a component with ANY-ATTRIBUTE. It must be a record of // UNIVERSAL_CHARSTRING. Add the attribute to it. - Record_Of_Type *aa = static_cast(get_at(aa_index)); + Record_Of_Type *aa = 0; + if (get_at(aa_index)->is_optional()) { + if (num_aa == 0) { + get_at(aa_index)->set_to_present(); + } + aa = static_cast(get_at(aa_index)->get_opt_value()); + } + else { + aa = static_cast(get_at(aa_index)); + } UNIVERSAL_CHARSTRING *new_elem = static_cast (aa->get_at(num_aa++)); @@ -5092,9 +5148,12 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, } // end if (own_tag) /* * * * * * * * Non-attributes (elements) * * * * * * * * * * * */ - Record_Of_Type* embed_values = 0; + embed_values_dec_struct_t* emb_val = 0; if (exer && (p_td.xer_bits & EMBED_VALUES)) { - embed_values = static_cast(get_at(0)); + emb_val = new embed_values_dec_struct_t; + emb_val->embval_array = static_cast(get_at(0)); + emb_val->embval_array->set_size(0); + emb_val->embval_index = 0; } if (exer && (p_td.xer_bits & USE_ORDER)) { @@ -5144,19 +5203,27 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, int *seen = new int[end-begin]; int num_seen = 0; int last_any_elem = begin - 1; + // The index of the latest embedded value can change outside of this function + // (if the field is a untagged record of), in this case the next value should + // be ignored, as it's already been handled by the record of + int last_embval_index = 0; for (i = begin; i < end; i++) { for (success = reader.Ok(); success == 1; success = reader.Read()) { type = reader.NodeType(); - if (embed_values) { - if (reader.NodeType()==XML_READER_TYPE_TEXT) { - UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value()); - embed_values->get_at(i-begin)->set_value(&emb_ustr); - } + if (0 != emb_val && reader.NodeType()==XML_READER_TYPE_TEXT) { + UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value()); + emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr); } // The non-attribute components must not be UNTAGGED if (type == XML_READER_TYPE_ELEMENT) break; // else if (type==XML_READER_TYPE_END_ELEMENT) panic? } + if (0 != emb_val) { + if (last_embval_index == emb_val->embval_index) { + ++emb_val->embval_index; + } + last_embval_index = emb_val->embval_index; + } if (success != 1) break; const char *name = (const char *)reader.LocalName(); boolean field_name_found = false; @@ -5182,7 +5249,7 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, static_cast(use_order->get_at(i - begin)) ->from_int(in_dex); Base_Type *b = jumbled->get_at(k); - b->XER_decode(*jumbled->xer_descr(k), reader, flavor); + b->XER_decode(*jumbled->xer_descr(k), reader, flavor, emb_val); field_name_found = true; break; } @@ -5208,17 +5275,20 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, static_cast(use_order->get_at(i - begin)) ->from_int(in_dex); Base_Type *b = jumbled->get_at(k); - b->XER_decode(*jumbled->xer_descr(k), reader, flavor); + b->XER_decode(*jumbled->xer_descr(k), reader, flavor, emb_val); last_any_elem = k; break; } } } } // next field - if (embed_values) { + if (0 != emb_val) { if (reader.NodeType()==XML_READER_TYPE_TEXT) { UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value()); - embed_values->get_at(i-begin)->set_value(&emb_ustr); + emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr); + } + if (last_embval_index == emb_val->embval_index) { + ++emb_val->embval_index; } } delete [] seen; @@ -5249,14 +5319,21 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, if (usenil_attribute) { reader.MoveToElement(); // value absent, nothing more to do } else { - int emb_idx = 0; + // The index of the latest embedded value can change outside of this function + // (if the field is a untagged record of), in this case the next value should + // be ignored, as it's already been handled by the record of + // Omitted fields can also reset this value + int last_embval_index = 0; for (; iget_at(emb_idx)->set_value(&emb_ustr); + emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr); } - emb_idx++; + if (last_embval_index == emb_val->embval_index) { + ++emb_val->embval_index; + } + last_embval_index = emb_val->embval_index; } ec_1.set_msg("%s': ", fld_name(i)); if (exer && i==field_cnt-1 && p_td.dfeValue && reader.IsEmptyElement()) { @@ -5281,38 +5358,35 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, if (i == field_cnt-1) new_flavor |= (p_td.xer_bits & USE_NIL); if (tag_closed) new_flavor |= PARENT_CLOSED; - get_at(i)->XER_decode(*xer_descr(i), reader, new_flavor); + get_at(i)->XER_decode(*xer_descr(i), reader, new_flavor, emb_val); } } + if (!get_at(i)->is_present()) { + // there was no new element, the last embedded value is for the next field + // (or the end of the record if this is the last field) + last_embval_index = -1; + } } // next field - if (embed_values) { + if (0 != emb_val) { if (reader.NodeType()==XML_READER_TYPE_TEXT) { UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value()); - embed_values->get_at(emb_idx)->set_value(&emb_ustr); + emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr); + } + if (last_embval_index == emb_val->embval_index) { + ++emb_val->embval_index; } } } } // if use-order - if (embed_values) { - // Set the embed_values member to the correct number of strings - int num_embedded = 0; // if usenil_attribute - if (!usenil_attribute) { - num_embedded = field_cnt - first_nonattr + 1; - const int num_opt = optional_count(); - const int * optionals = get_optional_indexes(); - for (int opt_idx = 0; opt_idx < num_opt; ++opt_idx) { - // skip optional attributes - if (optionals[opt_idx] < start_at + num_attributes) continue; - // reduce for each omitted member - if (!get_at(optionals[opt_idx])->is_present()) --num_embedded; - } - } - embed_values->set_size(num_embedded); + if (0 != emb_val) { static const UNIVERSAL_CHARSTRING emptystring(0, (const char*)NULL); - for (int j = 0; j < num_embedded; ++j) { - if (!embed_values->get_at(j)->is_bound()) embed_values->get_at(j)->set_value(&emptystring); + for (int j = 0; j < emb_val->embval_index; ++j) { + if (!emb_val->embval_array->get_at(j)->is_bound()) { + emb_val->embval_array->get_at(j)->set_value(&emptystring); + } } + delete emb_val; } // if embed-values } // if use-qname @@ -5588,7 +5662,7 @@ void Empty_Record_Type::encode(const TTCN_Typedescriptor_t& p_td, case TTCN_EncDec::CT_XER: { TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name); unsigned XER_coding=va_arg(pvar, unsigned); - XER_encode(*(p_td.xer),p_buf, XER_coding, 0); + XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0); p_buf.put_c('\n'); break;} case TTCN_EncDec::CT_JSON: { @@ -5661,7 +5735,7 @@ void Empty_Record_Type::decode(const TTCN_Typedescriptor_t& p_td, for (int success=reader.Read(); success==1; success=reader.Read()) { if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break; } - XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL); + XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, 0); size_t bytes = reader.ByteConsumed(); p_buf.set_pos(bytes); break;} @@ -5770,7 +5844,7 @@ int Empty_Record_Type::TEXT_decode(const TTCN_Typedescriptor_t& p_td, } int Empty_Record_Type::XER_encode(const XERdescriptor_t& p_td, - TTCN_Buffer& p_buf, unsigned int flavor, int indent) const + TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const { int encoded_length=(int)p_buf.get_len(); int indenting = !is_canonical(flavor); @@ -5784,7 +5858,7 @@ int Empty_Record_Type::XER_encode(const XERdescriptor_t& p_td, } int Empty_Record_Type::XER_decode(const XERdescriptor_t& p_td, - XmlReaderWrap& reader, unsigned int flavor) + XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*) { int exer = is_exer(flavor); bound_flag = true; diff --git a/doc/License_handling_in_TITAN.doc b/doc/License_handling_in_TITAN.doc index 0ec550ab700fcb3901fe78015f5733194c218637..979fb5e2389141ca75419858751efbd2f411395e 100644 GIT binary patch delta 30079 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�ug$6_XN@(excu1Z+hrH7Z>WE&U0T|aTX~t6 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 literal 147968 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 /dev/null"; +system($archive); #running it +if (-e $backupfile) { print ("archiving succeeded\n"); } +else { print ("archiving failed\n"); } +chdir ($home) or die "cannot change: $!\n"; +############################################################ +sub readFile +{ + my $makefile = "Makefile"; + open ( FILE, "<", $makefile ) or die ( "failed to open file: $home\/$makefile\n" ); + my @lines = ; + close FILE; + return @lines; +} +############################################################ +sub getPathToRootDir #get the relative path to OS workspace +{ + my @list = @{$_[0]}; + my $search = qr/^ROOT_DIR =/s; + my $offset = 0; + my $line; + for my $i ( 0 .. $#list ) + { + if ( $list[$i] =~ $search ) + { + $line = $list[$i]; + my $dot = '.'; + $offset = index($list[$i], $dot); + last; + } + } + if ($offset == 0) { die ( "no ROOT_DIR variable was found in the Makefile\n" ); } + my $path = substr $line, $offset; + return $path; +} +############################################################ +sub getTPDFileName # TPD filename what the Makefile is created from +{ + my @list = @{$_[0]}; + my $search = qr/^TPD =/s; + my $offset = 0; + my $line; + for my $i ( 0 .. $#list ) + { + if ( $list[$i] =~ $search ) + { + $line = $list[$i]; + my $assign = '='; + $offset = index($list[$i], $assign); + last; + } + } + if ($offset == 0) { die ( "no TPD variable was found in the Makefile\n" ); } + my $file = substr $line, $offset + 1; + $file =~ s/^\s+|\s+$//; # remove heading and traling whitespaces + return $file; +} +############################################################ +sub getArchiveDir # the name of the archive directory +{ + my @list = @{$_[0]}; + my $search = qr/^ARCHIVE_DIR =/s; + my $offset = 0; + my $line; + for my $i ( 0 .. $#list ) + { + if ( $list[$i] =~ $search ) + { + $line = $list[$i]; + my $assign = '='; + $offset = index($list[$i], $assign); + last; + } + } + if ($offset == 0) { die ( "no ARCHIVE_DIR variable was found in the Makefile\n" ); } + my $dir = substr $line, $offset + 1; + $dir =~ s/^\s+|\s+$//; # remove heading and trailing whitespaces + return $dir; +} +############################################################ +sub getExecutableName # the name of the target executable +{ + my @list = @{$_[0]}; + my $search = qr/^EXECUTABLE =/s; + my $offset = 0; + my $line; + for my $i ( 0 .. $#list ) + { + if ( $list[$i] =~ $search ) + { + $line = $list[$i]; + my $assign = '='; + $offset = index($list[$i], $assign); + last; + } + } + if ($offset == 0) { die ( "no EXCUTABLE variable was found in the Makefile\n" ); } + my $exec = substr $line, $offset + 1; + $exec =~ s/^\s+|\s+$//; # remove heading and trailing whitespaces + return $exec; +} +############################################################ +sub createBackupFileName +{ + my $backupFile = getExecutableName(\@list); + my $dot = '.'; + my $result = index($backupFile, $dot); + if ($result > -1) + { + $backupFile = substr $backupFile, 0, $result; + } + chomp ($backupFile); + my $date = `date '+%y%m%d-%H%M'`; + chomp ($date); + my $baseName = $backupFile . "-" . $date . ".tgz"; + chomp ($baseName); + return $baseName; +} +############################################################ \ No newline at end of file diff --git a/etc/xsd/TPD.xsd b/etc/xsd/TPD.xsd index a599afd..d56c8e1 100644 --- a/etc/xsd/TPD.xsd +++ b/etc/xsd/TPD.xsd @@ -367,13 +367,22 @@ XML Schema for JunitLogger plugin - - - - - - - + + + + + + + + + + + + + + + + @@ -453,7 +462,7 @@ XML Schema for JunitLogger plugin diff --git a/function_test/Semantic_Analyser/TTCN3_SA_13_TD.script b/function_test/Semantic_Analyser/TTCN3_SA_13_TD.script index c4c266a..3667858 100644 --- a/function_test/Semantic_Analyser/TTCN3_SA_13_TD.script +++ b/function_test/Semantic_Analyser/TTCN3_SA_13_TD.script @@ -1114,49 +1114,6 @@ template RoI t_i10 := permutation((all from t_RoI2),100); error: at or before token `permutation': syntax error, unexpected PermutationKeyword - -:exmp -*---------------------------------------------------------------------* -:h3. Component mapping: invalid ports -.*---------------------------------------------------------------------* -:xmp tab=0. - - - - - - -module test { - -type port P message { - inout charstring; -} with { extension "internal" } - -type component MTCType -{ - port P MyPCO_PT1; -} - -function akarmi () runs on MTCType { -map(mtc:MyPCO_PT, system:MyPCO_PT2); - -} - -testcase tc_akarmi () runs on MTCType { -map(mtc:MyPCO_PT, system:MyPCO_PT2); - -} - -} - - - -Component type `@test.MTCType' does not have port with name `MyPCO_PT' - - -Component type `@test.MTCType' does not have port with name `MyPCO_PT2' - - :exmp diff --git a/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script b/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script index d08f2a2..db2b40f 100644 --- a/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script +++ b/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script @@ -8609,4 +8609,35 @@ Temp.control :exmp. +*-----------------------------------------------------------* +:h3.Adhoc:: HT23335: Type Infinity is not a valid value for type `integer' which as subtype (-1..65535) +.*-----------------------------------------------------------* +:xmp tab=0. + + + + + +module Temp { +const integer limes_i := 65535; +const float limes_f2 := 65535.0; +const float limes_f1 := -1.0; +type record MyRecI { + integer inum (-1..limes_i) +}; +type record MyRecF { + float fnum (limes_f1..limes_f2) +}; + +template MyRecI t1 := { inum := (0..infinity) }; +template MyRecF t2 := { fnum := (-infinity..0.0) }; + +} + + +(?im)\Infinity is not a valid value for type\b + + +:exmp. + :etext. diff --git a/function_test/doc/TTCN3_Executor_TestReport.doc b/function_test/doc/TTCN3_Executor_TestReport.doc index bb3ede923e0998f9e99459a563527c74d8ab2baf..458f786c0c7725b5e73773bf4e43fdc44ffa0591 100644 GIT binary patch literal 1091072 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

d9X}$aRAMS^c^YM89cE$8g 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 VKpDUvtJXAHe*e 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 diff --git a/mctr2/cli/config_read.l b/mctr2/cli/config_read.l index 7d59c22..be8c193 100644 --- a/mctr2/cli/config_read.l +++ b/mctr2/cli/config_read.l @@ -121,7 +121,7 @@ IPV6 [0-9A-Fa-f:.]+(%[0-9A-Za-z]+)? %x SC_blockcomment SC_DEFINE SC_CSTRING SC_ORDERED_INCLUDE %s SC_MODULE_PARAMETERS SC_LOGGING SC_TESTPORT_PARAMETERS SC_EXECUTE SC_GROUPS -%s SC_COMPONENTS SC_EXTERNAL_COMMANDS SC_MAIN_CONTROLLER SC_INCLUDE +%s SC_COMPONENTS SC_EXTERNAL_COMMANDS SC_MAIN_CONTROLLER SC_INCLUDE SC_PROFILER %% int comment_caller = INITIAL; @@ -158,6 +158,13 @@ IPV6 [0-9A-Fa-f:.]+(%[0-9A-Za-z]+)? } } +<*>"["{WS}PROFILER{WS}"]" { + if (YY_START!=SC_blockcomment) { + BEGIN(SC_PROFILER); + RETURN(ProfilerKeyword); + } +} + <*>"["{WS}TESTPORT_PARAMETERS{WS}"]" { if (YY_START!=SC_blockcomment) { BEGIN(SC_TESTPORT_PARAMETERS); @@ -390,7 +397,7 @@ ifpresent RETURN(IfpresentKeyword); infinity RETURN(InfinityKeyword); } - + { true | false RETURN(BooleanValue); @@ -551,6 +558,16 @@ WARNING_UNQUALIFIED RETURN(LoggingBit); [Dd]elete RETURN(Delete); } + +{ +[Dd]isable[Pp]rofiler return DisableProfilerKeyword; +[Dd]isable[Cc]overage return DisableCoverageKeyword; +[Dd]ata[Bb]ase[Ff]ile return DatabaseFileKeyword; +[Aa]ggregate[Dd]ata return AggregateDataKeyword; +[Ss]tatistics[Ff]ile return StatisticsFileKeyword; +[Dd]isable[Ss]tatistics return DisableStatisticsKeyword; +} + control RETURN(ControlKeyword); diff --git a/mctr2/cli/config_read.y b/mctr2/cli/config_read.y index f70b160..496d4f3 100644 --- a/mctr2/cli/config_read.y +++ b/mctr2/cli/config_read.y @@ -69,12 +69,14 @@ static void yyprint(FILE *file, int type, const YYSTYPE& value); char *str_val; BIGNUM *int_val; double float_val; + boolean bool_val; cf_timestamp_format ts_val; execute_list_item execute_item_val; } %token ModuleParametersKeyword %token LoggingKeyword +%token ProfilerKeyword %token TestportParametersKeyword %token ExecuteKeyword %token ExternalCommandsKeyword @@ -163,6 +165,13 @@ static void yyprint(FILE *file, int type, const YYSTYPE& value); %token Re_try /* Retry clashes with an enum in Qt */ %token Delete +%token DisableProfilerKeyword "DisableProfiler" +%token DisableCoverageKeyword "DisableCoverage" +%token DatabaseFileKeyword "DatabaseFile" +%token AggregateDataKeyword "AggregateData" +%token StatisticsFileKeyword "StatisticsFile" +%token DisableStatisticsKeyword "DisableStatistics" + %type IntegerValue %type FloatValue KillTimerValue %type HostName StringValue LogFileName @@ -219,6 +228,7 @@ ConfigFile: Section: ModuleParametersSection | LoggingSection + | ProfilerSection | TestportParametersSection | ExecuteSection | ExternalCommandsSection @@ -678,6 +688,50 @@ MatchVerbosityValue: | Detailed ; +/*********************** [PROFILER] ********************************/ + +ProfilerSection: + ProfilerKeyword ProfilerSettings +; + +ProfilerSettings: + /* empty */ +| ProfilerSettings ProfilerSetting optSemiColon +; + +ProfilerSetting: + DisableProfilerSetting +| DisableCoverageSetting +| DatabaseFileSetting +| AggregateDataSetting +| StatisticsFileSetting +| DisableStatisticsSetting +; + +DisableProfilerSetting: + DisableProfilerKeyword AssignmentChar BooleanValue +; + +DisableCoverageSetting: + DisableCoverageKeyword AssignmentChar BooleanValue +; + +DatabaseFileSetting: + DatabaseFileKeyword AssignmentChar StringValue { Free($3); } +; + +AggregateDataSetting: + AggregateDataKeyword AssignmentChar BooleanValue +; + +StatisticsFileSetting: + StatisticsFileKeyword AssignmentChar StringValue { Free($3); } +; + +DisableStatisticsSetting: + DisableStatisticsKeyword AssignmentChar BooleanValue +; + /******************* [TESTPORT_PARAMETERS] section *******************/ TestportParametersSection: diff --git a/regression_test/XML/EXER-whitepaper/EmbedValues.ttcnpp b/regression_test/XML/EXER-whitepaper/EmbedValues.ttcnpp index 9ce328c..fc5cb93 100644 --- a/regression_test/XML/EXER-whitepaper/EmbedValues.ttcnpp +++ b/regression_test/XML/EXER-whitepaper/EmbedValues.ttcnpp @@ -154,6 +154,71 @@ testcase decode_emb_any() runs on EMB CHECK_DECODE(exer_dec_emb_any, str_emb_any, EmbedAnyElem, c_emb_any); } +// EMBED-VALUES with untagged array +// the values are also embedded between the array elements, not just the fields of the record +type record Inner { + integer num, + charstring str +} + +type record length (1..infinity) of Inner RoInner; + +type record Outer { + record of universal charstring embed_values, + integer attr, + octetstring bytes, + RoInner stuff +} with { + variant "embedValues"; + variant(attr) "attribute"; + variant(bytes) "name as 'Bytes'"; + variant(stuff) "untagged"; +} + +DECLARE_EXER_ENCODERS(Outer, emb_outer); + +const Outer c_emb_array := { + embed_values := { "one", "two", "three", "four", "five", "six" }, + attr := 48, + bytes := 'DEADBEEF'O, + stuff := { { 3, "abc" }, { 4, "def" }, { -6, "red" }, { 118, "blue" } } +} + +const Outer c_emb_array_w_holes := { + embed_values := { "one", "", "three", "", "five" }, + attr := 48, + bytes := 'DEADBEEF'O, + stuff := { { 3, "abc" }, { 4, "def" }, { -6, "red" }, { 118, "blue" } } +} + +const universal charstring str_emb_array := +"one" & +"DEADBEEFtwo" & +"3abcthree" & +"4deffour" & +"-6redfive" & +"118bluesix\n"; + +const universal charstring str_emb_array_w_holes := +"one" & +"DEADBEEF" & +"3abcthree" & +"4def" & +"-6redfive" & +"118blue\n"; + +testcase encode_emb_array() runs on EMB +{ + CHECK_METHOD(exer_enc_emb_outer, c_emb_array, str_emb_array); + CHECK_METHOD(exer_enc_emb_outer, c_emb_array_w_holes, str_emb_array_w_holes); +} + +testcase decode_emb_array() runs on EMB +{ + CHECK_DECODE(exer_dec_emb_outer, str_emb_array, Outer, c_emb_array); + CHECK_DECODE(exer_dec_emb_outer, str_emb_array_w_holes, Outer, c_emb_array_w_holes); +} + control { execute(encode_emb()); execute(decode_emb()); @@ -161,6 +226,8 @@ control { execute(decode_emb_all()); execute(encode_emb_any()); execute(decode_emb_any()); + //execute(encode_emb_array()); - this functionality was temporarily removed in RT1 + //execute(decode_emb_array()); } } diff --git a/regression_test/XML/Makefile b/regression_test/XML/Makefile index 340501f..6d9a50d 100644 --- a/regression_test/XML/Makefile +++ b/regression_test/XML/Makefile @@ -19,7 +19,7 @@ endif XDIRS := $(wildcard $(SHADOWED)) xsdConverter \ HM60295 HN15589 HQ30408 HR49727 $(RT2_ONLY) \ -XmlWorkflow +XmlWorkflow tpdValidTest # List of fake targets: .PHONY: all dep clean run $(XDIRS) $(addsuffix /, $(XDIRS)) profile diff --git a/regression_test/XML/tpdValidTest/Makefile b/regression_test/XML/tpdValidTest/Makefile new file mode 100644 index 0000000..843b772 --- /dev/null +++ b/regression_test/XML/tpdValidTest/Makefile @@ -0,0 +1,12 @@ +############################################################################### +# Copyright (c) 2000-2014 Ericsson Telecom AB +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################### + +dep clean distclean: + +all run: + ./tpdValidTest.sh >&2 diff --git a/regression_test/XML/tpdValidTest/tpdValidTest.sh b/regression_test/XML/tpdValidTest/tpdValidTest.sh new file mode 100755 index 0000000..e587670 --- /dev/null +++ b/regression_test/XML/tpdValidTest/tpdValidTest.sh @@ -0,0 +1,22 @@ +#!/bin/bash +############################################################################### +# Copyright (c) 2000-2014 Ericsson Telecom AB +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################### + +TPD_DIR="$WORKSPACE/titan_eclipse/Semantic_Analizer_Tests/tpdTest/" +XSD_DIR="$TTCN3_DIR/etc/xsd/" +XSD="TPD.xsd" + +find $TPD_DIR -type f -name *.tpd | xargs -I {} xmllint --noout --schema $XSD_DIR/$XSD {} + +if [ $? -ne 0 ]; then + echo "Not every .tpd is valid! Overall verdict: fail" + exit 1 +else + echo "Every .tpd is valid! Overall verdict: pass" + exit 0 +fi diff --git a/regression_test/compileonly/HT48786/Makefile b/regression_test/compileonly/HT48786/Makefile new file mode 100644 index 0000000..11d4230 --- /dev/null +++ b/regression_test/compileonly/HT48786/Makefile @@ -0,0 +1,45 @@ +############################################################################### +# Copyright (c) 2000-2015 Ericsson Telecom AB +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################### +TOPDIR := ../.. +include $(TOPDIR)/Makefile.regression + +.PHONY: all clean dep + +TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) + +EXTRA_COMPILER_FLAGS = -p -V 63 + +TTCN3_MODULES = Test1.ttcn Test2.ttcn + +GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) +GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh) +ifdef CODE_SPLIT +GENERATED_SOURCES := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), .cc _seq.cc _set.cc _seqof.cc _setof.cc _union.cc)) +endif + +OBJECTS = $(GENERATED_SOURCES:.cc=.o) + +TARGET = HT48786$(EXESUFFIX) + +all: $(TARGET) + +$(TARGET): $(GENERATED_SOURCES) $(USER_SOURCES) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ -L$(TTCN3_DIR)/lib -l$(TTCN3_LIB) \ + -L$(OPENSSL_DIR)/lib -lcrypto $($(PLATFORM)_LIBS) + +# an extra compilation is tested (with only parsing and maximum verbosity level) +$(GENERATED_SOURCES) $(GENERATED_HEADERS): $(TTCN3_MODULES) + $(TTCN3_COMPILER) $(EXTRA_COMPILER_FLAGS) $(COMPILER_FLAGS) $^ + $(TTCN3_COMPILER) $(COMPILER_FLAGS) $^ + +clean distclean: + $(RM) $(TARGET) $(OBJECTS) $(GENERATED_HEADERS) \ + $(GENERATED_SOURCES) compile *.log + +dep: $(GENERATED_SOURCES) + makedepend $(CPPFLAGS) $(GENERATED_SOURCES) diff --git a/regression_test/compileonly/HT48786/Test1.ttcn b/regression_test/compileonly/HT48786/Test1.ttcn new file mode 100644 index 0000000..28b6917 --- /dev/null +++ b/regression_test/compileonly/HT48786/Test1.ttcn @@ -0,0 +1,36 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2015 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +module Test1 +{ + +type component EMPTY_CT +{ +} + +type record Union +{ + record of integer record_of_integer, + charstring string +}; + +testcase TC_1() runs on EMPTY_CT +{ + var boolean b := false; + var Union u1 := { + record_of_integer := { + str2int("2"), + str2int("3") + } + }; +} + +control { + execute(TC_1()); +} + +} diff --git a/regression_test/compileonly/HT48786/Test2.ttcn b/regression_test/compileonly/HT48786/Test2.ttcn new file mode 100644 index 0000000..ae4a64a --- /dev/null +++ b/regression_test/compileonly/HT48786/Test2.ttcn @@ -0,0 +1,21 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2015 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// + +module Test2 { + +type record of integer Record1; +type record of Record1 Record2; + +function f1() { + var Record2 r1, r2; + r1 := {{1, 2}}; + r2 := valueof(r1); + r2 := valueof({{1, 2}}); +} + +} diff --git a/regression_test/compileonly/Makefile b/regression_test/compileonly/Makefile index facd1da..f5f02fe 100644 --- a/regression_test/compileonly/Makefile +++ b/regression_test/compileonly/Makefile @@ -14,7 +14,7 @@ CODIRS := dynamicTemplate styleGuide topLevelPdu \ centralstorage mfgen-tpd \ openType optionalAssignCompare portConstructor \ isbound namedActualParameters assignmentNotation \ - attribQualif + attribQualif HT48786 all dep clean distclean: for dir in $(CODIRS); do $(MAKE) -C $$dir $@ || exit; done diff --git a/regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/Makefile b/regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/Makefile index 57fb440..e981527 100644 --- a/regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/Makefile +++ b/regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/Makefile @@ -26,8 +26,7 @@ BuildHelloTpd: -t ../HelloTpd.tpd -b notexisting 2>&1 | tee ../output CheckHelloTpd: BuildHelloTpd - if [ `grep -c "error: The active build configuration named 'notexisting' does not exist" ./HelloTpd/output` -ne 1 ] \ - || [ `grep -c "error: Failed to process ../HelloTpd.tpd" ./HelloTpd/output` -ne 1 ]; \ + if [ `grep -c "error: The active build configuration named 'notexisting' does not exist" ./HelloTpd/output` -ne 1 ]; \ then exit 1; fi clean: diff --git a/regression_test/compileonly/mfgen-tpd/library/Makefile b/regression_test/compileonly/mfgen-tpd/library/Makefile index 051955a..a4a5665 100644 --- a/regression_test/compileonly/mfgen-tpd/library/Makefile +++ b/regression_test/compileonly/mfgen-tpd/library/Makefile @@ -40,7 +40,7 @@ BuildLibraryL: a.ttcn -L a.ttcn && ${MAKEPROG} CheckLibraryL: BuildLibraryL - if [ ! -f ./bin/a.a ]; then exit 1; fi + if [ ! -f ./bin/liba.a ]; then exit 1; fi if [ -f ./bin/a ]; then exit 1; fi # ttcn3_makefilegen -L; make executable @@ -51,7 +51,7 @@ BuildLibrary3L: a.ttcn -L a.ttcn && ${MAKEPROG} executable CheckLibrary3L: BuildLibrary3L - if [ -f ./bin3/a.a ]; then exit 1; fi + if [ -f ./bin3/liba.a ]; then exit 1; fi if [ ! -f ./bin3/a ]; then exit 1; fi # ttcn3_makefilegen -L; make library @@ -62,7 +62,7 @@ BuildLibrary2L: a.ttcn -L a.ttcn && ${MAKEPROG} library CheckLibrary2L: BuildLibrary2L - if [ ! -f ./bin2/a.a ]; then exit 1; fi + if [ ! -f ./bin2/liba.a ]; then exit 1; fi if [ -f ./bin2/a ]; then exit 1; fi # ttcn3_makefilegen -L; make run @@ -73,7 +73,7 @@ BuildLibrary4L: a.ttcn -L a.ttcn && ${MAKEPROG} all CheckLibrary4L: BuildLibrary4L - if [ ! -f ./bin4/a.a ]; then exit 1; fi + if [ ! -f ./bin4/liba.a ]; then exit 1; fi if [ -f ./bin4/a ]; then exit 1; fi #### Without -L #### @@ -86,7 +86,7 @@ BuildLibrary: a.ttcn a.ttcn && ${MAKEPROG} CheckLibrary: BuildLibrary - if [ -f ./bin/a.a ]; then exit 1; fi + if [ -f ./bin/liba.a ]; then exit 1; fi if [ ! -f ./bin/a ]; then exit 1; fi # ttcn3_makefilegen; make executable @@ -97,7 +97,7 @@ BuildLibrary3: a.ttcn a.ttcn && ${MAKEPROG} executable CheckLibrary3: BuildLibrary3 - if [ -f ./bin3/a.a ]; then exit 1; fi + if [ -f ./bin3/liba.a ]; then exit 1; fi if [ ! -f ./bin3/a ]; then exit 1; fi # ttcn3_makefilegen; make library @@ -108,7 +108,7 @@ BuildLibrary2: a.ttcn a.ttcn && ${MAKEPROG} library CheckLibrary2: BuildLibrary2 - if [ ! -f ./bin2/a.a ]; then exit 1; fi + if [ ! -f ./bin2/liba.a ]; then exit 1; fi if [ -f ./bin2/a ]; then exit 1; fi # ttcn3_makefilegen; make all @@ -119,7 +119,7 @@ BuildLibrary4: a.ttcn a.ttcn && ${MAKEPROG} all CheckLibrary4: BuildLibrary4 - if [ -f ./bin4/a.a ]; then exit 1; fi + if [ -f ./bin4/liba.a ]; then exit 1; fi if [ ! -f ./bin4/a ]; then exit 1; fi ############################### @@ -136,7 +136,7 @@ Build_dynamic: a.ttcn a.ttcn && ${MAKEPROG} Check_dynamic: Build_dynamic - if [ ! -f ./bin_dynamic/a_lib.so ]; then exit 1; fi + if [ ! -f ./bin_dynamic/liba.so ]; then exit 1; fi if [ -f ./bin_dynamic/a ]; then exit 1; fi # ttcn3_makefilegen -L -l; make library @@ -147,7 +147,7 @@ Build_dynamic2: a.ttcn a.ttcn && ${MAKEPROG} library Check_dynamic2: Build_dynamic2 - if [ ! -f ./bin_dynamic2/a_lib.so ]; then exit 1; fi + if [ ! -f ./bin_dynamic2/liba.so ]; then exit 1; fi if [ -f ./bin_dynamic2/a ]; then exit 1; fi # ttcn3_makefilegen -L -l; make executable @@ -158,7 +158,7 @@ Build_dynamic3: a.ttcn a.ttcn && ${MAKEPROG} executable Check_dynamic3: Build_dynamic3 - if [ ! -f ./bin_dynamic3/a_lib.so ]; then exit 1; fi + if [ ! -f ./bin_dynamic3/liba.so ]; then exit 1; fi if [ -f ./bin_dynamic3/a.so ]; then exit 1; fi if [ ! -f ./bin_dynamic3/a ]; then exit 1; fi @@ -172,7 +172,7 @@ Build_dynamic4: a.ttcn a.ttcn && ${MAKEPROG} Check_dynamic4: Build_dynamic4 - if [ -f ./bin_dynamic4/a_lib.so ]; then exit 1; fi + if [ -f ./bin_dynamic4/liba.so ]; then exit 1; fi if [ ! -f ./bin_dynamic4/a ]; then exit 1; fi # ttcn3_makefilegen -l; make library @@ -183,7 +183,7 @@ Build_dynamic5: a.ttcn a.ttcn && ${MAKEPROG} library Check_dynamic5: Build_dynamic5 - if [ ! -f ./bin_dynamic5/a_lib.so ]; then exit 1; fi + if [ ! -f ./bin_dynamic5/liba.so ]; then exit 1; fi if [ -f ./bin_dynamic5/a ]; then exit 1; fi # ttcn3_makefilegen -l; make executable @@ -194,7 +194,7 @@ Build_dynamic6: a.ttcn a.ttcn && ${MAKEPROG} executable Check_dynamic6: Build_dynamic6 - if [ -f ./bin_dynamic6/a_lib.so ]; then exit 1; fi + if [ -f ./bin_dynamic6/liba.so ]; then exit 1; fi if [ ! -f ./bin_dynamic6/a ]; then exit 1; fi @@ -208,7 +208,7 @@ Build_dynamic_central: b.ttcn Central b.ttcn ../central_storage/central.ttcn && ${MAKEPROG} Check_dynamic_central: Build_dynamic_central - if [ ! -f ./bin_central/b_lib.so ]; then exit 1; fi + if [ ! -f ./bin_central/libb.so ]; then exit 1; fi if [ -f ./bin_central/b ]; then exit 1; fi # ttcn3_makefilegen -c -l; make @@ -236,7 +236,7 @@ BuildHelloTpd: CheckHelloTpd: BuildHelloTpd if [ -f HelloTpd/bin/HelloTpd_test.exe ]; then exit 1; fi - if [ ! -f HelloTpd/bin/HelloTpd_test.a ]; then exit 1; fi + if [ ! -f HelloTpd/bin/libHelloTpd_test.a ]; then exit 1; fi # the default target is executable in the tpd file # check if the command line option overrides the one defined in the tpd @@ -249,7 +249,7 @@ BuildHelloTpd2: CheckHelloTpd2: BuildHelloTpd2 if [ -f HelloTpd2/bin/HelloTpd_test.exe ]; then exit 1; fi - if [ ! -f HelloTpd2/bin/HelloTpd_test.a ]; then exit 1; fi + if [ ! -f HelloTpd2/bin/libHelloTpd_test.a ]; then exit 1; fi clean: -rm -rf bin* diff --git a/regression_test/json/Functions.ttcn b/regression_test/json/Functions.ttcn index 18224c8..6064b62 100755 --- a/regression_test/json/Functions.ttcn +++ b/regression_test/json/Functions.ttcn @@ -102,6 +102,9 @@ external function f_enc_cba(in CBA u) return octetstring external function f_enc_stuff(in Stuff x) return octetstring with { extension "prototype(convert) encode(JSON)" } +external function f_enc_hpt(in HasPardType x) return octetstring + with { extension "prototype(convert) encode(JSON)" } + // for ASN.1 types external function f_enc_seqofint(in SeqOfInt x) return octetstring with { extension "prototype(convert) encode(JSON)" } @@ -117,6 +120,12 @@ external function f_enc_strings(in ManyStrings x) return octetstring external function f_enc_complex(in ComplexSet x) return octetstring with { extension "prototype(convert) encode(JSON)" } + +external function f_enc_obj(in Object x) return octetstring + with { extension "prototype(convert) encode(JSON)" } + +external function f_enc_null(in HasNull x) return octetstring + with { extension "prototype(convert) encode(JSON)" } //=================== Decoders ===================================== @@ -199,6 +208,9 @@ external function f_dec_stuff(in octetstring x) return Stuff external function f_dec_def(in octetstring x) return RecDef with { extension "prototype(convert) decode(JSON)" } +external function f_dec_hpt(in octetstring x) return HasPardType + with { extension "prototype(convert) decode(JSON)" } + // for ASN.1 types external function f_dec_seqofint(in octetstring x) return SeqOfInt with { extension "prototype(convert) decode(JSON)" } @@ -214,6 +226,12 @@ external function f_dec_strings(in octetstring x) return ManyStrings external function f_dec_complex(in octetstring x) return ComplexSet with { extension "prototype(convert) decode(JSON)" } + +external function f_dec_obj(in octetstring x) return Object + with { extension "prototype(convert) decode(JSON)" } + +external function f_dec_null(in octetstring x) return HasNull + with { extension "prototype(convert) decode(JSON)" } //============== Internal Functions ==================== diff --git a/regression_test/json/JsonData.asn b/regression_test/json/JsonData.asn index a100699..962186e 100644 --- a/regression_test/json/JsonData.asn +++ b/regression_test/json/JsonData.asn @@ -19,8 +19,10 @@ IMPORTS ; -- Type definitions -- ---------------------- +-- Sequence of SeqOfInt ::= SEQUENCE OF INTEGER +-- Sequence SeqProduct ::= SEQUENCE { name UniversalString, price REAL, @@ -28,12 +30,14 @@ SeqProduct ::= SEQUENCE { available BOOLEAN } +-- Choice Number ::= CHOICE { decimal INTEGER, binary BIT STRING, hexadecimal OCTET STRING } +-- Choice containing all string types AnyString ::= CHOICE { generalstr GeneralString, numericstr NumericString, @@ -48,14 +52,93 @@ AnyString ::= CHOICE { visiblestr VisibleString } +-- Sequence of strings ManyStrings ::= SEQUENCE OF AnyString +-- Set containing all of the above ComplexSet ::= SET { product SeqProduct, numbers SET OF Number, strings ManyStrings } +Priority ::= ENUMERATED { low, normal, medium, high, urgent } + +Conditionality ::= ENUMERATED { optional, conditional, mandatory } + +ProtocolElem-ID ::= INTEGER (0..65535) + +-- IOC +PROTOCOL-ELEMS ::= CLASS +{ + &id ProtocolElem-ID UNIQUE, + &priority Priority, + &Value, + &conditionality Conditionality +} +WITH SYNTAX +{ + ID &id + PRIORITY &priority + TYPE &Value + CONDITIONALITY &conditionality +} + +-- parameterized type +ProtocolElem-Field {PROTOCOL-ELEMS : ElemsSetParam} ::= SEQUENCE +{ + id PROTOCOL-ELEMS.&id ({ElemsSetParam}), + priority PROTOCOL-ELEMS.&priority ({ElemsSetParam}{@id}), + val PROTOCOL-ELEMS.&Value ({ElemsSetParam}{@id}) +} + + +-- Information objects +ies-Set-Element-1 PROTOCOL-ELEMS ::= +{ + ID 0 + PRIORITY low + TYPE INTEGER + CONDITIONALITY mandatory +} + +ies-Set-Element-2 PROTOCOL-ELEMS ::= +{ + ID 1 + PRIORITY high + TYPE IA5String + CONDITIONALITY optional +} +-- Information Object Set +Elems-Set PROTOCOL-ELEMS ::= { ies-Set-Element-1 | ies-Set-Element-2 } + + +-- instantiation +ProtocolElem-Field1 ::= ProtocolElem-Field {{Elems-Set}} + +ProtocolElem-Field2 ::= ProtocolElem-Field {{ies-Set-Element-2 }} + +-- Choice containing NULL +Price ::= CHOICE +{ + value REAL, + invaluable NULL +} + +-- Sequence containing an object identifier and an ANY type +Object ::= SEQUENCE +{ + id OBJECT IDENTIFIER, + data ANY +} + +-- Sequence containing an optional NULL field +HasNull ::= SEQUENCE +{ + theNull NULL OPTIONAL +} + + -- Values and their encoding -- ------------------------------- @@ -114,4 +197,19 @@ c-set-val ComplexSet ::= { c-set-val-str VisibleString ::= "{""product"":{""name"":""Headset"",""price"":28.500000,""available"":false},""numbers"":[{""hexadecimal"":""16678D""},{""decimal"":12}],""strings"":[{""printablestr"":""first""},{""numericstr"":""2""}]}" +-- Object +c-obj Object ::= { + id { joint-iso-itu-t remote-operations(4) informationObjects(5) version1(0) }, + data 'DEADBEEF'H +} + +c-obj-str VisibleString ::= "{""id"":""2.4.5.0"",""data"":""DEADBEEF""}" + +-- HasNull +c-null HasNull ::= { theNull NULL } +c-not-null HasNull ::= {} + +c-null-str VisibleString ::= "{""theNull"":null}" +c-not-null-str VisibleString ::= "{}" + END diff --git a/regression_test/json/Testcases.ttcn b/regression_test/json/Testcases.ttcn index 81cb2fd..e452ecc 100755 --- a/regression_test/json/Testcases.ttcn +++ b/regression_test/json/Testcases.ttcn @@ -517,6 +517,38 @@ testcase tc_asn_complex() runs on MTC { f_bool2verdict(match(f_dec_complex(os), c_set_val)); } +// ====== Special ASN.1 types ====== +// record containing an open type and a possible NULL value +testcase tc_asn_open_type_and_null() runs on MTC { + var HasPardType x := { + pard := { + id := 0, + priority := low, + val := { iNTEGER := 19 } + }, + buul := true, + price := { invaluable := NULL } + }; + var octetstring os := char2oct("{\"pard\":{\"id\":0,\"priority\":\"low\",\"val\":{\"iNTEGER\":19}},\"buul\":true,\"price\":{\"invaluable\":null}}"); + f_check_encoding(encoded := f_enc_hpt(x), expected := os); + f_bool2verdict(match(f_dec_hpt(os), x)); +} + +// SEQUENCE containing an object identifier and an ANY type +testcase tc_asn_objid_and_any() runs on MTC { + var octetstring os := char2oct(c_obj_str); + f_check_encoding(encoded:= f_enc_obj(c_obj), expected := os); + f_bool2verdict(match(f_dec_obj(os), c_obj)); +} + +testcase tc_asn_optional_null() runs on MTC { + var octetstring os := char2oct(c_null_str); + f_check_encoding(encoded:= f_enc_null(c_null), expected := os); + f_bool2verdict(match(f_dec_null(os), c_null)); + os := char2oct(c_not_null_str); + f_check_encoding(encoded:= f_enc_null(c_not_null), expected := os); + f_bool2verdict(match(f_dec_null(os), c_not_null)); +} //========================================================================= // Control @@ -572,6 +604,10 @@ control { execute(tc_asn_choice()); execute(tc_asn_strings()); execute(tc_asn_complex()); + + execute(tc_asn_open_type_and_null()); + execute(tc_asn_objid_and_any()); + execute(tc_asn_optional_null()); } diff --git a/regression_test/json/Types.ttcn b/regression_test/json/Types.ttcn index f1f372c..21eef282 100755 --- a/regression_test/json/Types.ttcn +++ b/regression_test/json/Types.ttcn @@ -7,6 +7,8 @@ ******************************************************************************/ module Types { +import from JsonData all; + const integer c_imported_i :=11; type component MTC {} @@ -156,6 +158,11 @@ type record RecDef { variant(b) "JSON:default(false)"; } +type record HasPardType { + ProtocolElem_Field1 pard, + boolean buul, + Price price +} } with { encode "JSON"; diff --git a/regression_test/recofOper/Makefile b/regression_test/recofOper/Makefile index 654a1d7..e4b9c7a 100644 --- a/regression_test/recofOper/Makefile +++ b/regression_test/recofOper/Makefile @@ -13,8 +13,15 @@ include $(TOPDIR)/Makefile.regression TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) -TTCN3_MODULES = TrecofOper.ttcn TrecofParamRef.ttcn +TTCN3_MODULES = TrecofOper.ttcn +ifdef RT2 +TTCN3_MODULES += TrecofParamRef.ttcn ASN1_MODULES = BerType.asn +CFG_FILE = config_rt2.cfg +else +ASN1_MODULES = +CFG_FILE = config.cfg +endif GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) $(ASN1_MODULES:.asn=.cc) GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh) @@ -41,7 +48,7 @@ clean distclean: dep: $(GENERATED_SOURCES) makedepend $(CPPFLAGS) $(GENERATED_SOURCES) -run: $(TARGET) config.cfg +run: $(TARGET) $(CFG_FILE) ./$^ .NOTPARALLEL: diff --git a/regression_test/recofOper/config.cfg b/regression_test/recofOper/config.cfg index a3b9428..eb0d2a5 100644 --- a/regression_test/recofOper/config.cfg +++ b/regression_test/recofOper/config.cfg @@ -12,4 +12,3 @@ FileMask := LOG_ALL ConsoleMask := TTCN_WARNING | TTCN_ERROR | TTCN_TESTCASE | TTCN_STATISTICS [EXECUTE] TrecofOper -TrecofParamRef diff --git a/regression_test/recofOper/config_rt2.cfg b/regression_test/recofOper/config_rt2.cfg new file mode 100644 index 0000000..8cd9abc --- /dev/null +++ b/regression_test/recofOper/config_rt2.cfg @@ -0,0 +1,15 @@ +############################################################################### +# Copyright (c) 2000-2015 Ericsson Telecom AB +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################### +[MODULE_PARAMETERS] +[LOGGING] +Logfile := "recofOper.log" +FileMask := LOG_ALL +ConsoleMask := TTCN_WARNING | TTCN_ERROR | TTCN_TESTCASE | TTCN_STATISTICS +[EXECUTE] +TrecofOper +TrecofParamRef diff --git a/regression_test/ttcn2json/CompareSchemas.ttcn b/regression_test/ttcn2json/CompareSchemas.ttcn new file mode 100644 index 0000000..426111b --- /dev/null +++ b/regression_test/ttcn2json/CompareSchemas.ttcn @@ -0,0 +1,117 @@ +/****************************************************************************** + * Copyright (c) 2000-2015 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + ******************************************************************************/ + +// This module compares two JSON schemas generated by the TITAN compiler +module CompareSchemas { + +////////////////////////////////////// +// JSON schema container data types // +////////////////////////////////////// + +// top level object +type record JsonSchema { + DefSchemas defs, + RefSchemas refs +} + +// definitions section: +type set of DefSchema DefSchemas; + +type record DefSchema { + charstring moduleName, + charstring typeName, + TypeSchema schema +} + +type set of TypeSchemaElement TypeSchema; + +type record TypeSchemaElement { + ElemKey key, + ElemValue val +} + +type enumerated ElemKey { + Ref, Type, SubType, Pattern, OriginalName, UnusedAlias, MinItems, MaxItems, // strVal + AdditionalProperties, OmitAsNull, // boolVal + Default, // strVal or boolVal + Enum, NumericValues, Required, FieldOrder, // strArrayVal + Items, // typeVal + AnyOf, // typeArrayVal + Properties // fieldSetVal +} + +type union ElemValue { + charstring strVal, + boolean boolVal, + record of charstring strArrayVal, + TypeSchema typeVal, + record of TypeSchema typeArrayVal, + set of FieldValue fieldSetVal +} + +type record FieldValue { + charstring fieldName, + TypeSchema schema +} + +// references/functions section: +type set of RefSchema RefSchemas; + +type record RefSchema { + charstring ref, + EncDecData enc optional, + EncDecData dec optional +} + +type record EncDecData { + PrototypeData prototype, + ErrorBehaviorData eb optional, + charstring printing optional +} + +type record of charstring PrototypeData; + +type record of ErrorBehaviorElem ErrorBehaviorData; + +type record ErrorBehaviorElem { + charstring errorType, + charstring errorBehavior +} + +////////////////////////////////// +// Import and compare functions // +////////////////////////////////// + +// Imports a JSON schema from the given file and stores it in the specified container. +// Throws a Dynamic Testcase Error if the file cannot be read or does not have the correct format. +// The resulting JsonSchema should not have any unbound fields. +external function f_ext_import_schema(in charstring file, out JsonSchema schema); + +// Compares the two schemas found in the files specified by the parameters. +// Returns true if they are equal. +function f_compare_schemas(in charstring schema_file1, in charstring schema_file2) return boolean +{ + // read the schemas from the files + var JsonSchema schema1; + f_ext_import_schema(schema_file1, schema1); + var JsonSchema schema2; + f_ext_import_schema(schema_file2, schema2); + + // log both schemas (good luck digging through these...) + //log("Generated (", schema_file1, "): ", schema1); + //log("Expected (", schema_file2, "): ", schema2); + + // set the verdict depending on their equality + if (match(schema1, schema2)) { + return true; + } + log(match(schema1, schema2)); + return false; +} + +} diff --git a/regression_test/ttcn2json/General_Types_e.json b/regression_test/ttcn2json/General_Types_e.json index fa9bfec..3fc889a 100644 --- a/regression_test/ttcn2json/General_Types_e.json +++ b/regression_test/ttcn2json/General_Types_e.json @@ -3,178 +3,222 @@ "General_Types" : { "BIT1" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT10" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT11" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT12" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT12n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT14" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT14_24n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT14n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT15" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT15n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT15np" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT16" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT16_BO_LAST" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT16n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT1n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT1np" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT2" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT24" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT2n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT2np" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT3" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT31" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT32_BO_LAST" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT3n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT3np" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT4" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT4n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT4np" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT5" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT56" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT56n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT5n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT5np" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT6" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT6_BO_LAST" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT6n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT6np" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT7" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT7n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT7np" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT8" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT8n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT9" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "BIT9n" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" }, "CHAR4" : { @@ -183,58 +227,72 @@ }, "Dummy" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "HEX0_16" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "HEX0_18n" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "HEX1" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "HEX15n" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "HEX16n" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "HEX1_20n" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "HEX1_32" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "HEX1_34n" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "HEX24n" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "HEX4n" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "HEX5_16" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "HEX6n" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "HEX8n" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" }, "INT1" : { @@ -343,102 +401,127 @@ }, "OCT0" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT0n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT10" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT100n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT10n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT11" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT11n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT12" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT128n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT12n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT13" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT13n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT14" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT14n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT15" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT15n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT16" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT16n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT17" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT17n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT18" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT18n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT19" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT19n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1List" : { @@ -450,122 +533,152 @@ }, "OCT1_112n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_12" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_127n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_128n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_12n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_15n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_16n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_172n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_18n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_20n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_24n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_260" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_32" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_32n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_34n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_3n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_46n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_4n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_50" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_50n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_5n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_6n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_7n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_8" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1_8n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT1n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT2" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT20" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT20n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT28n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT2List" : { @@ -577,26 +690,32 @@ }, "OCT2n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT3" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT32" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT32n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT34" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT34n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT3List" : { @@ -608,42 +727,52 @@ }, "OCT3_14n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT3_17n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT3_5n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT3_7n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT3_8" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT3_8n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT3n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT4" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT46" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT46n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT4List" : { @@ -655,22 +784,27 @@ }, "OCT4_8n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT4n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT5" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT500n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT50n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT5List" : { @@ -682,14 +816,17 @@ }, "OCT5n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT6" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT69n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT6List" : { @@ -701,10 +838,12 @@ }, "OCT6n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT7" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT7List" : { @@ -716,30 +855,37 @@ }, "OCT7n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT8" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT8n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT9" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCT9n" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCTN" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "OCTNn" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "ProtocolList" : { @@ -761,10 +907,586 @@ "bssmap", "ranap", "dtap" + ], + "numericValues" : [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 ] } } }, "anyOf" : [ + { + "$ref" : "#/definitions/General_Types/OCT7n" + }, + { + "$ref" : "#/definitions/General_Types/OCT8n" + }, + { + "$ref" : "#/definitions/General_Types/OCT9n" + }, + { + "$ref" : "#/definitions/General_Types/BIT2n" + }, + { + "$ref" : "#/definitions/General_Types/BIT3n" + }, + { + "$ref" : "#/definitions/General_Types/BIT4n" + }, + { + "$ref" : "#/definitions/General_Types/BIT5n" + }, + { + "$ref" : "#/definitions/General_Types/BIT6n" + }, + { + "$ref" : "#/definitions/General_Types/BIT7n" + }, + { + "$ref" : "#/definitions/General_Types/BIT8n" + }, + { + "$ref" : "#/definitions/General_Types/BIT9n" + }, + { + "$ref" : "#/definitions/General_Types/BIT12n" + }, + { + "$ref" : "#/definitions/General_Types/BIT14n" + }, + { + "$ref" : "#/definitions/General_Types/BIT15n" + }, + { + "$ref" : "#/definitions/General_Types/BIT16n" + }, + { + "$ref" : "#/definitions/General_Types/BIT56n" + }, + { + "$ref" : "#/definitions/General_Types/BIT14_24n" + }, + { + "$ref" : "#/definitions/General_Types/BIT1np" + }, + { + "$ref" : "#/definitions/General_Types/BIT2np" + }, + { + "$ref" : "#/definitions/General_Types/BIT11" + }, + { + "$ref" : "#/definitions/General_Types/BIT3np" + }, + { + "$ref" : "#/definitions/General_Types/BIT4np" + }, + { + "$ref" : "#/definitions/General_Types/BIT5np" + }, + { + "$ref" : "#/definitions/General_Types/BIT6np" + }, + { + "$ref" : "#/definitions/General_Types/BIT7np" + }, + { + "$ref" : "#/definitions/General_Types/BIT15np" + }, + { + "$ref" : "#/definitions/General_Types/BIT1" + }, + { + "$ref" : "#/definitions/General_Types/BIT2" + }, + { + "$ref" : "#/definitions/General_Types/BIT3" + }, + { + "$ref" : "#/definitions/General_Types/BIT4" + }, + { + "$ref" : "#/definitions/General_Types/BIT1n" + }, + { + "$ref" : "#/definitions/General_Types/BIT5" + }, + { + "$ref" : "#/definitions/General_Types/BIT6" + }, + { + "$ref" : "#/definitions/General_Types/BIT7" + }, + { + "$ref" : "#/definitions/General_Types/BIT8" + }, + { + "$ref" : "#/definitions/General_Types/BIT9" + }, + { + "$ref" : "#/definitions/General_Types/BIT10" + }, + { + "$ref" : "#/definitions/General_Types/OCT46n" + }, + { + "$ref" : "#/definitions/General_Types/BIT12" + }, + { + "$ref" : "#/definitions/General_Types/BIT14" + }, + { + "$ref" : "#/definitions/General_Types/BIT15" + }, + { + "$ref" : "#/definitions/General_Types/BIT16" + }, + { + "$ref" : "#/definitions/General_Types/BIT24" + }, + { + "$ref" : "#/definitions/General_Types/BIT31" + }, + { + "$ref" : "#/definitions/General_Types/BIT56" + }, + { + "$ref" : "#/definitions/General_Types/OCT0n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1n" + }, + { + "$ref" : "#/definitions/General_Types/OCT2n" + }, + { + "$ref" : "#/definitions/General_Types/OCT3n" + }, + { + "$ref" : "#/definitions/General_Types/OCT4n" + }, + { + "$ref" : "#/definitions/General_Types/OCT5n" + }, + { + "$ref" : "#/definitions/General_Types/OCT6n" + }, + { + "$ref" : "#/definitions/General_Types/OCT10n" + }, + { + "$ref" : "#/definitions/General_Types/OCT11n" + }, + { + "$ref" : "#/definitions/General_Types/OCT12n" + }, + { + "$ref" : "#/definitions/General_Types/OCT13n" + }, + { + "$ref" : "#/definitions/General_Types/OCT14n" + }, + { + "$ref" : "#/definitions/General_Types/OCT15n" + }, + { + "$ref" : "#/definitions/General_Types/OCT16n" + }, + { + "$ref" : "#/definitions/General_Types/OCT17n" + }, + { + "$ref" : "#/definitions/General_Types/OCT18n" + }, + { + "$ref" : "#/definitions/General_Types/OCT19n" + }, + { + "$ref" : "#/definitions/General_Types/OCT20n" + }, + { + "$ref" : "#/definitions/General_Types/OCT28n" + }, + { + "$ref" : "#/definitions/General_Types/OCT32n" + }, + { + "$ref" : "#/definitions/General_Types/OCT34n" + }, + { + "$ref" : "#/definitions/General_Types/OCT6" + }, + { + "$ref" : "#/definitions/General_Types/OCT50n" + }, + { + "$ref" : "#/definitions/General_Types/OCT69n" + }, + { + "$ref" : "#/definitions/General_Types/OCT100n" + }, + { + "$ref" : "#/definitions/General_Types/OCT128n" + }, + { + "$ref" : "#/definitions/General_Types/OCT500n" + }, + { + "$ref" : "#/definitions/General_Types/OCTNn" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_3n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_4n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_5n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_6n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_7n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_8n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_12n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_15n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_16n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_18n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_20n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_24n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_32n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_34n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_46n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_50n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_112n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_127n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_128n" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_172n" + }, + { + "$ref" : "#/definitions/General_Types/OCT3_5n" + }, + { + "$ref" : "#/definitions/General_Types/OCT3_7n" + }, + { + "$ref" : "#/definitions/General_Types/OCT3_8n" + }, + { + "$ref" : "#/definitions/General_Types/OCT3_14n" + }, + { + "$ref" : "#/definitions/General_Types/OCT3_17n" + }, + { + "$ref" : "#/definitions/General_Types/OCT4_8n" + }, + { + "$ref" : "#/definitions/General_Types/CHAR4" + }, + { + "$ref" : "#/definitions/General_Types/HEX4n" + }, + { + "$ref" : "#/definitions/General_Types/HEX6n" + }, + { + "$ref" : "#/definitions/General_Types/HEX8n" + }, + { + "$ref" : "#/definitions/General_Types/HEX15n" + }, + { + "$ref" : "#/definitions/General_Types/HEX16n" + }, + { + "$ref" : "#/definitions/General_Types/HEX24n" + }, + { + "$ref" : "#/definitions/General_Types/HEX0_18n" + }, + { + "$ref" : "#/definitions/General_Types/HEX1_20n" + }, + { + "$ref" : "#/definitions/General_Types/HEX1_34n" + }, + { + "$ref" : "#/definitions/General_Types/INT3nb" + }, + { + "$ref" : "#/definitions/General_Types/INT4nb" + }, + { + "$ref" : "#/definitions/General_Types/INT5nb" + }, + { + "$ref" : "#/definitions/General_Types/INT8nb" + }, + { + "$ref" : "#/definitions/General_Types/INT2nbp" + }, + { + "$ref" : "#/definitions/General_Types/INT1nbp" + }, + { + "$ref" : "#/definitions/General_Types/INT3nbp" + }, + { + "$ref" : "#/definitions/General_Types/INT5nbp" + }, + { + "$ref" : "#/definitions/General_Types/INT9nbp" + }, + { + "$ref" : "#/definitions/General_Types/INT13nbp" + }, + { + "$ref" : "#/definitions/General_Types/INT15nbp" + }, + { + "$ref" : "#/definitions/General_Types/BIT6_BO_LAST" + }, + { + "$ref" : "#/definitions/General_Types/BIT16_BO_LAST" + }, + { + "$ref" : "#/definitions/General_Types/BIT32_BO_LAST" + }, + { + "$ref" : "#/definitions/General_Types/Dummy" + }, + { + "$ref" : "#/definitions/General_Types/OCT0" + }, + { + "$ref" : "#/definitions/General_Types/OCT1" + }, + { + "$ref" : "#/definitions/General_Types/OCT2" + }, + { + "$ref" : "#/definitions/General_Types/OCT3" + }, + { + "$ref" : "#/definitions/General_Types/OCT4" + }, + { + "$ref" : "#/definitions/General_Types/OCT5" + }, + { + "$ref" : "#/definitions/General_Types/OCT7" + }, + { + "$ref" : "#/definitions/General_Types/OCT8" + }, + { + "$ref" : "#/definitions/General_Types/OCT9" + }, + { + "$ref" : "#/definitions/General_Types/OCT10" + }, + { + "$ref" : "#/definitions/General_Types/OCT11" + }, + { + "$ref" : "#/definitions/General_Types/OCT12" + }, + { + "$ref" : "#/definitions/General_Types/OCT13" + }, + { + "$ref" : "#/definitions/General_Types/OCT14" + }, + { + "$ref" : "#/definitions/General_Types/OCT15" + }, + { + "$ref" : "#/definitions/General_Types/OCT16" + }, + { + "$ref" : "#/definitions/General_Types/OCT17" + }, + { + "$ref" : "#/definitions/General_Types/OCT18" + }, + { + "$ref" : "#/definitions/General_Types/OCT19" + }, + { + "$ref" : "#/definitions/General_Types/OCT20" + }, + { + "$ref" : "#/definitions/General_Types/OCT32" + }, + { + "$ref" : "#/definitions/General_Types/OCT34" + }, + { + "$ref" : "#/definitions/General_Types/OCT46" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_260" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_8" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_12" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_32" + }, + { + "$ref" : "#/definitions/General_Types/OCT1_50" + }, + { + "$ref" : "#/definitions/General_Types/OCT3_8" + }, + { + "$ref" : "#/definitions/General_Types/OCTN" + }, + { + "$ref" : "#/definitions/General_Types/HEX1" + }, + { + "$ref" : "#/definitions/General_Types/HEX0_16" + }, + { + "$ref" : "#/definitions/General_Types/HEX5_16" + }, + { + "$ref" : "#/definitions/General_Types/HEX1_32" + }, + { + "$ref" : "#/definitions/General_Types/INT1" + }, + { + "$ref" : "#/definitions/General_Types/LIN1" + }, + { + "$ref" : "#/definitions/General_Types/LIN2" + }, + { + "$ref" : "#/definitions/General_Types/LIN2_BO_LAST" + }, + { + "$ref" : "#/definitions/General_Types/LIN3_BO_LAST" + }, + { + "$ref" : "#/definitions/General_Types/LIN4_BO_LAST" + }, + { + "$ref" : "#/definitions/General_Types/INT1b" + }, + { + "$ref" : "#/definitions/General_Types/INT2b" + }, + { + "$ref" : "#/definitions/General_Types/INT3b" + }, + { + "$ref" : "#/definitions/General_Types/INT4b" + }, + { + "$ref" : "#/definitions/General_Types/INT5b" + }, + { + "$ref" : "#/definitions/General_Types/INT6b" + }, + { + "$ref" : "#/definitions/General_Types/INT7b" + }, + { + "$ref" : "#/definitions/General_Types/INT11b_BO_LAST" + }, + { + "$ref" : "#/definitions/General_Types/INT12b_BO_LAST" + }, + { + "$ref" : "#/definitions/General_Types/INT13b_BO_LAST" + }, + { + "$ref" : "#/definitions/General_Types/INT14b_BO_LAST" + }, + { + "$ref" : "#/definitions/General_Types/INT20b_BO_LAST" + }, + { + "$ref" : "#/definitions/General_Types/INT31b_BO_LAST" + }, + { + "$ref" : "#/definitions/General_Types/Integers" + }, + { + "$ref" : "#/definitions/General_Types/Integer_array" + }, + { + "$ref" : "#/definitions/General_Types/Protocols" + }, + { + "$ref" : "#/definitions/General_Types/OCT1List" + }, + { + "$ref" : "#/definitions/General_Types/OCT2List" + }, + { + "$ref" : "#/definitions/General_Types/OCT3List" + }, + { + "$ref" : "#/definitions/General_Types/OCT4List" + }, + { + "$ref" : "#/definitions/General_Types/OCT5List" + }, + { + "$ref" : "#/definitions/General_Types/OCT6List" + }, + { + "$ref" : "#/definitions/General_Types/OCT7List" + }, + { + "$ref" : "#/definitions/General_Types/ProtocolList" + } ] } diff --git a/regression_test/ttcn2json/Main.ttcn b/regression_test/ttcn2json/Main.ttcn new file mode 100644 index 0000000..258f2a2 --- /dev/null +++ b/regression_test/ttcn2json/Main.ttcn @@ -0,0 +1,37 @@ +/****************************************************************************** + * Copyright (c) 2000-2015 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + ******************************************************************************/ + +module Main +{ + +import from PDU_Definitions all; + +type record HasPardType { + ProtocolElem_Field1 pard, + boolean buul, + Price price +} + +external function f_enc_hpt(in HasPardType x) return octetstring + with { extension "prototype(convert) encode(JSON) printing(pretty)" } + +external function f_dec_hpt(in octetstring x) return HasPardType + with { extension "prototype(convert) decode(JSON)" } + +external function f_enc_pard(in ProtocolElem_Field1 x) return octetstring + with { extension "prototype(convert) encode(JSON) printing(pretty)" } + +external function f_enc_obj(in Object x) return octetstring + with { extension "prototype(convert) encode(JSON)" } + +external function f_dec_obj(in octetstring x) return Object + with { extension "prototype(convert) decode(JSON)" } + +} with { + encode "JSON" +} diff --git a/regression_test/ttcn2json/Main_e.json b/regression_test/ttcn2json/Main_e.json new file mode 100644 index 0000000..40a29b3 --- /dev/null +++ b/regression_test/ttcn2json/Main_e.json @@ -0,0 +1,279 @@ +{ + "definitions" : { + "Main" : { + "HasPardType" : { + "type" : "object", + "subType" : "record", + "properties" : { + "pard" : { + "$ref" : "#/definitions/PDU_Definitions/ProtocolElem_Field1" + }, + "buul" : { + "type" : "boolean" + }, + "price" : { + "$ref" : "#/definitions/PDU_Definitions/Price" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "pard", + "buul", + "price" + ], + "required" : [ + "pard", + "buul", + "price" + ] + } + }, + "PDU_Definitions" : { + "Priority" : { + "enum" : [ + "low", + "normal", + "medium", + "high", + "urgent" + ], + "numericValues" : [ + 0, + 1, + 2, + 3, + 4 + ] + }, + "Conditionality" : { + "enum" : [ + "optional_", + "conditional", + "mandatory" + ], + "numericValues" : [ + 0, + 1, + 2 + ] + }, + "ProtocolElem_ID" : { + "type" : "integer" + }, + "ProtocolElem_Field2" : { + "type" : "object", + "subType" : "record", + "properties" : { + "id" : { + "$ref" : "#/definitions/PDU_Definitions/ProtocolElem_ID" + }, + "priority" : { + "$ref" : "#/definitions/PDU_Definitions/Priority" + }, + "val" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "iA5String" : { + "type" : "string", + "subType" : "charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "iA5String" + ] + } + ] + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "id", + "priority", + "val" + ], + "required" : [ + "id", + "priority", + "val" + ] + }, + "ProtocolElem_Field1" : { + "type" : "object", + "subType" : "record", + "properties" : { + "id" : { + "$ref" : "#/definitions/PDU_Definitions/ProtocolElem_ID" + }, + "priority" : { + "$ref" : "#/definitions/PDU_Definitions/Priority" + }, + "val" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "iNTEGER" : { + "type" : "integer" + } + }, + "additionalProperties" : false, + "required" : [ + "iNTEGER" + ] + }, + { + "type" : "object", + "properties" : { + "iA5String" : { + "type" : "string", + "subType" : "charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "iA5String" + ] + } + ] + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "id", + "priority", + "val" + ], + "required" : [ + "id", + "priority", + "val" + ] + }, + "Price" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "value_" : { + "anyOf" : [ + { + "type" : "number" + }, + { + "enum" : [ + "not_a_number", + "infinity", + "-infinity" + ] + } + ] + } + }, + "additionalProperties" : false, + "required" : [ + "value_" + ] + }, + { + "type" : "object", + "properties" : { + "invaluable" : { + "type" : "null" + } + }, + "additionalProperties" : false, + "required" : [ + "invaluable" + ] + } + ] + }, + "Object" : { + "type" : "object", + "subType" : "record", + "properties" : { + "id" : { + "type" : "string", + "subType" : "objid", + "pattern" : "^[0-2][.][1-3]?[0-9]([.][0-9]|([1-9][0-9]+))*$" + }, + "data" : { + "type" : "string", + "subType" : "octetstring", + "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "id", + "data" + ], + "required" : [ + "id", + "data" + ] + }, + "HasNull" : { + "type" : "object", + "subType" : "record", + "properties" : { + "theNull" : { + "type" : "null" + } + }, + "additionalProperties" : false + } + } + }, + "anyOf" : [ + { + "$ref" : "#/definitions/Main/HasPardType", + "decoding" : { + "prototype" : [ + "convert", + "f_dec_hpt", + "x" + ] + }, + "encoding" : { + "prototype" : [ + "convert", + "f_enc_hpt", + "x" + ], + "printing" : "pretty" + } + }, + { + "$ref" : "#/definitions/PDU_Definitions/ProtocolElem_Field1", + "encoding" : { + "prototype" : [ + "convert", + "f_enc_pard", + "x" + ], + "printing" : "pretty" + } + }, + { + "$ref" : "#/definitions/PDU_Definitions/Object", + "decoding" : { + "prototype" : [ + "convert", + "f_dec_obj", + "x" + ] + }, + "encoding" : { + "prototype" : [ + "convert", + "f_enc_obj", + "x" + ] + } + } + ] +} diff --git a/regression_test/ttcn2json/Makefile b/regression_test/ttcn2json/Makefile index a72bacd..30664bb 100755 --- a/regression_test/ttcn2json/Makefile +++ b/regression_test/ttcn2json/Makefile @@ -13,7 +13,7 @@ include $(TOPDIR)/Makefile.regression TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) -TTCN3_MODULES = PIPEasp_PortType.ttcn PIPEasp_Types.ttcn PIPEasp_Templates.ttcn Shell.ttcn Testcases.ttcn +TTCN3_MODULES = PIPEasp_PortType.ttcn PIPEasp_Types.ttcn PIPEasp_Templates.ttcn Shell.ttcn Testcases.ttcn CompareSchemas.ttcn ASN1_MODULES = @@ -23,14 +23,14 @@ ifdef CODE_SPLIT GENERATED_SOURCES := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), .cc _seq.cc _set.cc _seqof.cc _setof.cc _union.cc)) endif -USER_SOURCES = PIPEasp_PT.cc +USER_SOURCES = PIPEasp_PT.cc f_ext_import_schema.cc USER_HEADERS = $(USER_SOURCES:.cc=.hh) OBJECTS = $(GENERATED_SOURCES:.cc=.o) $(USER_SOURCES:.cc=.o) TARGET = ttcn2json$(EXESUFFIX) -TEMP_FILES = General_Types.json one.json two.json three.json +TEMP_FILES = General_Types.json one.json two.json three.json Main.json all: $(TARGET) diff --git a/regression_test/ttcn2json/MiniRanap.asn b/regression_test/ttcn2json/MiniRanap.asn new file mode 100644 index 0000000..0be5148 --- /dev/null +++ b/regression_test/ttcn2json/MiniRanap.asn @@ -0,0 +1,80 @@ +------------------------------------------------------------------------------- +-- Copyright (c) 2000-2015 Ericsson Telecom AB +-- All rights reserved. This program and the accompanying materials +-- are made available under the terms of the Eclipse Public License v1.0 +-- which accompanies this distribution, and is available at +-- http://www.eclipse.org/legal/epl-v10.html +------------------------------------------------------------------------------- + +MiniRanap + +-- This module contains a simplified version of the type DirectTransferInformationList-RANAP-RelocInf +-- from the RANAP protocol module and any elements needed to recreate it. +-- Used for tesing the JSON schema generator on an ASN.1 ellipsis type + +DEFINITIONS + +AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS ; + +-- RANAP-CommonDataTypes +Criticality ::= ENUMERATED { reject, ignore, notify } + +Presence ::= ENUMERATED { optionalValue, conditional, mandatory } + +ProtocolIE-ID ::= INTEGER (0..65535) + +-- RANAP-Containers +RANAP-PROTOCOL-IES ::= CLASS { + &id ProtocolIE-ID UNIQUE, + &criticality Criticality, + &Value, + &presence Presence +} +WITH SYNTAX { + ID &id + CRITICALITY &criticality + TYPE &Value + PRESENCE &presence +} + +ProtocolIE-ContainerList {INTEGER : lowerBound, INTEGER : upperBound, RANAP-PROTOCOL-IES : IEsSetParam} ::= + SEQUENCE (SIZE (lowerBound..upperBound)) OF + ProtocolIE-Container {{IEsSetParam}} + +ProtocolIE-Container {RANAP-PROTOCOL-IES : IEsSetParam} ::= + SEQUENCE (SIZE (0..maxProtocolIEs)) OF + ProtocolIE-Field {{IEsSetParam}} + +ProtocolIE-Field {RANAP-PROTOCOL-IES : IEsSetParam} ::= SEQUENCE { + id RANAP-PROTOCOL-IES.&id ({IEsSetParam}), + criticality RANAP-PROTOCOL-IES.&criticality ({IEsSetParam}{@id}), + valueField RANAP-PROTOCOL-IES.&Value ({IEsSetParam}{@id}) +} + +-- RANAP-PDU-Contents +DirectTransfer-IE-ContainerList { RANAP-PROTOCOL-IES : IEsSetParam } ::= + ProtocolIE-ContainerList { 1, maxNrOfDTs, {IEsSetParam} } + +DirectTransferInformationList-RANAP-RelocInf ::= + DirectTransfer-IE-ContainerList { {DirectTransferInformationItemIEs-RANAP-RelocInf} } + +DirectTransferInformationItemIEs-RANAP-RelocInf RANAP-PROTOCOL-IES ::= { + { ID id-DirectTransferInformationItem-RANAP-RelocInf + CRITICALITY ignore TYPE INTEGER --DirectTransferInformationItem-RANAP-RelocInf + PRESENCE mandatory }, + ... +} + +-- RABAP-Constants +maxNrOfDTs INTEGER ::= 15 + +id-DirectTransferInformationItem-RANAP-RelocInf INTEGER ::= 80 + +maxProtocolIEs INTEGER ::= 65535 + +END + diff --git a/regression_test/ttcn2json/MiniRanap_e.json b/regression_test/ttcn2json/MiniRanap_e.json new file mode 100644 index 0000000..534ec07 --- /dev/null +++ b/regression_test/ttcn2json/MiniRanap_e.json @@ -0,0 +1,94 @@ +{ + "definitions" : { + "MiniRanap" : { + "Criticality" : { + "enum" : [ + "reject", + "ignore", + "notify" + ], + "numericValues" : [ + 0, + 1, + 2 + ] + }, + "DirectTransferInformationList_RANAP_RelocInf" : { + "type" : "array", + "subType" : "record of", + "items" : { + "type" : "array", + "subType" : "record of", + "items" : { + "type" : "object", + "subType" : "record", + "properties" : { + "id" : { + "$ref" : "#/definitions/MiniRanap/ProtocolIE_ID" + }, + "criticality" : { + "$ref" : "#/definitions/MiniRanap/Criticality" + }, + "valueField" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "iNTEGER" : { + "type" : "integer" + } + }, + "additionalProperties" : false, + "required" : [ + "iNTEGER" + ] + } + ] + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "id", + "criticality", + "valueField" + ], + "required" : [ + "id", + "criticality", + "valueField" + ] + } + } + }, + "Presence" : { + "enum" : [ + "optionalValue", + "conditional", + "mandatory" + ], + "numericValues" : [ + 0, + 1, + 2 + ] + }, + "ProtocolIE_ID" : { + "type" : "integer" + } + } + }, + "anyOf" : [ + { + "$ref" : "#/definitions/MiniRanap/Criticality" + }, + { + "$ref" : "#/definitions/MiniRanap/Presence" + }, + { + "$ref" : "#/definitions/MiniRanap/ProtocolIE_ID" + }, + { + "$ref" : "#/definitions/MiniRanap/DirectTransferInformationList_RANAP_RelocInf" + } + ] +} diff --git a/regression_test/ttcn2json/PDU_Definitions.asn b/regression_test/ttcn2json/PDU_Definitions.asn new file mode 100644 index 0000000..4b33888 --- /dev/null +++ b/regression_test/ttcn2json/PDU_Definitions.asn @@ -0,0 +1,93 @@ +------------------------------------------------------------------------------ +-- Copyright (c) 2000-2015 Ericsson Telecom AB +-- All rights reserved. This program and the accompanying materials +-- are made available under the terms of the Eclipse Public License v1.0 +-- which accompanies this distribution, and is available at +-- http://www.eclipse.org/legal/epl-v10.html +------------------------------------------------------------------------------ + +-- +-- Based on definitions used in S1AP +-- + +PDU-Definitions DEFINITIONS ::= +BEGIN + +Priority ::= ENUMERATED { low, normal, medium, high, urgent } + +Conditionality ::= ENUMERATED { optional, conditional, mandatory } + +ProtocolElem-ID ::= INTEGER (0..65535) + + +--IOC +PROTOCOL-ELEMS ::= CLASS +{ + &id ProtocolElem-ID UNIQUE, + &priority Priority, + &Value, + &conditionality Conditionality +} +WITH SYNTAX +{ + ID &id + PRIORITY &priority + TYPE &Value + CONDITIONALITY &conditionality +} + +--parameterized type +ProtocolElem-Field {PROTOCOL-ELEMS : ElemsSetParam} ::= SEQUENCE +{ + id PROTOCOL-ELEMS.&id ({ElemsSetParam}), + priority PROTOCOL-ELEMS.&priority ({ElemsSetParam}{@id}), + val PROTOCOL-ELEMS.&Value ({ElemsSetParam}{@id}) +} + + +--Information objects +ies-Set-Element-1 PROTOCOL-ELEMS ::= +{ + ID 0 + PRIORITY low + TYPE INTEGER + CONDITIONALITY mandatory +} + +ies-Set-Element-2 PROTOCOL-ELEMS ::= +{ + ID 1 + PRIORITY high + TYPE IA5String + CONDITIONALITY optional +} +--Information Object Set +Elems-Set PROTOCOL-ELEMS ::= { ies-Set-Element-1 | ies-Set-Element-2 } + + +--instantiation +ProtocolElem-Field1 ::= ProtocolElem-Field {{Elems-Set}} + +ProtocolElem-Field2 ::= ProtocolElem-Field {{ies-Set-Element-2 }} + +--Choice containing NULL +Price ::= CHOICE +{ + value REAL, + invaluable NULL +} + +--Sequence containing an object identifier and an ANY type +Object ::= SEQUENCE +{ + id OBJECT IDENTIFIER, + data ANY +} + +--Sequence containing an optional NULL field +HasNull ::= SEQUENCE +{ + theNull NULL OPTIONAL +} + +END diff --git a/regression_test/ttcn2json/Testcases.ttcn b/regression_test/ttcn2json/Testcases.ttcn index 7c3d326..b6ae4a6 100644 --- a/regression_test/ttcn2json/Testcases.ttcn +++ b/regression_test/ttcn2json/Testcases.ttcn @@ -9,6 +9,7 @@ module Testcases { import from Shell all; +import from CompareSchemas all; function f_test_ttcn2json(in charstring p_args, in charstring p_gen_file_name, in charstring p_exp_file_name, in integer p_exp_result) runs on Shell_CT @@ -16,34 +17,32 @@ function f_test_ttcn2json(in charstring p_args, in charstring p_gen_file_name, i var charstring v_cmd := "compiler --ttcn2json " & p_args; f_shellCommandWithVerdict(v_cmd, "", p_exp_result); - /* The generated schema cannot be checked this way, as different platforms generate the parts of the schema - in a different order if (getverdict == pass) { - f_compareFiles(p_gen_file_name, p_exp_file_name, 0); - if (getverdict == fail) { - action("Generated and expected files do not match"); + if (f_compare_schemas(p_gen_file_name, p_exp_file_name) == false) { + setverdict(fail, "Generated and expected files do not match"); } } else { action("Command ", v_cmd, " failed"); - }*/ + } + } testcase tc_t2j_one() runs on Shell_CT { - f_test_ttcn2json("one.ttcn two.ttcn three.ttcn zero.asn", "one.json", "one_e.json", + f_test_ttcn2json("-f one.ttcn two.ttcn three.ttcn zero.asn", "one.json", "one_e.json", c_shell_successWithWarning); } testcase tc_t2j_two() runs on Shell_CT { - f_test_ttcn2json("one.ttcn two.ttcn three.ttcn zero.asn - two.json", "two.json", "one_e.json", + f_test_ttcn2json("-jf one.ttcn two.ttcn three.ttcn zero.asn - two.json", "two.json", "two_e.json", c_shell_successWithWarning); } testcase tc_t2j_three() runs on Shell_CT { - f_test_ttcn2json("-T one.ttcn -T two.ttcn -T three.ttcn -A zero.asn - three.json", "three.json", "one_e.json", + f_test_ttcn2json("-j -T one.ttcn -T two.ttcn -T three.ttcn -A zero.asn - three.json", "three.json", "three_e.json", c_shell_successWithWarning); } @@ -53,11 +52,25 @@ testcase tc_t2j_general_types() runs on Shell_CT c_shell_successWithoutWarningAndError); } +testcase tc_t2j_main_asn() runs on Shell_CT +{ + f_test_ttcn2json("-f Main.ttcn PDU_Definitions.asn", "Main.json", "Main_e.json", + c_shell_successWithoutWarningAndError); +} + +testcase tc_t2j_mini_ranap() runs on Shell_CT +{ + f_test_ttcn2json("MiniRanap.asn", "MiniRanap.json", "MiniRanap_e.json", + c_shell_successWithoutWarningAndError); +} + control { execute(tc_t2j_one()); execute(tc_t2j_two()); execute(tc_t2j_three()); execute(tc_t2j_general_types()); + execute(tc_t2j_main_asn()); + execute(tc_t2j_mini_ranap()); } } diff --git a/regression_test/ttcn2json/f_ext_import_schema.cc b/regression_test/ttcn2json/f_ext_import_schema.cc new file mode 100644 index 0000000..0532083 --- /dev/null +++ b/regression_test/ttcn2json/f_ext_import_schema.cc @@ -0,0 +1,456 @@ +/****************************************************************************** + * Copyright (c) 2000-2015 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + ******************************************************************************/ + +#include "f_ext_import_schema.hh" +#include +#include + +namespace CompareSchemas { + +#define IMPORT_FORMAT_ERROR(cond, comment) \ + if (cond) { \ + TTCN_error("Invalid format for file '%s' (%s). JSON schema could not be imported.", file_name, comment); \ + } + +ElemKey get_elem_key(const char* value, size_t value_len, const char* file_name) +{ + if (4 == value_len && 0 == strncmp(value, "$ref", value_len)) { + return ElemKey::Ref; + } + if (4 == value_len && 0 == strncmp(value, "type", value_len)) { + return ElemKey::Type; + } + if (7 == value_len && 0 == strncmp(value, "subType", value_len)) { + return ElemKey::SubType; + } + if (7 == value_len && 0 == strncmp(value, "pattern", value_len)) { + return ElemKey::Pattern; + } + if (12 == value_len && 0 == strncmp(value, "originalName", value_len)) { + return ElemKey::OriginalName; + } + if (11 == value_len && 0 == strncmp(value, "unusedAlias", value_len)) { + return ElemKey::UnusedAlias; + } + if (20 == value_len && 0 == strncmp(value, "additionalProperties", value_len)) { + return ElemKey::AdditionalProperties; + } + if (10 == value_len && 0 == strncmp(value, "omitAsNull", value_len)) { + return ElemKey::OmitAsNull; + } + if (7 == value_len && 0 == strncmp(value, "default", value_len)) { + return ElemKey::Default; + } + if (8 == value_len && 0 == strncmp(value, "minItems", value_len)) { + return ElemKey::MinItems; + } + if (8 == value_len && 0 == strncmp(value, "maxItems", value_len)) { + return ElemKey::MaxItems; + } + if (4 == value_len && 0 == strncmp(value, "enum", value_len)) { + return ElemKey::Enum; + } + if (13 == value_len && 0 == strncmp(value, "numericValues", value_len)) { + return ElemKey::NumericValues; + } + if (5 == value_len && 0 == strncmp(value, "items", value_len)) { + return ElemKey::Items; + } + if (5 == value_len && 0 == strncmp(value, "anyOf", value_len)) { + return ElemKey::AnyOf; + } + if (8 == value_len && 0 == strncmp(value, "required", value_len)) { + return ElemKey::Required; + } + if (10 == value_len && 0 == strncmp(value, "fieldOrder", value_len)) { + return ElemKey::FieldOrder; + } + if (10 == value_len && 0 == strncmp(value, "properties", value_len)) { + return ElemKey::Properties; + } + // throw the DTE if it didn't return until now + IMPORT_FORMAT_ERROR(true, "unknown type element key"); +} + +TypeSchema extract_type_schema(JSON_Tokenizer& json, const char* file_name) +{ + json_token_t token = JSON_TOKEN_NONE; + char* value = NULL; + size_t value_len = 0; + + // type schema object start + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_START != token, "missing type object start"); + + // type schema elements + TypeSchema type_schema; + int elem_index = 0; + json.get_next_token(&token, &value, &value_len); + while(JSON_TOKEN_NAME == token) { + type_schema[elem_index].key() = get_elem_key(value, value_len, file_name); + switch(type_schema[elem_index].key()) { + case ElemKey::Ref: + case ElemKey::Type: + case ElemKey::SubType: + case ElemKey::Pattern: + case ElemKey::OriginalName: + case ElemKey::UnusedAlias: + case ElemKey::MinItems: + case ElemKey::MaxItems: + case ElemKey::AdditionalProperties: + case ElemKey::OmitAsNull: + case ElemKey::Default: { + // string or boolean value + json.get_next_token(&token, &value, &value_len); + switch (token) { + case JSON_TOKEN_STRING: + case JSON_TOKEN_NUMBER: { + CHARSTRING str_val(value_len, value); + type_schema[elem_index].val().strVal() = str_val; + break; } + case JSON_TOKEN_LITERAL_FALSE: + type_schema[elem_index].val().boolVal() = FALSE; + break; + case JSON_TOKEN_LITERAL_TRUE: + type_schema[elem_index].val().boolVal() = TRUE; + break; + default: + IMPORT_FORMAT_ERROR(JSON_TOKEN_LITERAL_FALSE != token, "string or boolean value expected"); + } + break; } + + case ElemKey::Enum: + case ElemKey::NumericValues: + case ElemKey::Required: + case ElemKey::FieldOrder: { + // string array value + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_START != token, "missing string array start"); + json.get_next_token(&token, &value, &value_len); + int string_index = 0; + while (JSON_TOKEN_STRING == token || JSON_TOKEN_NUMBER == token) { + CHARSTRING str_val(value_len, value); + type_schema[elem_index].val().strArrayVal()[string_index] = str_val; + + // next string + ++string_index; + json.get_next_token(&token, &value, &value_len); + } + + // string array end + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_END != token, "missing string array end"); + break; } + + case ElemKey::Items: { + // type schema value + type_schema[elem_index].val().typeVal() = extract_type_schema(json, file_name); + break; } + + case ElemKey::AnyOf: { + // type schema array value + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_START != token, "missing type array start"); + int type_index = 0; + size_t buf_pos = json.get_buf_pos(); + json.get_next_token(&token, NULL, NULL); + while (JSON_TOKEN_OBJECT_START == token) { + // revert this extraction, the type schema extractor will read the "{" again + json.set_buf_pos(buf_pos); + type_schema[elem_index].val().typeArrayVal()[type_index] = extract_type_schema(json, file_name); + + // next type schema + ++type_index; + buf_pos = json.get_buf_pos(); + json.get_next_token(&token, NULL, NULL); + } + + // type schema array end + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_END != token, "missing type array end"); + break; } + + case ElemKey::Properties: { + // field set value + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_START != token, "missing field set start"); + int field_index = 0; + json.get_next_token(&token, &value, &value_len); + while(JSON_TOKEN_NAME == token) { + // store field name and schema + CHARSTRING field_name(value_len, value); + type_schema[elem_index].val().fieldSetVal()[field_index].fieldName() = field_name; + type_schema[elem_index].val().fieldSetVal()[field_index].schema() = extract_type_schema(json, file_name); + + // next field + ++field_index; + json.get_next_token(&token, &value, &value_len); + } + + // field set value end + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_END != token, "missing field set end"); + break; } + default: + break; + } + + // next schema element + ++elem_index; + json.get_next_token(&token, &value, &value_len); + } + + // type schema object end + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_END != token, "missing type object end"); + return type_schema; +} + +EncDecData extract_enc_dec_data(JSON_Tokenizer& json, const char* file_name) +{ + // initialize (error behavior and printing data might not appear in the schema) + json_token_t token = JSON_TOKEN_NONE; + char* value = NULL; + size_t value_len = 0; + EncDecData data; + data.eb() = OMIT_VALUE; + data.printing() = OMIT_VALUE; + + // enc/dec data start + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_START != token, "missing enc/dec data start"); + json.get_next_token(&token, &value, &value_len); + while(JSON_TOKEN_NAME == token) { + if (9 == value_len && 0 == strncmp(value, "prototype", value_len)) { + // prototype (string array) + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_START != token, "missing prototype array start"); + json.get_next_token(&token, &value, &value_len); + int pt_index = 0; + while(JSON_TOKEN_STRING == token) { + CHARSTRING pt_str(value_len, value); + data.prototype()[pt_index] = pt_str; + + // next prototype element + ++pt_index; + json.get_next_token(&token, &value, &value_len); + } + + // prototype end + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_END != token, "missing prototype array end"); + } + else if (13 == value_len && 0 == strncmp(value, "errorBehavior", value_len)) { + // error behavior (object) + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_START != token, "missing error behavior start"); + json.get_next_token(&token, &value, &value_len); + int eb_index = 0; + while(JSON_TOKEN_NAME == token) { + // store the key-value pair + CHARSTRING error_type(value_len, value); + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_STRING != token, "expected error behavior string"); + CHARSTRING error_behavior(value_len, value); + data.eb()()[eb_index].errorType() = error_type; + data.eb()()[eb_index].errorBehavior() = error_behavior; + + // next pair + ++eb_index; + json.get_next_token(&token, &value, &value_len); + } + + // error behavior end + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_END != token, "missing error behavior end"); + } + else if (8 == value_len && 0 == strncmp(value, "printing", value_len)) { + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_STRING != token, "expected printing string"); + CHARSTRING printing_str(value_len, value); + data.printing()() = printing_str; + } + else { + // invalid key + IMPORT_FORMAT_ERROR(true, "invalid enc/dec data key"); + } + + // next key-value pair + json.get_next_token(&token, &value, &value_len); + } + + // enc/dec data end + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_END != token, "missing enc/dec data end"); + return data; +} + +RefSchema extract_ref_schema(JSON_Tokenizer& json, const char* file_name) +{ + // initialize (set optional fields to "omit") + json_token_t token = JSON_TOKEN_NONE; + char* value = NULL; + size_t value_len = 0; + RefSchema ref_schema; + ref_schema.enc() = OMIT_VALUE; + ref_schema.dec() = OMIT_VALUE; + + // read reference data + json.get_next_token(&token, &value, &value_len); + while(JSON_TOKEN_NAME == token) { + if (4 == value_len && 0 == strncmp(value, "$ref", value_len)) { + // reference + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_STRING != token, "missing reference string"); + CHARSTRING ref_str(value_len, value); + ref_schema.ref() = ref_str; + } + else if (8 == value_len && 0 == strncmp(value, "encoding", value_len)) { + // encoding function + ref_schema.enc()() = extract_enc_dec_data(json, file_name); + } + else if (8 == value_len && 0 == strncmp(value, "decoding", value_len)) { + // encoding function + ref_schema.dec()() = extract_enc_dec_data(json, file_name); + } + else { + // invalid key + IMPORT_FORMAT_ERROR(true, "invalid reference/function data key"); + } + + // next key-value pair + json.get_next_token(&token, &value, &value_len); + } + + // reference & function info end + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_END != token, "missing reference/function data end"); + return ref_schema; +} + +void f__ext__import__schema(const CHARSTRING& file, JsonSchema& schema) +{ + // need a null-terminated string for fopen + char* file_name = mcopystrn((const char*)file, file.lengthof()); + FILE* fp = fopen(file_name, "r"); + try { + if (NULL == fp) { + TTCN_error("Could not open file '%s' for reading. JSON schema could not be imported.", file_name); + } + + // get the file size + fseek(fp, 0, SEEK_END); + int file_size = ftell(fp); + rewind(fp); + + // read the entire file into a character buffer + char* buffer = (char*)Malloc(file_size); + fread(buffer, 1, file_size, fp); + fclose(fp); + + // initialize a JSON tokenizer with the buffer + JSON_Tokenizer json(buffer, file_size); + Free(buffer); + + // extract tokens and store the schema in the JsonSchema parameter + // throw a DTE if the file format is invalid + json_token_t token = JSON_TOKEN_NONE; + char* value = NULL; + size_t value_len = 0; + + // top level object + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_START != token, "missing top level object start"); + + // definitions + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 11 || + 0 != strncmp(value, "definitions", value_len), "missing definitions key"); + + // module list + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_START != token, "missing module list start"); + json.get_next_token(&token, &value, &value_len); + int type_index = 0; + while (JSON_TOKEN_NAME == token) { + // extract module name, it will be inserted later + CHARSTRING module_name(value_len, value); + + // type list + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_START != token, "missing type list start"); + json.get_next_token(&token, &value, &value_len); + while (JSON_TOKEN_NAME == token) { + // extract type name + CHARSTRING type_name(value_len, value); + + // extract type schema + TypeSchema type_schema = extract_type_schema(json, file_name); + + // store definition data + schema.defs()[type_index].moduleName() = module_name; + schema.defs()[type_index].typeName() = type_name; + schema.defs()[type_index].schema() = type_schema; + + // next type + ++type_index; + json.get_next_token(&token, &value, &value_len); + } + + // end of type list + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_END != token, "missing type list end"); + + // next module + json.get_next_token(&token, &value, &value_len); + } + + // end of module list + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_END != token, "missing module list end"); + + if (0 == type_index) { + // no definitions, don't leave the field unbound + schema.defs().set_size(0); + } + + // top level anyOf + json.get_next_token(&token, &value, &value_len); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NAME != token || value_len != 5 || + 0 != strncmp(value, "anyOf", value_len), "missing anyOf key"); + + // reference & function info array + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_START != token, "missing reference/function list start"); + json.get_next_token(&token, NULL, NULL); + int ref_index = 0; + while (JSON_TOKEN_OBJECT_START == token) { + + // extract reference schema + schema.refs()[ref_index] = extract_ref_schema(json, file_name); + + // next reference + ++ref_index; + json.get_next_token(&token, NULL, NULL); + } + + // end of reference & function info array + IMPORT_FORMAT_ERROR(JSON_TOKEN_ARRAY_END != token, "missing reference/function list end"); + + if (0 == ref_index) { + // no references, don't leave the field unbound + schema.refs().set_size(0); + } + + // end of top level object + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_OBJECT_END != token, "missing top level object end"); + + // end of the schema + json.get_next_token(&token, NULL, NULL); + IMPORT_FORMAT_ERROR(JSON_TOKEN_NONE != token, "expected end of file"); + } + catch (...) { + Free(file_name); + throw; + } + Free(file_name); +} + +} + diff --git a/regression_test/ttcn2json/f_ext_import_schema.hh b/regression_test/ttcn2json/f_ext_import_schema.hh new file mode 100644 index 0000000..7ab618d --- /dev/null +++ b/regression_test/ttcn2json/f_ext_import_schema.hh @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2000-2015 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + ******************************************************************************/ + +#ifndef f_ext_import_schema_HH +#define f_ext_import_schema_HH + +#include "CompareSchemas.hh" + +namespace CompareSchemas { + +/** Imports a JSON schema from a given file to the specified container. + * Throws a Dynamic Testcase Error on failure. + * + * @param file source file name + * @param schema JSON schema container (defined in CompareSchemas.ttcn) + */ +extern void f__ext__import__schema(const CHARSTRING& file, JsonSchema& schema); + +} + +#endif + diff --git a/regression_test/ttcn2json/one_e.json b/regression_test/ttcn2json/one_e.json index f882745..da16123 100644 --- a/regression_test/ttcn2json/one_e.json +++ b/regression_test/ttcn2json/one_e.json @@ -27,6 +27,11 @@ "Short", "Medium", "Tall" + ], + "numericValues" : [ + 0, + 1, + 2 ] }, "Rec" : { @@ -59,6 +64,7 @@ "properties" : { "os" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" }, "buul" : { @@ -147,6 +153,7 @@ "properties" : { "bytes" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" } }, @@ -162,6 +169,11 @@ "Thin", "Medium", "Wide" + ], + "numericValues" : [ + 0, + 1, + 2 ] }, "anytype" : { @@ -195,6 +207,7 @@ "properties" : { "bitstring" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" } }, @@ -212,6 +225,7 @@ "subType" : "record of", "items" : { "type" : "string", + "subType" : "bitstring", "pattern" : "^[01]*$" } }, @@ -239,6 +253,7 @@ "subType" : "record of", "items" : { "type" : "string", + "subType" : "hexstring", "pattern" : "^[0-9A-Fa-f]*$" } }, @@ -261,6 +276,7 @@ "subType" : "set of", "items" : { "type" : "string", + "subType" : "octetstring", "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" } }, @@ -322,6 +338,11 @@ "Small", "Medium", "Large" + ], + "numericValues" : [ + 0, + 1, + 2 ] }, "filled" : { @@ -429,6 +450,109 @@ } }, "Zero" : { + "SeqOfInt" : { + "type" : "array", + "subType" : "record of", + "items" : { + "type" : "integer" + } + }, + "SeqProduct" : { + "type" : "object", + "subType" : "record", + "properties" : { + "name" : { + "type" : "string", + "subType" : "universal charstring" + }, + "price" : { + "anyOf" : [ + { + "type" : "number" + }, + { + "enum" : [ + "not_a_number", + "infinity", + "-infinity" + ] + } + ] + }, + "id" : { + "anyOf" : [ + { + "type" : "null" + }, + { + "type" : "string", + "subType" : "octetstring", + "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" + } + ], + "omitAsNull" : false + }, + "available" : { + "type" : "boolean" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "name", + "price", + "id", + "available" + ], + "required" : [ + "name", + "price", + "available" + ] + }, + "Number" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "decimal" : { + "type" : "integer" + } + }, + "additionalProperties" : false, + "required" : [ + "decimal" + ] + }, + { + "type" : "object", + "properties" : { + "binary" : { + "type" : "string", + "subType" : "bitstring", + "pattern" : "^[01]*$" + } + }, + "additionalProperties" : false, + "required" : [ + "binary" + ] + }, + { + "type" : "object", + "properties" : { + "hexadecimal" : { + "type" : "string", + "subType" : "octetstring", + "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" + } + }, + "additionalProperties" : false, + "required" : [ + "hexadecimal" + ] + } + ] + }, "AnyString" : { "anyOf" : [ { @@ -576,37 +700,12 @@ } ] }, - "Big_Choice" : { - "anyOf" : [ - { - "type" : "object", - "properties" : { - "numbers" : { - "type" : "array", - "subType" : "set of", - "items" : { - "$ref" : "#/definitions/Zero/Number" - } - } - }, - "additionalProperties" : false, - "required" : [ - "numbers" - ] - }, - { - "type" : "object", - "properties" : { - "strings" : { - "$ref" : "#/definitions/Zero/ManyStrings" - } - }, - "additionalProperties" : false, - "required" : [ - "strings" - ] - } - ] + "ManyStrings" : { + "type" : "array", + "subType" : "record of", + "items" : { + "$ref" : "#/definitions/Zero/AnyString" + } }, "Big_Set" : { "type" : "object", @@ -631,6 +730,12 @@ "blue", "green", "yellow" + ], + "numericValues" : [ + 0, + 1, + 2, + 3 ] } }, @@ -648,55 +753,52 @@ "color" ] }, - "ManyStrings" : { - "type" : "array", - "subType" : "record of", - "items" : { - "$ref" : "#/definitions/Zero/AnyString" - } - }, - "Number" : { + "Big_Choice" : { "anyOf" : [ { "type" : "object", "properties" : { - "decimal" : { - "type" : "integer" - } - }, - "additionalProperties" : false, - "required" : [ - "decimal" - ] - }, - { - "type" : "object", - "properties" : { - "binary" : { - "type" : "string", - "pattern" : "^[01]*$" + "numbers" : { + "type" : "array", + "subType" : "set of", + "items" : { + "$ref" : "#/definitions/Zero/Number" + } } }, "additionalProperties" : false, "required" : [ - "binary" + "numbers" ] }, { "type" : "object", "properties" : { - "hexadecimal" : { - "type" : "string", - "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" + "strings" : { + "$ref" : "#/definitions/Zero/ManyStrings" } }, "additionalProperties" : false, "required" : [ - "hexadecimal" + "strings" ] } ] }, + "Season" : { + "enum" : [ + "spring", + "summer", + "fall", + "winter" + ], + "numericValues" : [ + 1, + 2, + 3, + 4 + ] + }, "SelectionType" : { "type" : "array", "subType" : "set of", @@ -704,63 +806,18 @@ "$ref" : "#/definitions/Zero/Number" } }, - "SeqOfInt" : { - "type" : "array", - "subType" : "record of", - "items" : { - "type" : "integer" - } + "NullType" : { + "type" : "null" }, - "SeqProduct" : { - "type" : "object", - "subType" : "record", - "properties" : { - "name" : { - "type" : "string", - "subType" : "universal charstring" - }, - "price" : { - "anyOf" : [ - { - "type" : "number" - }, - { - "enum" : [ - "not_a_number", - "infinity", - "-infinity" - ] - } - ] - }, - "id" : { - "anyOf" : [ - { - "type" : "null" - }, - { - "type" : "string", - "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" - } - ], - "omitAsNull" : false - }, - "available" : { - "type" : "boolean" - } - }, - "additionalProperties" : false, - "fieldOrder" : [ - "name", - "price", - "id", - "available" - ], - "required" : [ - "name", - "price", - "available" - ] + "ObjIdType" : { + "type" : "string", + "subType" : "objid", + "pattern" : "^[0-2][.][1-3]?[0-9]([.][0-9]|([1-9][0-9]+))*$" + }, + "RelObjIdType" : { + "type" : "string", + "subType" : "objid", + "pattern" : "^[0-2][.][1-3]?[0-9]([.][0-9]|([1-9][0-9]+))*$" } } }, diff --git a/regression_test/ttcn2json/three_e.json b/regression_test/ttcn2json/three_e.json new file mode 100644 index 0000000..52268ba --- /dev/null +++ b/regression_test/ttcn2json/three_e.json @@ -0,0 +1,866 @@ +{ + "definitions" : { + "one" : { + "HasAny" : { + "type" : "object", + "subType" : "record", + "properties" : { + "num" : { + "type" : "integer" + }, + "at" : { + "$ref" : "#/definitions/one/anytype" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "num", + "at" + ], + "required" : [ + "num", + "at" + ] + }, + "Height" : { + "enum" : [ + "Short", + "Medium", + "Tall" + ], + "numericValues" : [ + 0, + 1, + 2 + ] + }, + "Rec" : { + "type" : "object", + "subType" : "record", + "properties" : { + "num" : { + "type" : "integer", + "default" : 0 + }, + "str" : { + "type" : "string", + "subType" : "universal charstring", + "default" : "empty" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "num", + "str" + ], + "required" : [ + "num", + "str" + ] + }, + "Set" : { + "type" : "object", + "subType" : "set", + "properties" : { + "os" : { + "type" : "string", + "subType" : "octetstring", + "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" + }, + "buul" : { + "anyOf" : [ + { + "type" : "null" + }, + { + "type" : "boolean" + } + ], + "omitAsNull" : true + }, + "verd" : { + "anyOf" : [ + { + "type" : "null" + }, + { + "enum" : [ + "none", + "pass", + "inconc", + "fail", + "error" + ] + } + ], + "omitAsNull" : false + }, + "numbr" : { + "anyOf" : [ + { + "type" : "number" + }, + { + "enum" : [ + "not_a_number", + "infinity", + "-infinity" + ] + } + ], + "default" : "-infinity" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "os", + "buul", + "verd", + "numbr" + ], + "required" : [ + "os", + "numbr" + ] + }, + "Uni" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "numbr" : { + "anyOf" : [ + { + "type" : "number" + }, + { + "enum" : [ + "not_a_number", + "infinity", + "-infinity" + ] + } + ] + } + }, + "additionalProperties" : false, + "required" : [ + "numbr" + ] + }, + { + "type" : "object", + "properties" : { + "bytes" : { + "type" : "string", + "subType" : "octetstring", + "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" + } + }, + "additionalProperties" : false, + "required" : [ + "bytes" + ] + } + ] + }, + "Width" : { + "enum" : [ + "Thin", + "Medium", + "Wide" + ], + "numericValues" : [ + 0, + 1, + 2 + ] + }, + "anytype" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "integer" : { + "type" : "integer" + } + }, + "additionalProperties" : false, + "required" : [ + "integer" + ] + }, + { + "type" : "object", + "properties" : { + "boolean" : { + "type" : "boolean" + } + }, + "additionalProperties" : false, + "required" : [ + "boolean" + ] + }, + { + "type" : "object", + "properties" : { + "bitstring" : { + "type" : "string", + "subType" : "bitstring", + "pattern" : "^[01]*$" + } + }, + "additionalProperties" : false, + "required" : [ + "bitstring" + ] + } + ] + } + }, + "two" : { + "Ints" : { + "type" : "array", + "subType" : "record of", + "items" : { + "type" : "integer" + } + }, + "PosInt" : { + "type" : "integer" + } + }, + "three" : { + "Barrels" : { + "type" : "object", + "subType" : "set", + "properties" : { + "numBarrels" : { + "type" : "integer" + }, + "barrelType" : { + "type" : "object", + "subType" : "record", + "properties" : { + "size" : { + "enum" : [ + "Small", + "Medium", + "Large" + ], + "numericValues" : [ + 0, + 1, + 2 + ] + }, + "filled" : { + "type" : "boolean" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "size", + "filled" + ], + "required" : [ + "size", + "filled" + ] + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "numBarrels", + "barrelType" + ], + "required" : [ + "numBarrels", + "barrelType" + ] + }, + "Nums" : { + "type" : "array", + "subType" : "set of", + "items" : { + "type" : "object", + "subType" : "record", + "properties" : { + "number" : { + "originalName" : "num", + "type" : "integer" + } + }, + "additionalProperties" : false, + "required" : [ + "number" + ] + } + }, + "Numz" : { + "type" : "object", + "subType" : "record", + "properties" : { + "nums" : { + "$ref" : "#/definitions/three/Nums" + } + }, + "additionalProperties" : false, + "required" : [ + "nums" + ] + }, + "Rex" : { + "type" : "array", + "subType" : "record of", + "items" : { + "$ref" : "#/definitions/one/Rec" + } + }, + "Stuff" : { + "type" : "array", + "subType" : "record of", + "items" : { + "$ref" : "#/definitions/three/Thing" + } + }, + "Thing" : { + "anyOf" : [ + { + "originalName" : "b", + "type" : "boolean" + }, + { + "originalName" : "i", + "unusedAlias" : "int", + "type" : "integer" + }, + { + "originalName" : "cs", + "unusedAlias" : "str", + "type" : "string", + "subType" : "charstring" + }, + { + "originalName" : "rec", + "type" : "object", + "subType" : "record", + "properties" : { + "num" : { + "type" : "integer" + } + }, + "additionalProperties" : false, + "required" : [ + "num" + ] + } + ] + } + }, + "Zero" : { + "AnyString" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "generalstr" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "generalstr" + ] + }, + { + "type" : "object", + "properties" : { + "numericstr" : { + "type" : "string", + "subType" : "charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "numericstr" + ] + }, + { + "type" : "object", + "properties" : { + "utf8str" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "utf8str" + ] + }, + { + "type" : "object", + "properties" : { + "printablestr" : { + "type" : "string", + "subType" : "charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "printablestr" + ] + }, + { + "type" : "object", + "properties" : { + "universalstr" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "universalstr" + ] + }, + { + "type" : "object", + "properties" : { + "bmpstr" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "bmpstr" + ] + }, + { + "type" : "object", + "properties" : { + "graphicstr" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "graphicstr" + ] + }, + { + "type" : "object", + "properties" : { + "ia5str" : { + "type" : "string", + "subType" : "charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "ia5str" + ] + }, + { + "type" : "object", + "properties" : { + "teletexstr" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "teletexstr" + ] + }, + { + "type" : "object", + "properties" : { + "videotexstr" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "videotexstr" + ] + }, + { + "type" : "object", + "properties" : { + "visiblestr" : { + "type" : "string", + "subType" : "charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "visiblestr" + ] + } + ] + }, + "Big_Choice" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "numbers" : { + "type" : "array", + "subType" : "set of", + "items" : { + "$ref" : "#/definitions/Zero/Number" + } + } + }, + "additionalProperties" : false, + "required" : [ + "numbers" + ] + }, + { + "type" : "object", + "properties" : { + "strings" : { + "$ref" : "#/definitions/Zero/ManyStrings" + } + }, + "additionalProperties" : false, + "required" : [ + "strings" + ] + } + ] + }, + "Big_Set" : { + "type" : "object", + "subType" : "set", + "properties" : { + "product" : { + "$ref" : "#/definitions/Zero/SeqProduct" + }, + "numbers" : { + "type" : "array", + "subType" : "set of", + "items" : { + "$ref" : "#/definitions/Zero/Number" + } + }, + "strings" : { + "$ref" : "#/definitions/Zero/ManyStrings" + }, + "color" : { + "enum" : [ + "red", + "blue", + "green", + "yellow" + ], + "numericValues" : [ + 0, + 1, + 2, + 3 + ] + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "product", + "numbers", + "strings", + "color" + ], + "required" : [ + "product", + "numbers", + "strings", + "color" + ] + }, + "ManyStrings" : { + "type" : "array", + "subType" : "record of", + "items" : { + "$ref" : "#/definitions/Zero/AnyString" + } + }, + "NullType" : { + "type" : "null" + }, + "Number" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "decimal" : { + "type" : "integer" + } + }, + "additionalProperties" : false, + "required" : [ + "decimal" + ] + }, + { + "type" : "object", + "properties" : { + "binary" : { + "type" : "string", + "subType" : "bitstring", + "pattern" : "^[01]*$" + } + }, + "additionalProperties" : false, + "required" : [ + "binary" + ] + }, + { + "type" : "object", + "properties" : { + "hexadecimal" : { + "type" : "string", + "subType" : "octetstring", + "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" + } + }, + "additionalProperties" : false, + "required" : [ + "hexadecimal" + ] + } + ] + }, + "ObjIdType" : { + "type" : "string", + "subType" : "objid", + "pattern" : "^[0-2][.][1-3]?[0-9]([.][0-9]|([1-9][0-9]+))*$" + }, + "RelObjIdType" : { + "type" : "string", + "subType" : "objid", + "pattern" : "^[0-2][.][1-3]?[0-9]([.][0-9]|([1-9][0-9]+))*$" + }, + "Season" : { + "enum" : [ + "spring", + "summer", + "fall", + "winter" + ], + "numericValues" : [ + 1, + 2, + 3, + 4 + ] + }, + "SelectionType" : { + "type" : "array", + "subType" : "set of", + "items" : { + "$ref" : "#/definitions/Zero/Number" + } + }, + "SeqOfInt" : { + "type" : "array", + "subType" : "record of", + "items" : { + "type" : "integer" + } + }, + "SeqProduct" : { + "type" : "object", + "subType" : "record", + "properties" : { + "name" : { + "type" : "string", + "subType" : "universal charstring" + }, + "price" : { + "anyOf" : [ + { + "type" : "number" + }, + { + "enum" : [ + "not_a_number", + "infinity", + "-infinity" + ] + } + ] + }, + "id" : { + "anyOf" : [ + { + "type" : "null" + }, + { + "type" : "string", + "subType" : "octetstring", + "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" + } + ], + "omitAsNull" : false + }, + "available" : { + "type" : "boolean" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "name", + "price", + "id", + "available" + ], + "required" : [ + "name", + "price", + "available" + ] + } + } + }, + "anyOf" : [ + { + "$ref" : "#/definitions/two/Ints", + "decoding" : { + "prototype" : [ + "fast", + "f_dec_ints", + "os", + "x" + ] + }, + "encoding" : { + "prototype" : [ + "fast", + "f_enc_ints", + "eents", + "octus" + ], + "printing" : "pretty" + } + }, + { + "$ref" : "#/definitions/one/Rec", + "decoding" : { + "prototype" : [ + "convert", + "f_dec_rec", + "octie" + ], + "errorBehavior" : { + "ALL" : "WARNING", + "INVAL_MSG" : "ERROR" + } + }, + "encoding" : { + "prototype" : [ + "convert", + "f_enc_rec", + "x" + ] + } + }, + { + "$ref" : "#/definitions/one/Set" + }, + { + "$ref" : "#/definitions/one/Uni" + }, + { + "$ref" : "#/definitions/one/HasAny" + }, + { + "$ref" : "#/definitions/one/Height" + }, + { + "$ref" : "#/definitions/one/Width" + }, + { + "$ref" : "#/definitions/one/anytype" + }, + { + "$ref" : "#/definitions/three/Thing" + }, + { + "$ref" : "#/definitions/three/Stuff" + }, + { + "$ref" : "#/definitions/three/Barrels" + }, + { + "$ref" : "#/definitions/two/PosInt" + }, + { + "$ref" : "#/definitions/Zero/SeqOfInt" + }, + { + "$ref" : "#/definitions/Zero/SeqProduct" + }, + { + "$ref" : "#/definitions/Zero/Number" + }, + { + "$ref" : "#/definitions/three/Nums" + }, + { + "$ref" : "#/definitions/three/Numz" + }, + { + "$ref" : "#/definitions/three/Rex" + }, + { + "$ref" : "#/definitions/Zero/AnyString" + }, + { + "$ref" : "#/definitions/Zero/ManyStrings" + }, + { + "$ref" : "#/definitions/Zero/Big_Set", + "decoding" : { + "prototype" : [ + "convert", + "f_dec_bigset", + "os" + ] + }, + "encoding" : { + "prototype" : [ + "convert", + "f_enc_bigset", + "x" + ] + } + }, + { + "$ref" : "#/definitions/Zero/Big_Choice" + }, + { + "$ref" : "#/definitions/Zero/Season" + }, + { + "$ref" : "#/definitions/Zero/SelectionType" + }, + { + "$ref" : "#/definitions/Zero/NullType" + }, + { + "$ref" : "#/definitions/Zero/ObjIdType" + }, + { + "$ref" : "#/definitions/Zero/RelObjIdType" + } + ] +} diff --git a/regression_test/ttcn2json/two.ttcn b/regression_test/ttcn2json/two.ttcn index e54a5cb..21eb94e 100644 --- a/regression_test/ttcn2json/two.ttcn +++ b/regression_test/ttcn2json/two.ttcn @@ -7,7 +7,7 @@ ******************************************************************************/ module two { - type record of integer Ints; + type record of integer Ints with { encode "JSON" }; type set of universal charstring Strings; @@ -34,4 +34,4 @@ module two { //type record of integer Rec; -} with { encode "JSON" } +} diff --git a/regression_test/ttcn2json/two_e.json b/regression_test/ttcn2json/two_e.json new file mode 100644 index 0000000..27c91bd --- /dev/null +++ b/regression_test/ttcn2json/two_e.json @@ -0,0 +1,794 @@ +{ + "definitions" : { + "one" : { + "HasAny" : { + "type" : "object", + "subType" : "record", + "properties" : { + "num" : { + "type" : "integer" + }, + "at" : { + "$ref" : "#/definitions/one/anytype" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "num", + "at" + ], + "required" : [ + "num", + "at" + ] + }, + "Height" : { + "enum" : [ + "Short", + "Medium", + "Tall" + ], + "numericValues" : [ + 0, + 1, + 2 + ] + }, + "Rec" : { + "type" : "object", + "subType" : "record", + "properties" : { + "num" : { + "type" : "integer", + "default" : 0 + }, + "str" : { + "type" : "string", + "subType" : "universal charstring", + "default" : "empty" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "num", + "str" + ], + "required" : [ + "num", + "str" + ] + }, + "Set" : { + "type" : "object", + "subType" : "set", + "properties" : { + "os" : { + "type" : "string", + "subType" : "octetstring", + "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" + }, + "buul" : { + "anyOf" : [ + { + "type" : "null" + }, + { + "type" : "boolean" + } + ], + "omitAsNull" : true + }, + "verd" : { + "anyOf" : [ + { + "type" : "null" + }, + { + "enum" : [ + "none", + "pass", + "inconc", + "fail", + "error" + ] + } + ], + "omitAsNull" : false + }, + "numbr" : { + "anyOf" : [ + { + "type" : "number" + }, + { + "enum" : [ + "not_a_number", + "infinity", + "-infinity" + ] + } + ], + "default" : "-infinity" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "os", + "buul", + "verd", + "numbr" + ], + "required" : [ + "os", + "numbr" + ] + }, + "Uni" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "numbr" : { + "anyOf" : [ + { + "type" : "number" + }, + { + "enum" : [ + "not_a_number", + "infinity", + "-infinity" + ] + } + ] + } + }, + "additionalProperties" : false, + "required" : [ + "numbr" + ] + }, + { + "type" : "object", + "properties" : { + "bytes" : { + "type" : "string", + "subType" : "octetstring", + "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" + } + }, + "additionalProperties" : false, + "required" : [ + "bytes" + ] + } + ] + }, + "Width" : { + "enum" : [ + "Thin", + "Medium", + "Wide" + ], + "numericValues" : [ + 0, + 1, + 2 + ] + }, + "anytype" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "integer" : { + "type" : "integer" + } + }, + "additionalProperties" : false, + "required" : [ + "integer" + ] + }, + { + "type" : "object", + "properties" : { + "boolean" : { + "type" : "boolean" + } + }, + "additionalProperties" : false, + "required" : [ + "boolean" + ] + }, + { + "type" : "object", + "properties" : { + "bitstring" : { + "type" : "string", + "subType" : "bitstring", + "pattern" : "^[01]*$" + } + }, + "additionalProperties" : false, + "required" : [ + "bitstring" + ] + } + ] + } + }, + "two" : { + "Ints" : { + "type" : "array", + "subType" : "record of", + "items" : { + "type" : "integer" + } + }, + "PosInt" : { + "type" : "integer" + } + }, + "three" : { + "Barrels" : { + "type" : "object", + "subType" : "set", + "properties" : { + "numBarrels" : { + "type" : "integer" + }, + "barrelType" : { + "type" : "object", + "subType" : "record", + "properties" : { + "size" : { + "enum" : [ + "Small", + "Medium", + "Large" + ], + "numericValues" : [ + 0, + 1, + 2 + ] + }, + "filled" : { + "type" : "boolean" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "size", + "filled" + ], + "required" : [ + "size", + "filled" + ] + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "numBarrels", + "barrelType" + ], + "required" : [ + "numBarrels", + "barrelType" + ] + }, + "Nums" : { + "type" : "array", + "subType" : "set of", + "items" : { + "type" : "object", + "subType" : "record", + "properties" : { + "number" : { + "originalName" : "num", + "type" : "integer" + } + }, + "additionalProperties" : false, + "required" : [ + "number" + ] + } + }, + "Numz" : { + "type" : "object", + "subType" : "record", + "properties" : { + "nums" : { + "$ref" : "#/definitions/three/Nums" + } + }, + "additionalProperties" : false, + "required" : [ + "nums" + ] + }, + "Rex" : { + "type" : "array", + "subType" : "record of", + "items" : { + "$ref" : "#/definitions/one/Rec" + } + }, + "Stuff" : { + "type" : "array", + "subType" : "record of", + "items" : { + "$ref" : "#/definitions/three/Thing" + } + }, + "Thing" : { + "anyOf" : [ + { + "originalName" : "b", + "type" : "boolean" + }, + { + "originalName" : "i", + "unusedAlias" : "int", + "type" : "integer" + }, + { + "originalName" : "cs", + "unusedAlias" : "str", + "type" : "string", + "subType" : "charstring" + }, + { + "originalName" : "rec", + "type" : "object", + "subType" : "record", + "properties" : { + "num" : { + "type" : "integer" + } + }, + "additionalProperties" : false, + "required" : [ + "num" + ] + } + ] + } + }, + "Zero" : { + "AnyString" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "generalstr" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "generalstr" + ] + }, + { + "type" : "object", + "properties" : { + "numericstr" : { + "type" : "string", + "subType" : "charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "numericstr" + ] + }, + { + "type" : "object", + "properties" : { + "utf8str" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "utf8str" + ] + }, + { + "type" : "object", + "properties" : { + "printablestr" : { + "type" : "string", + "subType" : "charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "printablestr" + ] + }, + { + "type" : "object", + "properties" : { + "universalstr" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "universalstr" + ] + }, + { + "type" : "object", + "properties" : { + "bmpstr" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "bmpstr" + ] + }, + { + "type" : "object", + "properties" : { + "graphicstr" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "graphicstr" + ] + }, + { + "type" : "object", + "properties" : { + "ia5str" : { + "type" : "string", + "subType" : "charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "ia5str" + ] + }, + { + "type" : "object", + "properties" : { + "teletexstr" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "teletexstr" + ] + }, + { + "type" : "object", + "properties" : { + "videotexstr" : { + "type" : "string", + "subType" : "universal charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "videotexstr" + ] + }, + { + "type" : "object", + "properties" : { + "visiblestr" : { + "type" : "string", + "subType" : "charstring" + } + }, + "additionalProperties" : false, + "required" : [ + "visiblestr" + ] + } + ] + }, + "Big_Choice" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "numbers" : { + "type" : "array", + "subType" : "set of", + "items" : { + "$ref" : "#/definitions/Zero/Number" + } + } + }, + "additionalProperties" : false, + "required" : [ + "numbers" + ] + }, + { + "type" : "object", + "properties" : { + "strings" : { + "$ref" : "#/definitions/Zero/ManyStrings" + } + }, + "additionalProperties" : false, + "required" : [ + "strings" + ] + } + ] + }, + "Big_Set" : { + "type" : "object", + "subType" : "set", + "properties" : { + "product" : { + "$ref" : "#/definitions/Zero/SeqProduct" + }, + "numbers" : { + "type" : "array", + "subType" : "set of", + "items" : { + "$ref" : "#/definitions/Zero/Number" + } + }, + "strings" : { + "$ref" : "#/definitions/Zero/ManyStrings" + }, + "color" : { + "enum" : [ + "red", + "blue", + "green", + "yellow" + ], + "numericValues" : [ + 0, + 1, + 2, + 3 + ] + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "product", + "numbers", + "strings", + "color" + ], + "required" : [ + "product", + "numbers", + "strings", + "color" + ] + }, + "ManyStrings" : { + "type" : "array", + "subType" : "record of", + "items" : { + "$ref" : "#/definitions/Zero/AnyString" + } + }, + "NullType" : { + "type" : "null" + }, + "Number" : { + "anyOf" : [ + { + "type" : "object", + "properties" : { + "decimal" : { + "type" : "integer" + } + }, + "additionalProperties" : false, + "required" : [ + "decimal" + ] + }, + { + "type" : "object", + "properties" : { + "binary" : { + "type" : "string", + "subType" : "bitstring", + "pattern" : "^[01]*$" + } + }, + "additionalProperties" : false, + "required" : [ + "binary" + ] + }, + { + "type" : "object", + "properties" : { + "hexadecimal" : { + "type" : "string", + "subType" : "octetstring", + "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" + } + }, + "additionalProperties" : false, + "required" : [ + "hexadecimal" + ] + } + ] + }, + "ObjIdType" : { + "type" : "string", + "subType" : "objid", + "pattern" : "^[0-2][.][1-3]?[0-9]([.][0-9]|([1-9][0-9]+))*$" + }, + "RelObjIdType" : { + "type" : "string", + "subType" : "objid", + "pattern" : "^[0-2][.][1-3]?[0-9]([.][0-9]|([1-9][0-9]+))*$" + }, + "Season" : { + "enum" : [ + "spring", + "summer", + "fall", + "winter" + ], + "numericValues" : [ + 1, + 2, + 3, + 4 + ] + }, + "SelectionType" : { + "type" : "array", + "subType" : "set of", + "items" : { + "$ref" : "#/definitions/Zero/Number" + } + }, + "SeqOfInt" : { + "type" : "array", + "subType" : "record of", + "items" : { + "type" : "integer" + } + }, + "SeqProduct" : { + "type" : "object", + "subType" : "record", + "properties" : { + "name" : { + "type" : "string", + "subType" : "universal charstring" + }, + "price" : { + "anyOf" : [ + { + "type" : "number" + }, + { + "enum" : [ + "not_a_number", + "infinity", + "-infinity" + ] + } + ] + }, + "id" : { + "anyOf" : [ + { + "type" : "null" + }, + { + "type" : "string", + "subType" : "octetstring", + "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$" + } + ], + "omitAsNull" : false + }, + "available" : { + "type" : "boolean" + } + }, + "additionalProperties" : false, + "fieldOrder" : [ + "name", + "price", + "id", + "available" + ], + "required" : [ + "name", + "price", + "available" + ] + } + } + }, + "anyOf" : [ + { + "$ref" : "#/definitions/two/Ints", + "decoding" : { + "prototype" : [ + "fast", + "f_dec_ints", + "os", + "x" + ] + }, + "encoding" : { + "prototype" : [ + "fast", + "f_enc_ints", + "eents", + "octus" + ], + "printing" : "pretty" + } + }, + { + "$ref" : "#/definitions/one/Rec", + "decoding" : { + "prototype" : [ + "convert", + "f_dec_rec", + "octie" + ], + "errorBehavior" : { + "ALL" : "WARNING", + "INVAL_MSG" : "ERROR" + } + }, + "encoding" : { + "prototype" : [ + "convert", + "f_enc_rec", + "x" + ] + } + }, + { + "$ref" : "#/definitions/Zero/Big_Set", + "decoding" : { + "prototype" : [ + "convert", + "f_dec_bigset", + "os" + ] + }, + "encoding" : { + "prototype" : [ + "convert", + "f_enc_bigset", + "x" + ] + } + } + ] +} diff --git a/regression_test/ttcn2json/zero.asn b/regression_test/ttcn2json/zero.asn index 1ab9eec..aaa7e04 100644 --- a/regression_test/ttcn2json/zero.asn +++ b/regression_test/ttcn2json/zero.asn @@ -61,15 +61,20 @@ Big-Choice ::= CHOICE { strings ManyStrings } +Season ::= ENUMERATED { + spring (1), summer (2), fall (3), winter (4) +} + SelectionType ::= numbers < Big-Choice --- non-encodable types NullType ::= NULL ObjIdType ::= OBJECT IDENTIFIER RelObjIdType ::= RELATIVE-OID +-- non-encodable types + EmbPdvType ::= EMBEDDED PDV ExtType ::= EXTERNAL diff --git a/titan_executor_api/doc/Titan_Executor_API_User_Guide.doc b/titan_executor_api/doc/Titan_Executor_API_User_Guide.doc index efa789f6eb597a366d8ddc7b7e0c52e1ced4811e..62c5615b969dfc39c458f69bc1d57249f37923e2 100755 GIT binary patch delta 3929 zcmb`~dr%eE9l-J5@(>UNFE0gy0zyzCazWm{0Hso+Ra0ZEPgJmqBoa`HncxM(Bs0|{ zCfnHjk=8UdmWXoEjkTlLj!{gE4rtY}N>N^xqG{AoXH43O{hoVSwKp--&UEj5?(gi` z-Lv~U=j`6S)%V=1@3}WV;pT4-6!Dkk#mkGE0-6H!c(?Gt%SDpjJ>WP0jvd4%dE zZaZyzD@EenMBa;XZc=fZCXzhTx$YWQ#)xnNsU-RlYl+@OEA7yXBoo#0-$V`#mA02e z_HpFvRU$h$a2^eWaCt!k{}8Df64?@?t~N@YSuJMV(!XxTdHO%yN7&5kb?)oTBZYj{ z&}=A`-;8o@agC~#H`rvJ)NIFfUFG@cVz$#?r?+^H9&29F)9 z6X@lnjn4H-j`#0huNHBa{PkSNk8;iJ&b=OXhq}IV>~E%KMl*eL-7!{AMn7D2He{}= z!Bxw=N`~}F&sXD^Ncvt|kp8~M;7oHT*J$S8TK`~OALg|^*}U=xwJy`++x7Yp&qednS%W_wtZMU0ik>eji=0tZvU-g^z%tq^ zxMaiPp&;WIcM*IaAaS3hsE81}xR{~_2 zbWrF-7kY3Ne?u?+4&T9a2m%p=VBEcNx39DP{F%swRKGIaI0U)DteRgQQs2c94)i1Z^2=C)?15mFD~Nw>8RCn<3?MYN2sk5;H-T) zE+@p%!h`X?lRZ%#s~?PubBxp25#ez%<}u0sN3PvQ?5H*^qMH=Wv{lL~y-ApirA9=2 zw`NmSA(()PFgIsYo{pz612ZuTv#|gRu?UN?6a{!0RoI9Ru@eVz2u(PQf8a}aTSR;; zVv~Usd@&i>$U!mIU?Xg(Mh$+4IyAtJM(o8ooW~V(pc7s2;U{b$eBp;d@JAZbkr8MU z$)s@m`t9pI7ke(AhvU1o=LCgM)an7g?GIOXI4Yf+`oDYZ>i%>Y`2NB34_&1OdCK%) z$;E$2IO|DF@AIo>2(Pah2Jxm9_;(b>|yq)wej9HL%%)$sO1#d<}g*#{f?nB zEMsqIQEJ50=$Hc$L&uFl5>heQh_YVM!p!keW1;$8^|9*D4Be6vug^{n#~{5bxLDsc z%HQZp9OfY}|;*80P6__c9Xm*1H?_?2R7ImDfjWcKz@Ri3zLtoh(KP(s<*_z<8+lq}K+i z2d(plQ|a3Eu(ffq>cOg>nCcEzx275p)%&VzRbQ#=vFk-^*VuY#rVrt~5v1aI{1Wxp zgL7y@J2cMk2lYFjh74q310RjkN!mxVHoLM3#Z#9jD! za3>)dnHZ0yC`Ji>fo*sfN6?Hfa1$YP%s58}=^vDi@d&>EPPKlzG)om~4Zjx)G)v(? z<`vZPkt*v|WeYv`I7;nhtNTk&mp9uM58#&%^*D~R=t7hizc84CXRrycpaFJVL>t=C ziCzRTSizWx$(V^*Sd1zhLKA#^csjx6BNL>Wf*p`D`#wo%}|7yTz)V)00}Bvfbg_j1-ergx;4i zM0!`UiFBgOCvp==A(2j#TB0v;D^dLod5_4gC3Qq@B>9-gjU-J(ZX`KI3?iN)GNq-5 z#D^0jF?aPky{#o-=upae-}T~mt1DQKX&uS?Tz+e&HcsEv8W(R3A5K$}4au+A)N$*u z<|uy=IqI{`tsLgT zqbIkP$}xmef1$x<-DJ${u3M_hNw+vD5(EJ zox~x;TSjb0qc-eu`Ll=K(U}mKOF{LSy4L#Muw8m>4AE^I5uK#~jqo<`!j>-|{ z*>jT044W^<4lb${`#dztfSKa;%g-1Vv delta 3670 zcmb8y3s4p36~OVc_kv(F;FX6#MINFEdJ&KWK|;ldnv^L>)O3tyki^6XC{am`wYlWg zPU0iRZ=C5&>!UMGrZJfoT-xG;ilSiD5i_YxM`Pn7)*2@j-`dP*|7S0&7W>N1{O;NB z+ud*XoPF?7cf(tE!&^Vl6H(n)Btk0ZRnAL^O^G$>p8kC&EEiF=q2espL(ID&v8KxN zeqh~Fk#vv9&y#|iG`?+#3>_S7caPIkL^y#|5qlGt62pnnjKeSzOVs86i5wa$JC})U z;m8+%#ECgDp8;aHyr>775_KSvx)i%4#;bCw0f^-qt+tUEFcH`pluwv<&x({?opCOomsatVX29V;Z8L2o%%? z2XIe&n?-vvEB{v5`?C%b2rh1a#1N5Z=xSLcGPY}*6S%x+R%R13iF$jTWwA&BRsM!5 z>r%z>5nb&%5w8@~avk3r=Wcg);>S&2uWt|gyQ#U+P2X)h_iAYJ-DYqgx2-os=ZOnGB{7!GT$K(Efvn#aFcVD+XCOjg% zM^SlMN$E5*qfeu^q`1T+`qE69FFh>BpPA>+9%Wwj4Y!K;jWR91v)^Xtfp&g$yJcFU z$JthFjph4obiPQWcb*m{b`CB3wSJzk!qNzy4opTlUc>8Hj}6#}P52d>@JAfMpKv?E z>>f1J+mJQbBqywJVtvAMp*qw?J1+6874IIsm9AZA!+z)}Tg>F-I8&C~-!4n8x8mJ_ z!y`qqP>I#pikHpg6n0Hv*OYoIaGRrr?j8t(9?}ydkqJFK8&fe26_^Db@>#r%6YVmv9+ZFrbgfKwQ0W_1wwh zC(m6yr)zh9&mB2%yuG!(b$jDSKWkjmxaO@jjmwwt5tYc8ITV-Mb#8jIj0u1BA?Nmu zmu}rt!!7CU_UQo<6THuEpB~OmN#1$0`GPvVCOtLHcX#lvQ<>*di%fHBigPbB68fi# z|9=$2sl{%4$gpEp{BBZp%c3RG^y5i;5DM-1^wU;AtKfDeu%3o=495s$U?lR8k1;4f zA-;pBF#|L42HwOQ5?hPI1ZnWTi4eo5`_XhipMY>#h8F9RAT`aVl52T zV*@r~6WXy4A7eib;2^HxDz4!=Zr~;o_)~Vh^U*V%XHLTTJ=S@Il|$NW<#+qtrn85$ zA-I{1_3v#Evo|;267!5dE-rZIdW<`*_x0X;Z`SzZOa990 z{S*1a^f-RgsM&4!qg%91=LTQzDD|fXnnPqS}CoDUQe}| zy>NcuD8qb?2l*2`3>DD%(Yr9%h8;M8^Y|JuTt`2|VH_r-7R&Jp-p2=M#P6^b`p2~m zXA#NVpdaGA@}xY$%51DhI}YJ6uHz=+Npu*}QI08?h5%m2X8anT;v#N_n9VgKJnO_9 zt;zSS3$Y)1vBL5tKft2_U0%?2^VXuL!{!Hj&4oq%jAwCKsM9u2E#4a_>p@!BfURi5 z5rl1cQjG=J zfQ{IX1GtJCNaXSdLlc^d;N=Hi8fAyqCRI zQ;6g*ONhOQbwr)KuO#w*$WMv-*ZY@5-Uj)I$lD-|#3-UZ;5?V|B{>ZuCSuCmC8pq% zzn7k`xNEvJxFd&Y(f2#@tSqy(BQ^c2Y5!oWjMbkL4T*og*laoLZ_H@hxuPSu-lsU5 z39fy*BR)cBfm{AkVR=q?P30Hafmb=FruQCE(`z8=>6(d}-Wj5%b&;rPh4MORT0Wwt zl|wpPR?Ml=lu67b#olzPq8F(qZuxtaC#>Q#XM%4p?hLi8 zAKEWpJa0`r{DZU3q`&**Uk5uN(`CGTDtn||a->a;@{l|!yW}A4PiVEWUM@$ZMJAgM zFXu&e8_T|Y`PtBvyzB|1@-mCY`->jQ&GqNx6p!{7WsS@B=RTHOG`ct|C->peS@yD< HKlc0+b2I6x diff --git a/usrguide/Makefile b/usrguide/Makefile index be02514..00c44cc 100644 --- a/usrguide/Makefile +++ b/usrguide/Makefile @@ -12,13 +12,26 @@ include ../Makefile.cfg .SUFFIXES: .tex .labels .dvi .ps .pdf +DOC2PDF_JAR := ../../titan_playground/jar/doc2pdf.jar +WARNING_TXT := warning.txt TITAN_DOCS := apiguide.doc userguide.doc installationguide.doc referenceguide.doc releasenotes.doc - TITAN_PDFS := $(TITAN_DOCS:.doc=.pdf) ifeq ($(GEN_PDF), yes) -install: $(TITAN_PDFS) +# Install with error handling: Tries to create PDFs and copy the available documents to $(DOCDIR). +# On success (PDF files are successfully created), the PDF files are copied to the $(DOCDIR) directory. +# On failure (if doc2pdf.jar is not available or install_pdf exits with error, so PDFs are not created), the DOC files are copied to the $(DOCDIR) directory instead of the PDF files. +install: + { make test_doc2pdf_jar && make install_pdf; } || make install_error_handling + +# Checks if $(DOC2PDF_JAR) is present, and exit with error if not. +test_doc2pdf_jar: + @{ test -f $(DOC2PDF_JAR) && echo "$(DOC2PDF_JAR) is present .. OK"; } || { echo "ERROR: $(DOC2PDF_JAR) is missing" && false; }; + +# Install PDFs normal case: PDFs are created and copied to the $(DOCDIR) directory. +# PDF creation may fail if doc2pdf.jar fails, which can happen for example if the server, that converts from DOC to PDF, is not available. In this case the target exits with error. +install_pdf: $(TITAN_PDFS) ifdef MINGW $(info Skipped ${CURDIR} for MinGW) else @@ -26,12 +39,28 @@ else cp $(TITAN_PDFS) $(DOCDIR) endif +# Copies DOC files to $(DOCDIR) instead of the PDF files, because PDF creation failed. Also a $(WARNING_TXT) is created +install_error_handling: + @echo "Error handling: DOC files are copied to $(DOCDIR) instead of PDF files" +ifdef MINGW +$(info Skipped ${CURDIR} for MinGW) +else + mkdir -p $(DOCDIR) + cp $(TITAN_DOCS) $(DOCDIR) + @echo "Creating $(WARNING_TXT)" + @echo "DOC files are copied to $(DOCDIR) instead of PDF files." >$(WARNING_TXT) + @echo "It is because $(DOC2PDF_JAR) is missing or failed, which can happen for example if the server, that converts from DOC to PDF, is not available." >>$(WARNING_TXT) + cp $(WARNING_TXT) $(DOCDIR) +endif + +# Converts DOC to PDF +# $@ : target name, for example: apiguide.pdf +# $(basename $@) : target name without extension, for example: apiguide %.pdf : %.doc - @for doc in $(TITAN_DOCS:.doc=); do \ - java -jar ../../titan_playground/jar/doc2pdf.jar $(addsuffix .doc, $$doc) $(addsuffix .pdf, $$doc) || exit; \ - done + @java -jar $(DOC2PDF_JAR) $(basename $@).doc $@ || { echo "ERROR: doc2pdf.jar failed with $(basename $@).doc" && false; } else +# GEN_PDF == no install: endif @@ -45,3 +74,4 @@ clean: distclean:clean dep: + diff --git a/usrguide/PRI.doc b/usrguide/PRI.doc new file mode 100644 index 0000000000000000000000000000000000000000..b0e48bf0a226c2435a81cbb3459a2fb80adc7e5d GIT binary patch literal 83456 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 +%C-dwcUK5hL66`@Z6l29iLFWx3tIJ9Z5HJ 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 literal 0 HcmV?d00001 diff --git a/usrguide/apiguide.doc b/usrguide/apiguide.doc index b70d90274337724b9b0e26c81278a91ffe4de781..6d9e0e61f2044c2b981cb6ec4afec09665d603e6 100644 GIT binary patch delta 19845 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 delta 21627 zcmeI4cX(9Q+VZ6-(8%%6aQ;I&OMYp*iKW$RquaO-e+g(d%GiLLZu>_BhE zMg%gJHjJ@DqS4`ug(C?^DjxQ<@M*?Aie~KRX^d@D7+W!$v5P3*bE?E-=z1X)kH3>P z5KY{gCb9J>xqODiwxOT}6-+_*LaS{nw$;R@?h(DMCt4N{dpdQGZrfAKRO>yTIu?6J zb*J9(6wxOPR1D~FhTcKbJ0Wtf~^C z9cP~n8rp!lwCly*=nWEQjZyhVZwghhVp1ElC`QwhJ?fLIjli1ie#zs$)SguRA z^3cm#u){IxB&1@R#p4s`P9WNSU)Sx31c{CE)9u$7^I@+{;UWHNs2D+JzFlQ2iYI$4 zL@#%tf|sm}nL@A--p7IraK`ptIb&!189T9su?;F_uU9rdWks?ODh{@l2GBM0*2?`3bS7y}1V7(d^S=pR9$zC0mPwoxT+7bHUDXDb`gkzEtb!;6}mrR#Wv>P1dX+XR~S6W+C=i znUm72TSJ^xr&}!{$&O~zg)iJ*nOO`jxrNC;d)$!Wk6Y)2)N=^U)|i^kN;0fDH5)p7 z8P?HGpE1e$PR%%bh>b~l|B_u+huLVfUaRRC9<17-j;f6&YhI|MYFMtmWb3=3(e`GI z$<`gAbyF()ZnQ1YlorYUU9-A-pGjj%WnawBm1;JoT8*`0?BO(4hBJlF-6coc*0R}{ zW}R58siW02K4+60UqdW&voT!+EY+XS=`ST%)vzFkD%~0v<{XpRS`e1*@R^A(!&)9@ zKU2)c3~Sr)y7u6iZ0j=>W8!s2NwL;O;f@AONkV9^(qyzg8Qx5(3&1v}j`}O3 zM-*w+fsq{@iZs0kM3HX27@6%*q*p4eb89#jw8?Dk5|!!bquF{h$~pE7>((g8^q4YS zeaT7Iu;`Zda!wO|Wp#?r(7iE?`KeOaU^ZqB3m+_eNrlD2AMBpTqI`ymO~E}MT0dJ! z9(+_@>r*Yrs(p4;E-_dt8;T4YT*nw(S$UU2A65be6k^-gyU-w`sxE}ty7-~l=GQyt z=y)?d*Gp&Y9e0j~#kh2VFRYNG+IS3CZ);6DZ7WD0vZL+Ffj&4b-?umim8wp09hW|= znyvqOSZ`(0ru0&gdajpY=^cExmA#ZjpGNOJWUT6_+vDSy?7x^;y;F7cMro(CKhDaL zQeCo|{Mx#YnJ1l-BSO8b1pe4LxpqsBY4Gfv$J}Ll6w+sfG51*LA)BpFgl!JByXWNU zlE0${9(cjoy;zq4a`Oc_-r~^NPYS)piS6u@@V`3;b@Ve)p9H2i>e5H;w+nKNWIxSZ z!7vZ^Yj&sC($WrM6bzU#Ui@qas6qxIG*C+jOY)Gch@x~QsNlZg-~P^T(pw548!BOIuIOQp(EW~f^im7D{B^0?y5CXCwRit(C)Co;RdtG)I^w>&5Ok`=wCX>| zvfE|lrP8X3>QON0e#dz9D7@D7uS-?e{f<(uQ3&=t?SA~9pLRcr3uYB7=9g}^-a2}t zk72x?>$0uTP2rC+TFP~yd*5cv6Z9fps&rk9wq`s}$;KYNca55JWor+v%OO%b54ApD zS9{Q2>tlUf&voe-?|f5^$Rp?G(C$@D>fh+S=Vepx&&@|^f2tbOO_vStKS#Q2ud2GL zw|e$5+NvIf9(t}z6zGgwzUoPfdGG9h>m?>L{UegGm0%y(AIY?!TXKp-Z&UL7{Pjo= z;*HY3+TUDbX}bY%xjgTvkRuv;tRrvR-L$(EGVsyvR`|ZLMK-1K*H#<)`etWkmGR$J z8_Io(@{0JTHHN1AUuz7_l$6Azj6_p1kNDV-AZ2Me9~-tycq^^${Bpy|OtI#|2e0xu z%`(*~k@h<)l8b$rp&PiNVl3WgsL@x#y%!WbV4WcrY^4M0QC2s8#=KrtxcS2r3WEvxpQ+J9;-o|m86vi}sfnIdbyepG3TJ6jsH zvKI%65aG0Ui?w}H-1J?CyzE6EV8PN1A8Zh>jo^ zRc9_*X$WVFF(I3Ped5Fo&U7<~3t*X484hA>^C zVB((F2s3lZb%{;;0M8b^T68nl1$x%v$aCpgve#8zRqoZ* zioBsbuD)M2-nT#r)V9|1Yr8^R!T&tq_f&VOKOYpQ^fC0`EwgC8H%>_in}z?d&H-E7L7RexXqrTeodN`K8*8CeNoqWTvb=qFGh#gS)ZF`G0q>0kqmyepR`f8sy zSC;xq{k133ls|m?h<|+V11G^5@GGc|f1@@8jX@7E5_||wg7e@@AfX#RpfNCk6wn*= z1^vNv@DAUZsU*v9G3~cZrMD#g#!K5Mv+E~g=dxdYZMzs#Sq>Y?MzFE$3ET4+9^Y2U z32_&u@`G)a7(S=1(!|4;CVZYn(s}K6O1~htns}d5C5pe_PHFB@PX@o*PH9XEh|B2J zj!H~S3jY0FgY{!&=!`myl9z{zEl^E^I_DVI$!xdkKZj|RJzC1Wv z3Gj61VYK<#N?;Az*6ci`HlLKOO!6$z#a>~P93{Z5*v<|p);C89B!kB2n3+$^aSNWv z&fq6=l*VqgT<)mUuA5eMB$$yIc~-8H=T>fXTP2hywNwF??HB3>;9q!)`c7HH{_pzuk{AG)p;y)VpNH9v< zZBfrjkw4=2d&b)T0IuQq2Dpx6UOq)_z)$p3;A~m5MOg*B@$%|;%iB) zB%(A{`fTm{F%yv{6Dx&Ssj!@9MH=y?6U$7L8N}DhZi)8&SSFFSwmWUUHpFU6lmX4cBEG{;OYDC~i1et_3Ewed9Vf~Y#CMWdr-<@2@ttw8u>YMU(l1<`e(W5v&J*PY z;`={@0i|o9NEUi%C=BYeswt#Mhiy ziLgQ)QELH9c33SdefU(AxXLFHsgX!c#FtF06rxPs7o=Snt5o<(1GK}>D;)xmhQ6w_ z^7HvPoG`}sXZlbXFLh%n3t@^+u55sNi3^KV$;BM zus~b9T3IXelC_A$#I?!^AFbO4)x?g$8m$y5hL<>8X2i;dx?tesym3(>sBX}RZ%>hM~eE8BM zN(cV#5#^ZB7K+^7;we~^s>MIOr1a-Yjw!o@8O-C4C{6gtBT55)^tf_}Z@8q_t_ocb ze)P05icdd@JUE^d#YXWrPAcKTY-H;dfBvEpAdUj`no(7-UhLp$WxVJ?O`EBWJfobD z+@Dh<(X$hxd=tL*loH7MT~q@7WA(8!AHMOT@~6o26Sc1w)#dArHT@ckV$5abIX^?g zN`*!{7|K2(EyHx)MtUgX1MO46MhZ{S^FyFY*1JfKTJqNR(JpkPOm6LJNs?00m$m z7zCz+8DKq_-BMy!@G)2ic7r|OEVuw}gWrLYBr$)`8}tX8!5;7{h{l)oYJ)N(F1h`2 zFc>@!CW52j3((pmu@X=QhJg{_FgOP;gLJdRGQkaS3*=`=tTTvgg$M!@NC9aeA9Msg zKp!vwya*;)@H7j|0Y8DCK~5$r0*k;uz*%q!`~-dm*{vnk39JMAz(H^UTm)flaP0ui zfVsWI+5w*|L<4LF+d$21L;!pXEI;7MCkLOT0^uMMGzE#E0CWP6f!?4TYy^f}i3Njx zU>M+F2`C2}flr>q0>Cq18khkVfJNXO_!is%$MZ4&XY#So3M951dm#TX_;rz3 zHE^pKb6J985C8%}9S{$aKq|-prQlKUBp3|#fkPmstHc_CsbDtP3ig0AT`~XXanPg` za|SqA4c3C4;4|P~hRA?AVBV7wTMCwem0%Unz-Dk9y!RB&2oO6Mmuk=&pFIqa@Y}EVAI~eefH20L-H$)*h6BUSJw{19W;uVqL&I@HRLFz5u~v@SRzZ3ktv+ zU@kZejsyR(5~~41$72xS4KNRs0}WWhpOaV=nExVr1MYx_pxXq@IT$nv;RIK}_rMns zs}2f4Cva$r#7=?{uSje(_yybrF|T4Ff`jpIKEez*SPU+Me}V?(xR!uY@EAC{ z0d<4Mo3Xe-HYnVT5uC!odGOe$66*^tfp5Uo?Gn2N{@jaiiSNU?3^Kt}U<4R+5L+>@ zf_dP;Q8WUQPCyGnPhrh~uya@s;69MgW9~sZ=yd_@S@6{2B33ZS{Tg!&ios*x2`~~2 zx{MHlZ@@L+e+BanI)f5W_#KYHPOt~m{Sm7jib{Pjh$uheG0)1sx6HHWOHWfUj%4`^@0PXx`mR?O}nczls zncV^v;5O(|11|)?SnwjK6(X|;&^=6My+BB~%))>cDYI?hb_`xjfaq9@%;IBZwxq7i zJ_MH<$?OVv0K`WQQbC5Gnao;)q6C?h0iQ&f`GaO42|NRy16J@3*a~(7wFL$R+JGFe z5G)6$zgd>3@m}EG7ANL!Q)^hC$$RgP*}2(6W`xia`nJ z4&DKa!6vW`JODnK=m>}hPl4g!WiSIA1E;}tPyv!# z)CT>*6JREI6PyKK0;w%tVS>(}6ifgwf&JhJxDD=tHtl4V4OW73Ahkz1U;<{Kf$iX1 zaLt0Jh%7V=azP<@7EA=o!ABr3TV@@>om^Cwhsb~w&oy#zgglK`uU?o@uHUn|AUF!Hg9;!%9Tf%AKr7G#OagPjd{7QHf|KAJXgM2G z1loWcPy|ZA={cAl@IAN&{48@3axfY^3#@>H?O+cGeG?6XI-ouHkrIlY-LVR#{ zwBx$+EZ_bU?lJH*fgioD%n?UL;>jFkz})^!s( zs9?CTkPdxcUM`1pRtUI+J&!GBy^ zc1Kw$)hT!n=NYhqd0-3J3e@*8hwt+>zbG>-Ggo6?fCkQiJKzssT7%nLFb0eT{{RQU zHEr zN^9N*Z}F7)iuZxQe=XI%zOPg-2ot~W;0y3;RO~w-9z*zpJhd0^ldqcjJNat!pgrA( zuulVqvKvi@vxVJ<^NaavPoB|1jcXhm_YoUcu#!#oTg_&Keaa4Z-pVe;?ZIbM_puQn z``E_D2iURrgM4NOwX}iHWC>RiaW&D~k(h1^%bv$CcTf`_5uf2b!B{YBj~_3>SH*+^ zX%9)alf+xaupgIo8#fv@dz+7Le_LrEvDsSB0ySLnyZUf7Ywxd(>!|)BS8s5*>9pIe znmwto6WW*}^$STd@xsn({TgaPG3sLKt%pI9s=d%z^^<}WmWR)+7O-rVg}*ZXVHfq} z{H|(}beY~BCvI5&T z)6z@Pxhy`oR5i=#j4v-$8#lZ1QDALI+5>iFUEKMK?IM^sJ{Hq!4!)fuj(_N9!H-*M zzm%#q0`axAfcXQ}v(gOy#Xxn1l)@(tQZp@QBlR)lJ&}sB zJ&jb1?RlhPY}1j7u`NR?#rb-#SrorGsRXAfB&F^_p7+qo-&5Oo*_QPm9E%ca1 z^Mzg&&X`8?8(tO8m`3x~@gLJBX)(`Hz8|IP?O09(tCp1G%yRRLToeQo~3YoNHKo05$7?>R4-sD>-pb?_}{#^WZcSFmfuZknVn3^q4Gv8JFINC3@&_#w>} zNLzv=U<4+R3{rsb^E0#5xRAE6+JW{U3uN<(S!zPqBRK2~giwH&MeM=c(Oc)w!N=C) zPU*kRSgehkqxwklzh37r%vJA7iG19fs>P5BZ8`trO?6m@{`Y6te#O!K*Br$-FR-uh z+T{W}%J$$TMhA8boBwCn`p>Ylun)5X*jI{J53q}`vZ@(DZk1`jSk*y>2H9!Z8QB?m n>4`~c$vKHB=4^AK*_fN0n3`kC&NAkja??$D+6(Wfugd=icfw#} diff --git a/usrguide/installationguide.doc b/usrguide/installationguide.doc index f199061fb04c7cc41cd4a6ee2de78afc59154334..d530d55c31271dabbe32808e08cdfc5737fad0cb 100644 GIT binary patch delta 13338 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 delta 12912 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

k4b(&nv_u<3 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 E1%x$ZV*mgE delta 197941 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

maOXeo`>t!p=};3F@; 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®-?VkvS^?eF66 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 EH?rI)UH||9 diff --git a/usrguide/releasenotes.doc b/usrguide/releasenotes.doc index 6c6bbe792a2814057c443484bacef348924447f1..b9c5b49bcaf02c1f4c612b5cadf5d8d2506adab0 100644 GIT binary patch delta 109346 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 ANB{r; diff --git a/usrguide/userguide.doc b/usrguide/userguide.doc index a31a339b25655fee18a81f70e7e97a58270f2d4f..da7dd72a28d15a2719d0a32bc9680a8633b60cb2 100644 GIT binary patch delta 10915 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 MsYAX05`Wb4e?ay<9RL6T delta 11260 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 -- 2.34.1