Sync with 5.2.0
authorerititan <elemer.lelik@ericsson.com>
Mon, 16 Mar 2015 09:45:12 +0000 (10:45 +0100)
committererititan <elemer.lelik@ericsson.com>
Mon, 16 Mar 2015 09:45:12 +0000 (10:45 +0100)
140 files changed:
Install/.gitignore
README.cygwin
README.linux
README.md
README.md~ [new file with mode: 0644]
README.mingw [new file with mode: 0644]
common/config_preproc_la.l
common/version.h
compiler2/AST.cc
compiler2/AST.hh
compiler2/CompilerError.cc
compiler2/Makefile
compiler2/ProjectGenHelper.cc [new file with mode: 0644]
compiler2/ProjectGenHelper.hh [new file with mode: 0644]
compiler2/Setting.cc
compiler2/Setting.hh
compiler2/Type.cc
compiler2/Type.hh
compiler2/Type_chk.cc
compiler2/Type_codegen.cc
compiler2/Value.cc
compiler2/Value.hh
compiler2/asn1/AST_asn1.cc
compiler2/asn1/AST_asn1.hh
compiler2/asn1/Ref.cc
compiler2/compiler.1
compiler2/encdec.c
compiler2/enum.c
compiler2/main.cc
compiler2/main.hh
compiler2/makefile.c
compiler2/record.c
compiler2/record_of.c
compiler2/subtype.cc
compiler2/subtype.hh
compiler2/subtypestuff.cc
compiler2/subtypestuff.hh
compiler2/ttcn3/AST_ttcn3.cc
compiler2/ttcn3/AST_ttcn3.hh
compiler2/ttcn3/Statement.cc
compiler2/ttcn3/Statement.hh
compiler2/ttcn3/Ttcn2Json.cc
compiler2/ttcn3/TtcnTemplate.cc
compiler2/ttcn3/compiler.c
compiler2/union.c
compiler2/xpather.cc
compiler2/xpather.h
core/ASN_Any.cc
core/ASN_CharacterString.cc
core/ASN_CharacterString.hh
core/ASN_EmbeddedPDV.cc
core/ASN_EmbeddedPDV.hh
core/ASN_External.cc
core/ASN_External.hh
core/ASN_Null.cc
core/ASN_Null.hh
core/Array.hh
core/Basetype.cc
core/Basetype.hh
core/Bitstring.cc
core/Bitstring.hh
core/Boolean.cc
core/Boolean.hh
core/Charstring.cc
core/Charstring.hh
core/Float.cc
core/Float.hh
core/Hexstring.cc
core/Hexstring.hh
core/Integer.cc
core/Integer.hh
core/JSON.cc
core/JSON.hh
core/Makefile
core/Objid.cc
core/Objid.hh
core/Octetstring.cc
core/Octetstring.hh
core/Optional.hh
core/Profiler.cc [new file with mode: 0644]
core/Profiler.hh [new file with mode: 0644]
core/Template.hh
core/Universal_charstring.cc
core/Universal_charstring.hh
core/Verdicttype.cc
core/Verdicttype.hh
core/XER.hh
core/config_process.l
core/config_process.y
core2/Basetype2.cc
doc/License_handling_in_TITAN.doc
etc/Makefile
etc/scripts/ttcn3_archive.pl [new file with mode: 0644]
etc/xsd/TPD.xsd
function_test/Semantic_Analyser/TTCN3_SA_13_TD.script
function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script
function_test/doc/TTCN3_Executor_TestReport.doc
mctr2/cli/config_read.l
mctr2/cli/config_read.y
regression_test/XML/EXER-whitepaper/EmbedValues.ttcnpp
regression_test/XML/Makefile
regression_test/XML/tpdValidTest/Makefile [new file with mode: 0644]
regression_test/XML/tpdValidTest/tpdValidTest.sh [new file with mode: 0755]
regression_test/compileonly/HT48786/Makefile [new file with mode: 0644]
regression_test/compileonly/HT48786/Test1.ttcn [new file with mode: 0644]
regression_test/compileonly/HT48786/Test2.ttcn [new file with mode: 0644]
regression_test/compileonly/Makefile
regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/Makefile
regression_test/compileonly/mfgen-tpd/library/Makefile
regression_test/json/Functions.ttcn
regression_test/json/JsonData.asn
regression_test/json/Testcases.ttcn
regression_test/json/Types.ttcn
regression_test/recofOper/Makefile
regression_test/recofOper/config.cfg
regression_test/recofOper/config_rt2.cfg [new file with mode: 0644]
regression_test/ttcn2json/CompareSchemas.ttcn [new file with mode: 0644]
regression_test/ttcn2json/General_Types_e.json
regression_test/ttcn2json/Main.ttcn [new file with mode: 0644]
regression_test/ttcn2json/Main_e.json [new file with mode: 0644]
regression_test/ttcn2json/Makefile
regression_test/ttcn2json/MiniRanap.asn [new file with mode: 0644]
regression_test/ttcn2json/MiniRanap_e.json [new file with mode: 0644]
regression_test/ttcn2json/PDU_Definitions.asn [new file with mode: 0644]
regression_test/ttcn2json/Testcases.ttcn
regression_test/ttcn2json/f_ext_import_schema.cc [new file with mode: 0644]
regression_test/ttcn2json/f_ext_import_schema.hh [new file with mode: 0644]
regression_test/ttcn2json/one_e.json
regression_test/ttcn2json/three_e.json [new file with mode: 0644]
regression_test/ttcn2json/two.ttcn
regression_test/ttcn2json/two_e.json [new file with mode: 0644]
regression_test/ttcn2json/zero.asn
titan_executor_api/doc/Titan_Executor_API_User_Guide.doc
usrguide/Makefile
usrguide/PRI.doc [new file with mode: 0644]
usrguide/apiguide.doc
usrguide/installationguide.doc
usrguide/referenceguide.doc
usrguide/releasenotes.doc
usrguide/userguide.doc

index 24600083db41748be192c1a6cc2b90e6ba21c012..3d758890d349a004d946898e11906fe95d43b2d8 100644 (file)
@@ -1 +1 @@
-!Makefile
+!Makefile
\ No newline at end of file
index 43be04ac3fe9f84dfecd2506d358f48d1fd2e3fb..4b683ee49b5c1eb88afab35c6cc2ed58fca85121 100644 (file)
@@ -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\r
     - If Cygwin is installed already, refresh your Cygwin installation\r
       Titan is always build for the newest Cygwin version available. \r
index 06666777f7d4f048ddb88964bbab25d3e5c04684..9becb31bc6742292cde535606890c48258003eda 100644 (file)
-Build and install Titan on Linux\r
-\r
-1.Install required libraries: \r
-(examples are given for Ubuntu 12.04/14.04; for other Linuxes, pls. use the relevant library installation method)\r
-\r
-sudo apt-get install g++ expect libssl-dev libxml2-dev libncurses5-dev flex bison\r
-xutils-dev is needed by makedepend:\r
-sudo apt-get install xutils-dev\r
-The following packages may be needed for titan_eclipse/automatic_build:\r
-sudo apt-get install ant xsltproc\r
-\r
-2.Clone the titan directory from git  into /home/<user_id>/titan\r
-\r
-git clone https://github.com/eclipse/titan.core  titan\r
-\r
-3. Configure the build \r
-\r
-cd titan\r
-check  that MakefileFOSS.cfg is present   and  has the following content:\r
-cat MakefileFOSS.cfg\r
-\r
-# Configurations for the Free Open Source Software version\r
-LICENSING := no\r
-USAGE_STATS := no\r
-\r
-\r
-Several build options are possible; for details on options , please read through the Makefile.cfg.\r
-Options can be overridden by the content of  a file named Makefile.personal which can be used to \r
-adapt to local installation directories, change config options etc.\r
-Below, a small number of typical scenarios are presented.\r
-\r
-1) JNI  disabled\r
-\r
-The JNI interface is used by the Eclipse Titan Executor or by the Java Executor API.\r
-If you don't need them , Titan can be compiled without JNI. \r
-\r
-Create ~/titan/Makefile.personal to override settings in Makefile.cfg with the following content:\r
-(replace paths with values relevant to your installation)\r
-\r
-TTCN3_DIR := /home/<user id>/titan/Install\r
-OPENSSL_DIR := /usr\r
-#JDKDIR := /usr/lib/jvm/java-7-openjdk-amd64\r
-XMLDIR := /usr\r
-JNI := no\r
-GEN_PDF := no\r
-\r
-\r
-\r
-\r
-2) JNI  enabled\r
-\r
-install JDK   into /home/<user id>/jdk\r
-\r
-Create ~/titan/Makefile.personal to override settings in Makefile.cfg with the following content:\r
-(replace paths with values relevant to your installation)\r
-\r
-TTCN3_DIR := /home/<user id>/titan/Install\r
-OPENSSL_DIR := /usr\r
-JDKDIR := /usr/lib/jvm/java-7-openjdk-amd64\r
-XMLDIR := /usr\r
-JNI := yes\r
-GEN_PDF := no\r
-\r
-\r
-\r
-3. Run make\r
-\r
-make\r
-\r
-4. Run make install\r
-\r
-make install\r
-\r
-This will install Titan into  /home/<user id>/titan/Install\r
-\r
-5. Optionally , run function/regression tests\r
-\r
-set environment variable TTCN3_DIR to /home/<user id>/titan/Install\r
-\r
-(setenv  TTCN3_DIR /home/<user id>/titan/Install  for csh,\r
-export TTCN3_DIR=/home/<user id>/titan/Install for bash )\r
-\r
-\r
-\r
-cd /home/<user id>/titan/function_test\r
-\r
-in the following Makefiles \r
-\r
-XER_EncDec/Makefile\r
-Text_EncDec/Makefile\r
-RAW_EncDec/Makefile\r
-\r
-edit the value of XMLDIR to match your installation values \r
-\r
-run the tests\r
-\r
-make\r
-\r
-( or make |& tee outputfile if you want to save the output for verification)\r
-\r
-cd /home/<user id>/titan/regression_test\r
-make run\r
-\r
-( or make run |& tee outputfile if you want to save the output for verification)\r
-\r
-These tests might run for half an hour (regr.tests)  to two hours (func.tests)\r
-\r
-6. Optionally , copy Titan into its' final directory.\r
-From here on, you can continue with the Titan installation guide, see /Install/docs, to set environment variables etc.\r
-\r
-\r
-\r
-\r
+******************************************************************************
+* 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/<user_id>/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/<user id>/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/<user id>/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/<user id>/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/<user id>/titan/Install
+
+5. Optionally , run function/regression tests
+
+set environment variable TTCN3_DIR to /home/<user id>/titan/Install
+
+(setenv  TTCN3_DIR /home/<user id>/titan/Install  for csh,
+export TTCN3_DIR=/home/<user id>/titan/Install for bash )
+
+
+
+cd /home/<user id>/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/<user id>/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.
+
index b920dec58200d1a825f19b342069ba5a05da4d99..8dfedb8a213f720682baefd338fbb5e3777bf17e 100644 (file)
--- 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 (file)
index 0000000..b920dec
--- /dev/null
@@ -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 (file)
index 0000000..6169d87
--- /dev/null
@@ -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 <Install folder>\msys\<version>\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.
index 316b6349fb6336dbdf3fd58aff6f9ffbfd62babb..1699f33a9dc61072b509faf887f895a4ca0257e1 100644 (file)
@@ -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);
index b6472c04e4e6fc0acacdb2b8e0a03fb8adb4f48f..a72a783c64b5e61a883c64e0f78016b29ae0837f 100644 (file)
@@ -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)
index 3f45141d064e8cd8cfe8b9fb0ceaba396eed3413..4cfcad260ae88a849d24f460d1d723f72b87bd29 100644 (file)
@@ -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<Type*, JSON_Tokenizer>& 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<Type*, JSON_Tokenizer>& 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);
index 693559ca6305b8de0d696063816298dc4782f545..ddb99c27437d7be6d91f9e5709e01756a4ca3069 100644 (file)
@@ -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<Type*, JSON_Tokenizer>& 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<Type*, JSON_Tokenizer>& 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<Type*, JSON_Tokenizer>&) = 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<Type*, JSON_Tokenizer>& json_refs) = 0;
   };
 
   /**
index 88b5accf5bff45ad9a9ab62a8d7b9854fe2b4607..2b438fa90a10c07f3624888d972c89a9e76418c1 100644 (file)
@@ -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);
     }
   }
 
index e5a18337659d4b80f0d7dd52ea6fc77e065d269e..61ef64fc5780c5d5b58db7e210768b0a52b718b2 100644 (file)
@@ -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 (file)
index 0000000..991449e
--- /dev/null
@@ -0,0 +1,744 @@
+///////////////////////////////////////////////////////////////////////////////\r
+// Copyright (c) 2000-2014 Ericsson Telecom AB\r
+// All rights reserved. This program and the accompanying materials\r
+// are made available under the terms of the Eclipse Public License v1.0\r
+// which accompanies this distribution, and is available at\r
+// http://www.eclipse.org/legal/epl-v10.html\r
+///////////////////////////////////////////////////////////////////////////////\r
+#include "ProjectGenHelper.hh"\r
+#include "../common/memory.h"\r
+\r
+#include "error.h"\r
+#include <limits>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+const std::string ProjectDescriptor::emptyString = std::string();\r
+\r
+ProjectDescriptor::ProjectDescriptor(const char * name) :\r
+  projectName(std::string(name)),\r
+  tpdFileName(),\r
+  targetExecutableName(),\r
+  projectAbsTpdDir(),\r
+  projectAbsWorkingDir(),\r
+  projectWorkingDir(),\r
+  library(false),\r
+  dynamicLinked(false),\r
+  referencedProjects(),\r
+  refProjWorkingDirs(),\r
+  libSearchPaths(),\r
+  linkerLibraries(),\r
+  ttcn3ModuleNames(),\r
+  asn1ModuleNames(),\r
+  userSources(),\r
+  userHeaders(),\r
+  ttcnPP(),\r
+  initialized(false)\r
+{}\r
+\r
+void ProjectDescriptor::cleanUp()\r
+{\r
+  referencedProjects.clear();\r
+  refProjWorkingDirs.clear(),\r
+  libSearchPaths.clear();\r
+  linkerLibraries.clear();\r
+  ttcn3ModuleNames.clear();\r
+  asn1ModuleNames.clear();\r
+  userSources.clear();\r
+  userHeaders.clear();\r
+  ttcnPP.clear();\r
+}\r
+\r
+bool ProjectDescriptor::isInitialized()\r
+{\r
+  if (!projectName.empty() &&\r
+      !targetExecutableName.empty() &&\r
+      !projectAbsTpdDir.empty() &&\r
+      !projectAbsWorkingDir.empty() &&\r
+      !projectWorkingDir.empty())\r
+    initialized = true;\r
+  return initialized;\r
+}\r
+\r
+void ProjectDescriptor::setTPDFileName(const char* name)\r
+{\r
+  const char SEPARATOR = '/';\r
+  std::string fileName(name);\r
+  size_t refProjPos = fileName.find_last_of(SEPARATOR);\r
+  if (std::string::npos == refProjPos) {\r
+    tpdFileName = fileName;\r
+  }\r
+  else {\r
+    tpdFileName = fileName.substr(refProjPos + 1);\r
+  }\r
+}\r
+\r
+void ProjectDescriptor::setProjectAbsWorkingDir(const char* name)\r
+{\r
+  if (!name) {\r
+    ERROR("No path was given to the working directory. Check if 'r' flag is set ");\r
+    return;\r
+  }\r
+  projectAbsWorkingDir = std::string(name);\r
+  ProjectGenHelper::Instance().setRootDirOS(name);\r
+}\r
+\r
+void ProjectDescriptor::addToReferencedProjects(const char* refProjName)\r
+{\r
+  std::vector<std::string>::iterator it;\r
+  for (it = referencedProjects.begin(); it != referencedProjects.end(); ++it) {\r
+    if (*it  == std::string(refProjName)) return;\r
+  }\r
+  referencedProjects.push_back(std::string(refProjName));\r
+}\r
+\r
+void ProjectDescriptor::addToRefProjWorkingDirs(const std::string& subProjDir)\r
+{\r
+  std::vector<std::string>::iterator it;\r
+  for (it = refProjWorkingDirs.begin(); it != refProjWorkingDirs.end(); ++it) {\r
+    if (*it  == subProjDir) return;\r
+  }\r
+  refProjWorkingDirs.push_back(subProjDir);\r
+}\r
+\r
+bool ProjectDescriptor::hasLinkerLibTo(const std::string& refProjName) const\r
+{\r
+  ProjectDescriptor* refProj = ProjectGenHelper::Instance().getTargetOfProject(refProjName.c_str());\r
+  for (size_t i = 0; i < referencedProjects.size(); ++i){\r
+    if (refProj && refProj->library) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool ProjectDescriptor::hasLinkerLib(const char* libName) const\r
+{\r
+  std::string linkerLibName(libName);\r
+  std::vector<std::string>::const_iterator it;\r
+  for (it = linkerLibraries.begin(); it != linkerLibraries.end(); ++it) {\r
+    if (*it  == linkerLibName) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+void ProjectDescriptor::addToLibSearchPaths(const char* libSearchPath)\r
+{\r
+  std::string searchPath(libSearchPath);\r
+  std::vector<std::string>::iterator it;\r
+  for (it = libSearchPaths.begin(); it != libSearchPaths.end(); ++it) {\r
+    if (*it  == searchPath) return;\r
+  }\r
+  libSearchPaths.push_back(libSearchPath);\r
+}\r
+\r
+void ProjectDescriptor::addToLinkerLibs(const char* linkerLibs)\r
+{\r
+  std::string llibs(linkerLibs);\r
+  std::vector<std::string>::iterator it;\r
+  for (it = linkerLibraries.begin(); it != linkerLibraries.end(); ++it) {\r
+    if (*it  == llibs) return;\r
+  }\r
+  linkerLibraries.push_back(linkerLibs);\r
+}\r
+\r
+size_t ProjectDescriptor::getLibSearchPathIndex(const std::string& subProjName) const\r
+{\r
+\r
+  for (size_t i = 0; i < libSearchPaths.size(); ++i) {\r
+    if (std::string::npos != libSearchPaths[i].find(subProjName))\r
+      return i;\r
+  }\r
+  return std::numeric_limits<unsigned int>::max();\r
+}\r
+\r
+const char* ProjectDescriptor::getLibSearchPath(const std::string& subProjName) const\r
+{\r
+  for (size_t i = 0; i < libSearchPaths.size(); ++i) {\r
+    if (std::string::npos != libSearchPaths[i].find(subProjName))\r
+      return libSearchPaths[i].c_str();\r
+  }\r
+  return NULL;\r
+}\r
+\r
+bool ProjectDescriptor::hasTtcn3ModuleName(const char* moduleName) const\r
+{\r
+  std::string modName(moduleName);\r
+  std::vector<std::string>::const_iterator it;\r
+  for (it = ttcn3ModuleNames.begin(); it != ttcn3ModuleNames.end(); ++it) {\r
+    if (*it == modName) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool ProjectDescriptor::hasAsn1ModuleName(const char* moduleName) const\r
+{\r
+  std::string modName(moduleName);\r
+  std::vector<std::string>::const_iterator it;\r
+  for (it = asn1ModuleNames.begin(); it != asn1ModuleNames.end(); ++it) {\r
+    if (*it == modName) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool ProjectDescriptor::hasUserSource(const char* userSourceName) const\r
+{\r
+  std::string sourceName(userSourceName);\r
+  std::vector<std::string>::const_iterator it;\r
+  for (it = userSources.begin(); it != userSources.end(); ++it) {\r
+    if (*it == sourceName) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool ProjectDescriptor::hasUserHeader(const char* userHeaderName) const\r
+{\r
+  std::string headerName(userHeaderName);\r
+  std::vector<std::string>::const_iterator it;\r
+  for (it = userHeaders.begin(); it != userHeaders.end(); ++it) {\r
+    if (*it == headerName) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool ProjectDescriptor::hasTtcn3PP(const char* ttcnPPName) const\r
+{\r
+  std::string ttcnPPFile(ttcnPPName);\r
+  std::vector<std::string>::const_iterator it;\r
+  for (it = ttcnPP.begin(); it != ttcnPP.end(); ++it) {\r
+    if (*it == ttcnPPFile) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+std::string ProjectDescriptor::setRelativePathTo(const std::string& absPathTo)\r
+{\r
+  if (projectAbsWorkingDir.empty()) return std::string();\r
+  const char SEPARATOR = '/';\r
+  if (projectAbsWorkingDir.at(0) != SEPARATOR || absPathTo.at(0) != SEPARATOR) \r
+    ERROR("Expecting absolute path to generate LinkerLibSearchPath ");\r
+  size_t length = projectAbsWorkingDir.size() > absPathTo.size() ? absPathTo.size() : projectAbsWorkingDir.size();\r
+  size_t lastSlash = 0;\r
+  size_t i;\r
+  for(i = 0; i < length && projectAbsWorkingDir.at(i) == absPathTo.at(i); ++i) {\r
+    if (projectAbsWorkingDir.at(i) == SEPARATOR && absPathTo.at(i) == SEPARATOR) {\r
+      lastSlash = i; // the same path until now...\r
+    }\r
+  }\r
+  if (length == i) {  // got subdirectory\r
+    if (projectAbsWorkingDir == absPathTo) {\r
+      return std::string("."); // the same pathes were given \r
+    }\r
+    else if ((projectAbsWorkingDir.size() > absPathTo.size() && projectAbsWorkingDir.at(length) == SEPARATOR) ||\r
+       (projectAbsWorkingDir.size() < absPathTo.size() && absPathTo.at(length) == SEPARATOR))\r
+      lastSlash = length;\r
+  }\r
+\r
+  size_t slashCount = 0;\r
+  for (size_t i = lastSlash; i < projectAbsWorkingDir.size(); ++i) {\r
+    if (projectAbsWorkingDir.at(i) == SEPARATOR)\r
+      ++slashCount;\r
+  }\r
+\r
+  std::string relPath;\r
+  const std::string upDir("../");\r
+  for (size_t i = 0; i < slashCount; ++i)\r
+    relPath.append(upDir);\r
+\r
+  std::string pathTo = absPathTo.substr(lastSlash+1); // we left the heading slash\r
+  relPath.append(pathTo);\r
+  return std::string(relPath);\r
+}\r
+\r
+void ProjectDescriptor::print()\r
+{\r
+  fprintf( stderr, "project name %s and it is %s initialized\n", projectName.c_str(), isInitialized() ? "" : "not");\r
+  fprintf( stderr, "  target executable name %s\n",targetExecutableName.c_str());\r
+  fprintf( stderr, "  project abs TPD dir %s\n", projectAbsTpdDir.c_str());\r
+  fprintf( stderr, "  project abs working dir %s\n", projectAbsWorkingDir.c_str());\r
+  fprintf( stderr, "  project working dir %s\n", projectWorkingDir.c_str());\r
+  fprintf( stderr, "  project is %s\n", library ? "Library" : "Executable");\r
+  fprintf( stderr, "  project linking is %s\n", dynamicLinked ? "dynamic" : "static");\r
+  std::vector<std::string>::iterator it;\r
+  for (it = referencedProjects.begin(); it != referencedProjects.end(); ++it) {\r
+    fprintf( stderr, "    Referenced project %s\n",(*it).c_str());\r
+  }\r
+  for (it = refProjWorkingDirs.begin(); it != refProjWorkingDirs.end(); ++it) {\r
+    fprintf( stderr, "    Working dir of referenced project %s\n",(*it).c_str());\r
+  }\r
+  for (it = linkerLibraries.begin(); it != linkerLibraries.end(); ++it) {\r
+    fprintf( stderr, "    Linker library %s\n", (*it).c_str());\r
+  }\r
+  for (it = libSearchPaths.begin(); it != libSearchPaths.end(); ++it) {\r
+    fprintf( stderr, "    Linker lib search path %s\n", (*it).c_str());\r
+  }\r
+  for (it = ttcn3ModuleNames.begin(); it != ttcn3ModuleNames.end(); ++it) {\r
+    fprintf( stderr, "    TTCN3 Module Name: %s\n", (*it).c_str());\r
+  }\r
+  for (it = asn1ModuleNames.begin(); it != asn1ModuleNames.end(); ++it) {\r
+    fprintf( stderr, "    ASN1 Module Name: %s\n", (*it).c_str());\r
+  }\r
+  for (it = userSources.begin(); it != userSources.end(); ++it) {\r
+    fprintf( stderr, "    Source Name: %s\n", (*it).c_str());\r
+  }\r
+  for (it = userHeaders.begin(); it != userHeaders.end(); ++it) {\r
+    fprintf( stderr, "    Header Name: %s\n", (*it).c_str());\r
+  }\r
+  for (it = ttcnPP.begin(); it != ttcnPP.end(); ++it) {\r
+    fprintf( stderr, "    TTCN PP Name: %s\n", (*it).c_str());\r
+  }\r
+  fprintf( stderr, "\n");\r
+}\r
+\r
+ProjectGenHelper& ProjectGenHelper::Instance()\r
+{\r
+  static ProjectGenHelper singleton;\r
+  return singleton;\r
+}\r
+\r
+const std::string ProjectGenHelper::emptyString = std::string();\r
+\r
+ProjectGenHelper::ProjectGenHelper() :\r
+  nameOfTopLevelProject(),\r
+  rootDirOS(),\r
+  relPathToRootDirOS(),\r
+  Zflag(false),\r
+  Wflag(false),\r
+  Hflag(false),\r
+  projs(),\r
+  checkedProjs()\r
+{}\r
+\r
+void ProjectGenHelper::addTarget(const char* projName)\r
+{\r
+  if (!Zflag) return;\r
+  if (projs.end() != projs.find(std::string(projName))) return; // we have it \r
+  ProjectDescriptor newLib(projName);\r
+  projs.insert(std::pair<std::string, ProjectDescriptor> (std::string(projName), newLib));\r
+}\r
+\r
+void ProjectGenHelper::setToplevelProjectName(const char* name)\r
+{\r
+  if (!nameOfTopLevelProject.empty()) return;\r
+   nameOfTopLevelProject = std::string(name);\r
+}\r
+\r
+void ProjectGenHelper::setRootDirOS( const char* name)\r
+{\r
+  if (rootDirOS.empty()) {\r
+    rootDirOS = std::string(name);\r
+  }\r
+  else { //compare the 2 string and get the common part\r
+    const char* root = rootDirOS.c_str();\r
+    const char* head = root;\r
+    for (; *root++ == *name++; ) ;\r
+    size_t length = root - head - 1; //minus the non-matching\r
+    if (rootDirOS.size() > length) {\r
+      rootDirOS.resize(length);\r
+    }\r
+  }\r
+}\r
+\r
+const std::string& ProjectGenHelper::getRootDirOS(const char* name)\r
+{\r
+  ProjectDescriptor* proj = getProject(name);\r
+  if (!proj) return emptyString;\r
+  relPathToRootDirOS = proj->setRelativePathTo(rootDirOS);\r
+  return relPathToRootDirOS;\r
+}\r
+\r
+ProjectDescriptor* ProjectGenHelper::getTargetOfProject(const char* projName)\r
+{\r
+  if (!Zflag) return NULL;\r
+  if (projs.end() == projs.find(std::string(projName))) return NULL;\r
+  return getProject(projName);\r
+}\r
+\r
+const ProjectDescriptor* ProjectGenHelper::getTargetOfProject(const char* projName) const\r
+{\r
+  if (!Zflag) return NULL;\r
+  if (projs.end() == projs.find(std::string(projName))) return NULL;\r
+  return getProject(projName);\r
+}\r
+\r
+ProjectDescriptor* ProjectGenHelper::getProjectDescriptor(const char* targetName)\r
+{\r
+  if (!Zflag) return NULL;\r
+  for (std::map<std::string, ProjectDescriptor>::iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    if ((it->second).getTargetExecName() == std::string(targetName))\r
+      return &(it->second);\r
+  }\r
+  return NULL;\r
+}\r
+\r
+std::map<std::string, ProjectDescriptor>::const_iterator ProjectGenHelper::getHead() const\r
+{\r
+  return projs.begin();\r
+}\r
+\r
+std::map<std::string, ProjectDescriptor>::const_iterator ProjectGenHelper::getEnd() const\r
+{\r
+  return projs.end();\r
+}\r
+\r
+void ProjectGenHelper::addTtcn3ModuleToProject(const char* projName, const char* moduleName)\r
+{\r
+  if (!Zflag) return;\r
+  if (projs.end() == projs.find(std::string(projName))) return;\r
+  ProjectDescriptor* proj = getProject(projName);\r
+  if (proj && !proj->hasTtcn3ModuleName(moduleName)) {\r
+     proj->addTtcn3ModuleName(moduleName);\r
+  }\r
+}\r
+\r
+void ProjectGenHelper::addAsn1ModuleToProject(const char* projName, const char* moduleName)\r
+{\r
+  if (!Zflag) return;\r
+  if (projs.end() == projs.find(std::string(projName))) return;\r
+  ProjectDescriptor* proj = getProject(projName);\r
+  if (proj &&!proj->hasAsn1ModuleName(moduleName)) {\r
+     proj->addAsn1ModuleName(moduleName);\r
+  }\r
+}\r
+\r
+void ProjectGenHelper::addUserSourceToProject(const char* projName, const char* userSourceName)\r
+{\r
+  if (!Zflag) return;\r
+  if (projs.end() == projs.find(std::string(projName))) return;\r
+  ProjectDescriptor* proj = getProject(projName);\r
+  if (proj && !proj->hasUserSource(userSourceName)) {\r
+     proj->addUserSource(userSourceName);\r
+  }\r
+}\r
+\r
+void ProjectGenHelper::addUserHeaderToProject(const char* projName, const char* userHeaderName)\r
+{\r
+  if (!Zflag) return;\r
+  if (projs.end() == projs.find(std::string(projName))) return;\r
+  ProjectDescriptor* proj = getProject(projName);\r
+  if (proj && !proj->hasUserHeader(userHeaderName)) {\r
+    proj->addUserHeader(userHeaderName);\r
+  }\r
+}\r
+\r
+void ProjectGenHelper::addTtcnPPToProject(const char* projName, const char* ttcnPPName)\r
+{\r
+  if (!Zflag) return;\r
+  if (projs.end() == projs.find(std::string(projName))) return;\r
+  ProjectDescriptor* proj = getProject(projName);\r
+  if (proj && !proj->hasTtcn3PP(ttcnPPName)) {\r
+    proj->addTtcn3PP(ttcnPPName);\r
+  }\r
+}\r
+\r
+void ProjectGenHelper::generateRefProjectWorkingDirsTo(const char* projName)\r
+{\r
+  if (!Zflag) return;\r
+  std::map<std::string,ProjectDescriptor>::iterator iter = projs.find(projName);\r
+  if (projs.end() == iter) {\r
+    ERROR("Project \"%s\" is not found in the project hierarchy ", projName);\r
+    return;\r
+  }\r
+  if (nameOfTopLevelProject != (iter->second).getProjectName()) {\r
+    ERROR("Project \"%s\" is not the on the top-level ", projName);\r
+    return;\r
+  }\r
+  ProjectDescriptor* proj = &(iter->second); // the Top level project\r
+\r
+  for (size_t i = 0; i < proj->numOfReferencedProjects(); ++i) {\r
+    const std::string& refProjName = proj->getReferencedProject(i);\r
+    ProjectDescriptor* refProj = getTargetOfProject(refProjName.c_str());\r
+    if (!refProj) return; // for sure...\r
+    const std::string& absWorkingDir = refProj->getProjectAbsWorkingDir();\r
+    if (!absWorkingDir.empty()) {\r
+      std::string relPath =  proj->setRelativePathTo(absWorkingDir);\r
+      proj->addToRefProjWorkingDirs(relPath);\r
+    }\r
+  }\r
+}\r
+\r
+size_t ProjectGenHelper::numOfLibs() const\r
+{\r
+  if (!Zflag) return 0;\r
+  size_t num = 0;\r
+  for (std::map<std::string, ProjectDescriptor>::const_iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    if ((it->second).isLibrary()) {\r
+      ++num;\r
+    }\r
+  }\r
+  return num;\r
+}\r
+\r
+struct CompareStr\r
+{\r
+  bool operator () (const char* lhs, const char* rhs) {\r
+    int ret = strcmp(lhs, rhs);\r
+    return (0 > ret);\r
+  }\r
+};\r
+\r
+void ProjectGenHelper::getExternalLibs(std::vector<const char*>& extLibs)\r
+{\r
+  if (!Zflag) return;\r
+  std::map<const char*, const char*, CompareStr> libs;\r
+  for (std::map<std::string, ProjectDescriptor>::iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    if ((it->second).numOfLinkerLibs() > 0) {\r
+      for (size_t i = 0; i < (it->second).numOfLinkerLibs(); ++i) {\r
+        const char* key = (it->second).getLinkerLib(i);\r
+        const char* value = (it->second).getProjectName().c_str();\r
+        libs.insert(std::pair<const char*,const char*>(key,value)); // filter duplicates\r
+      }\r
+    }\r
+  }\r
+  std::map<const char*, const char*>::iterator it;\r
+  for (it = libs.begin(); it != libs.end(); ++it) {\r
+    extLibs.push_back(it->first);\r
+  }\r
+}\r
+\r
+void ProjectGenHelper::getExternalLibSearchPathes(std::vector<const char*>& extLibPathes)\r
+{\r
+  if (!Zflag) return;\r
+  std::map<const char*, const char*, CompareStr> libPathes;\r
+  for (std::map<std::string, ProjectDescriptor>::iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    if ((it->second).numOfLibSearchPaths() > 0) {\r
+      for (size_t i = 0; i < (it->second).numOfLibSearchPaths(); ++i) {\r
+        const char* key = (it->second).getLibSearchPath(i);\r
+        const char* value = (it->second).getProjectName().c_str();\r
+        libPathes.insert(std::pair<const char*,const char*>(key,value)); // filter duplicates\r
+      }\r
+    }\r
+  }\r
+  std::map<const char*, const char*>::iterator it;\r
+  for (it = libPathes.begin(); it != libPathes.end(); ++it) {\r
+    extLibPathes.push_back(it->first);\r
+  }\r
+}\r
+\r
+bool ProjectGenHelper::hasReferencedProject()\r
+{\r
+  if (!Zflag) return false;\r
+  ProjectDescriptor* topLevel = getTargetOfProject(nameOfTopLevelProject.c_str());\r
+  if (topLevel && topLevel->numOfReferencedProjects()) return true;\r
+  return false;\r
+}\r
+\r
+bool ProjectGenHelper::isTtcn3ModuleInLibrary(const char* moduleName) const\r
+{\r
+  if (!Zflag) return false;\r
+  for (std::map<std::string, ProjectDescriptor>::const_iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    if ((it->second).hasTtcn3ModuleName(moduleName) && (it->second).isLibrary()) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool ProjectGenHelper::isAsn1ModuleInLibrary(const char* moduleName) const\r
+{\r
+  if (!Zflag) return false;\r
+  for (std::map<std::string, ProjectDescriptor>::const_iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    if ((it->second).hasAsn1ModuleName(moduleName) && (it->second).isLibrary()) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool ProjectGenHelper::isSourceFileInLibrary(const char* fileName) const\r
+{\r
+  if (!Zflag || NULL == fileName) return false;\r
+  for (std::map<std::string, ProjectDescriptor>::const_iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    if ((it->second).hasUserSource(fileName) && (it->second).isLibrary()) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool ProjectGenHelper::isHeaderFileInLibrary(const char* fileName) const\r
+{\r
+  if (!Zflag || NULL == fileName) return false;\r
+\r
+  for (std::map<std::string, ProjectDescriptor>::const_iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    if ((it->second).hasUserHeader(fileName) && (it->second).isLibrary()) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool ProjectGenHelper::isTtcnPPFileInLibrary(const char* fileName) const\r
+{\r
+  if (!Zflag || NULL == fileName) return false;\r
+\r
+  for (std::map<std::string, ProjectDescriptor>::const_iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    if ((it->second).hasTtcn3PP(fileName) && (it->second).isLibrary()) return true;\r
+  }\r
+  return false;\r
+}\r
+\r
+bool ProjectGenHelper::isCPPSourceFile(const char* fileName) const\r
+{\r
+  std::string fnStr(fileName);\r
+  size_t pos = fnStr.find_last_of('.');\r
+  if (std::string::npos == pos) return false;\r
+  const std::string EXT_CC("cc");\r
+  const std::string EXT_CPP("cpp");\r
+  int length = 0;\r
+  if (std::string::npos != fnStr.find (EXT_CC, pos + 1))\r
+    length = EXT_CC.size();\r
+  else if (std::string::npos != fnStr.find (EXT_CPP, pos + 1))\r
+    length = EXT_CPP.size();\r
+\r
+  if (length && fnStr.size() == pos + length + 1)\r
+    return true;\r
+  else \r
+    return false;\r
+}\r
+\r
+bool ProjectGenHelper::isCPPHeaderFile(const char* fileName) const\r
+{\r
+  std::string fnStr(fileName);\r
+  size_t pos = fnStr.find_last_of('.');\r
+  if (std::string::npos == pos) return false;\r
+  const std::string EXT_HPP("hpp");\r
+  const std::string EXT_HH("hh");\r
+  const std::string EXT_H("h");\r
+  int length = 0;\r
+  if (std::string::npos != fnStr.find (EXT_HH, pos + 1))\r
+    length = EXT_HH.size();\r
+  else if (std::string::npos != fnStr.find (EXT_HPP, pos + 1))\r
+    length = EXT_HPP.size();\r
+  else if (std::string::npos != fnStr.find (EXT_H, pos + 1))\r
+    length = EXT_H.size();\r
+\r
+  if (length && fnStr.size() == pos + length + 1)\r
+    return true;\r
+  else\r
+    return false;\r
+}\r
+\r
+bool ProjectGenHelper::isTtcnPPFile(const char* fileName) const\r
+{\r
+  std::string fnStr(fileName);\r
+  size_t pos = fnStr.find_last_of('.');\r
+  if (std::string::npos == pos) return false;\r
+  const std::string EXT_TTCNPP("ttcnpp");\r
+  int length = 0;\r
+  if (std::string::npos != fnStr.find (EXT_TTCNPP, pos + 1))\r
+    length = EXT_TTCNPP.size();\r
+\r
+  if (length && fnStr.size() == pos + length + 1)\r
+    return true;\r
+  else\r
+    return false;\r
+}\r
+\r
+void ProjectGenHelper::print()\r
+{\r
+  if (!Zflag) return;\r
+  fprintf(stderr, "Top Level project : %s\n", nameOfTopLevelProject.c_str());\r
+  for (std::map<std::string, ProjectDescriptor>::iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    (it->second).print();\r
+  }\r
+}\r
+\r
+bool ProjectGenHelper::sanityCheck()\r
+{\r
+  if (!Zflag) return true;\r
+  bool ret = true;\r
+// if toplevel is a dynamic linked executable (not library) all executable shall set to the same linking method\r
+  {\r
+    ProjectDescriptor* topLevel = getTargetOfProject(nameOfTopLevelProject.c_str());\r
+    bool isDynamicLinked = topLevel->getLinkingStrategy();\r
+    if (!topLevel->isLibrary() && isDynamicLinked) { // dynamic linked executable\r
+      for (std::map<std::string, ProjectDescriptor>::iterator it = projs.begin(); it != projs.end(); ++it) {\r
+        if (!(it->second).isLibrary()) { //if exectubale \r
+          if (isDynamicLinked != (it->second).getLinkingStrategy()) {\r
+             ERROR("project \"%s\" is set to %s linking. Sub project \"%s\" is set to %s linking. "\r
+                   "All sub-level executable shall be set to the %s's type.",\r
+                   nameOfTopLevelProject.c_str(),\r
+                   isDynamicLinked ? "dynamic" : "static",\r
+                   ((it->second).getProjectName()).c_str(),\r
+                   isDynamicLinked ? "static" : "dynamic",\r
+                   nameOfTopLevelProject.c_str());\r
+             ret = false;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+// under a dynamic linked library every project shall be linked dynamic library too.\r
+  {\r
+    checkedProjs.clear();\r
+    bool found = false; // search for executable under dynamic linked library\r
+    char* execName = NULL;\r
+    for (std::map<std::string, ProjectDescriptor>::reverse_iterator rit = projs.rbegin(); rit != projs.rend(); ++rit) {\r
+      if ((rit->second).isLibrary() && (rit->second).getLinkingStrategy()) { //dynamic library \r
+        ProjectDescriptor& proj = rit->second;\r
+        found = DynamicLibraryChecker(&proj, found, &execName);\r
+        if (found) {\r
+           ERROR("Project \"%s\" is dynamic linked library. Sub project \"%s\" is executable.\n"\r
+                 "in TPD file, %s's all sub-level defaultTarget shall be set library too.",\r
+                 proj.getProjectName().c_str(), execName, proj.getProjectName().c_str());\r
+           ret = false;\r
+           break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return ret;\r
+}\r
+\r
+ProjectDescriptor* ProjectGenHelper::getProject(const char* projName)\r
+{\r
+  if (!projName) return NULL;\r
+  for (std::map<std::string, ProjectDescriptor>::iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    if (it->first == std::string(projName)) {\r
+      return &(it->second);\r
+    }\r
+  }\r
+  return NULL;\r
+}\r
+\r
+const ProjectDescriptor* ProjectGenHelper::getProject(const char* projName) const\r
+{\r
+  if (!projName) return NULL;\r
+  for (std::map<std::string, ProjectDescriptor>::const_iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    if (it->first == std::string(projName)) {\r
+      return &(it->second);\r
+    }\r
+  }\r
+  return NULL;\r
+}\r
+\r
+\r
+void ProjectGenHelper::cleanUp()\r
+{\r
+  if (!Zflag) return;\r
+  checkedProjs.clear();\r
+  for (std::map<std::string, ProjectDescriptor>::iterator it = projs.begin(); it != projs.end(); ++it) {\r
+    (it->second).cleanUp();\r
+  }\r
+}\r
+\r
+bool ProjectGenHelper::DynamicLibraryChecker(const ProjectDescriptor* desc,\r
+                                       bool& found,\r
+                                       char** executableName)\r
+{\r
+  if (found || !desc) return true;\r
+  for (size_t i = 0; i < desc->numOfReferencedProjects(); ++i) {\r
+    char* refProjName = const_cast<char*> (desc->getReferencedProject(i).c_str());\r
+    const ProjectDescriptor* subProj = getTargetOfProject(refProjName);\r
+    if (0 == checkedProjs.count(subProj->getProjectName())) {\r
+      if (subProj->isLibrary()) {\r
+        found = DynamicLibraryChecker(subProj, found, executableName);\r
+      }\r
+      else { // search for executable under dynamic linked library\r
+        found = true;\r
+        *executableName = refProjName;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  // it is checked, no such executable was found. Store it not to iterate again\r
+  if (!found)\r
+    checkedProjs.insert(std::pair<const std::string, const ProjectDescriptor*> \r
+                       (desc->getProjectName(), desc));\r
+  return found;\r
+}\r
+\r
diff --git a/compiler2/ProjectGenHelper.hh b/compiler2/ProjectGenHelper.hh
new file mode 100644 (file)
index 0000000..638633b
--- /dev/null
@@ -0,0 +1,157 @@
+///////////////////////////////////////////////////////////////////////////////\r
+// Copyright (c) 2000-2014 Ericsson Telecom AB\r
+// All rights reserved. This program and the accompanying materials\r
+// are made available under the terms of the Eclipse Public License v1.0\r
+// which accompanies this distribution, and is available at\r
+// http://www.eclipse.org/legal/epl-v10.html\r
+///////////////////////////////////////////////////////////////////////////////\r
+#ifndef _LIB_GEN_HELPER_HH\r
+#define _LIB_GEN_HELPER_HH\r
+#include <string>\r
+#include <map>\r
+#include <vector>\r
+#include <cstdio>\r
+class ProjectGenHelper;\r
+class ProjectDescriptor {\r
+public:\r
+  explicit ProjectDescriptor(const char* name);\r
+  ~ProjectDescriptor() { cleanUp(); };\r
+\r
+  const std::string& getProjectName() const { return projectName; }\r
+  void setTPDFileName( const char* name);\r
+  const std::string& getTPDFileName() const { return tpdFileName; }\r
+  void setTargetExecName(const char* name) { targetExecutableName = std::string(name); }\r
+  const std::string& getTargetExecName() const { return targetExecutableName; }\r
+  void setProjectAbsTpdDir(const char* name) { projectAbsTpdDir = std::string(name); }\r
+  const std::string& getProjectAbsTpdDir() const { return projectAbsTpdDir; }\r
+  void setProjectAbsWorkingDir(const char* name);\r
+  void setProjectWorkingDir(const char* name) { projectWorkingDir = std::string(name); }\r
+  const std::string& getProjectAbsWorkingDir() const { return projectAbsWorkingDir; }\r
+  const std::string& getProjectWorkingDir() const { return projectWorkingDir; }\r
+  void setLinkingStrategy(bool strategy) { dynamicLinked = strategy; }\r
+  bool getLinkingStrategy() const { return dynamicLinked; }\r
+  void setLibrary(bool isLib) { library = isLib; }\r
+  bool isLibrary() const { return library; }\r
+  bool isInitialized();\r
+  void addToReferencedProjects(const char* refProjName);\r
+  void addToRefProjWorkingDirs(const std::string& subProjDir);\r
+  bool hasLinkerLibTo(const std::string& refProjName) const; \r
+  bool hasLinkerLib(const char* libName) const; // Linker Lib got from TPD\r
+  void addToLibSearchPaths(const char* libSearchPath);\r
+  void addToLinkerLibs(const char* linkerLibs);\r
+  void print();\r
+  void cleanUp();\r
+  size_t numOfReferencedProjects() const { return referencedProjects.size(); };\r
+  size_t numOfRefProjWorkingDirs() const { return refProjWorkingDirs.size(); };\r
+  size_t numOfLibSearchPaths() const { return libSearchPaths.size(); };\r
+  size_t numOfLinkerLibs() const { return linkerLibraries.size(); };\r
+  const std::string& getReferencedProject(size_t index) const \r
+    { return index < referencedProjects.size() ? referencedProjects[index] : emptyString; };\r
+  const std::string& getRefProjWorkingDir(size_t index) const \r
+    { return index < refProjWorkingDirs.size() ? refProjWorkingDirs[index] : emptyString; };\r
+  const char* getLibSearchPath(const std::string& subProjName) const;\r
+  const char* getLibSearchPath(size_t index) const { return libSearchPaths[index].c_str(); };\r
+  const char* getLinkerLib(const std::string& subProjName) const;\r
+  const char* getLinkerLib(size_t index) const { return linkerLibraries[index].c_str(); };\r
+  size_t getLibSearchPathIndex(const std::string& subProjName) const;\r
+  void setLibSearchPath(size_t index, const std::string& relPath) { libSearchPaths[index] = relPath; };\r
+  void addTtcn3ModuleName(const char* name) { ttcn3ModuleNames.push_back(name); };\r
+  bool hasTtcn3ModuleName(const char* moduleName) const;\r
+  void addAsn1ModuleName(const char* name) { asn1ModuleNames.push_back(name); };\r
+  bool hasAsn1ModuleName(const char* moduleName) const;\r
+  void addUserSource(const char* name) { userSources.push_back(name); };\r
+  bool hasUserSource(const char* userSourceName) const;\r
+  void addUserHeader(const char* name) { userHeaders.push_back(name); };\r
+  bool hasUserHeader(const char* userHeaderName) const;\r
+  void addTtcn3PP(const char* name) { ttcnPP.push_back(name); };\r
+  bool hasTtcn3PP(const char* ttcnPPName) const;\r
+  std::string setRelativePathTo(const std::string& absPathTo);\r
+\r
+private:\r
+  static const std::string emptyString;\r
+  std::string projectName;\r
+  std::string tpdFileName;\r
+  std::string targetExecutableName; //Library or Executable(only the top level)\r
+  std::string projectAbsTpdDir;\r
+  std::string projectAbsWorkingDir;\r
+  std::string projectWorkingDir;\r
+  bool library;\r
+  bool dynamicLinked;\r
+  std::vector<std::string> referencedProjects;\r
+  std::vector<std::string> refProjWorkingDirs;\r
+  std::vector<std::string> libSearchPaths;\r
+  std::vector<std::string> linkerLibraries;\r
+  std::vector<std::string> ttcn3ModuleNames;\r
+  std::vector<std::string> asn1ModuleNames;\r
+  std::vector<std::string> userSources; // *.cc ; *.cpp\r
+  std::vector<std::string> userHeaders; // *.hh ; *.h ; *.hpp\r
+  std::vector<std::string> ttcnPP; // *.ttcnpp\r
+  bool initialized;\r
+};\r
+\r
+class ProjectGenHelper {\r
+public:\r
+  static ProjectGenHelper &Instance();\r
+  ~ProjectGenHelper() { cleanUp(); };\r
+  void setZflag(bool flag) { Zflag = flag; };\r
+  bool getZflag() const { return Zflag; };\r
+  void setWflag(bool flag) { Wflag = flag; };\r
+  bool getWflag() const { return Wflag; };\r
+  void setHflag(bool flag) { Hflag = flag; };\r
+  bool getHflag() const { return Hflag; };\r
+  void setToplevelProjectName(const char* name);\r
+  const std::string& getToplevelProjectName() const { return nameOfTopLevelProject; };\r
+  void setRootDirOS(const char* name);\r
+  const std::string& getRootDirOS(const char* name);\r
+  void addTarget(const char* projName);\r
+  void generateRefProjectWorkingDirsTo(const char* projName);\r
+  void addTtcn3ModuleToProject(const char* projName, const char* moduleName);\r
+  void addAsn1ModuleToProject(const char* projName, const char* moduleName);\r
+  void addUserSourceToProject(const char* projName, const char* userSourceName);\r
+  void addUserHeaderToProject(const char* projName, const char* userHeaderName);\r
+  void addTtcnPPToProject(const char* projName, const char* ttcnPPName);\r
+  bool isTtcn3ModuleInLibrary(const char* moduleName) const;\r
+  bool isAsn1ModuleInLibrary(const char* moduleName) const;\r
+  bool isSourceFileInLibrary(const char* fileName) const;\r
+  bool isHeaderFileInLibrary(const char* fileName) const;\r
+  bool isTtcnPPFileInLibrary(const char* fileName) const;\r
+  ProjectDescriptor* getTargetOfProject(const char* projName);\r
+  const ProjectDescriptor* getTargetOfProject(const char* projName) const;\r
+  ProjectDescriptor* getProjectDescriptor(const char* targetName); //target_executable_name\r
+  std::map<std::string, ProjectDescriptor>::const_iterator getHead() const;\r
+  std::map<std::string, ProjectDescriptor>::const_iterator getEnd() const;\r
+  size_t numOfLibs() const;\r
+  void getExternalLibs(std::vector<const char*>& extLibs);\r
+  void getExternalLibSearchPathes(std::vector<const char*>& extLibPathes);\r
+  bool hasReferencedProject();\r
+  size_t numOfProjects() const { return projs.size();};\r
+  bool isCPPSourceFile(const char* fileName) const;\r
+  bool isCPPHeaderFile(const char* fileName) const;\r
+  bool isTtcnPPFile(const char* fileName) const;\r
+  void print();\r
+  bool sanityCheck(); // tests if the structure generated from TPDs is consistent\r
+  void cleanUp();\r
+\r
+private:\r
+    ProjectGenHelper();\r
+    ProjectGenHelper(const ProjectGenHelper &rhs);\r
+    ProjectGenHelper &operator=(const ProjectGenHelper &rhs);\r
+    ProjectDescriptor* getProject(const char* projName);\r
+    const ProjectDescriptor* getProject(const char* projName) const;\r
+    bool DynamicLibraryChecker(const ProjectDescriptor* desc,\r
+                         bool& found,\r
+                         char** executableName);\r
+private:\r
+  static ProjectGenHelper& intance;\r
+  static const std::string emptyString;\r
+  std::string nameOfTopLevelProject;\r
+  std::string rootDirOS; // make archive needs the top dir on OS level\r
+  std::string relPathToRootDirOS;\r
+  bool Zflag; // the makefilegen switch wether to use this option at all\r
+  bool Wflag; // prefix woring directory\r
+  bool Hflag; // hierarchical make structure\r
+  std::map<const std::string, ProjectDescriptor> projs;\r
+  std::map<const std::string, const ProjectDescriptor*> checkedProjs;\r
+};\r
+\r
+#endif // _LIB_GEN_HELPER_HH\r
index 64c02b6bbd79a16fc2e054fed105434ab2c82dae..1dae00b162f0c9a8ad4709e21d2846884bc4f7a5 100644 (file)
@@ -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;
   }
 
index 7ddf074974ef9f3b10c09fc2f27a8b3a10e9ef48..82f1bfcb1593cdd8045f03e98040252bb1e2b160 100644 (file)
@@ -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
index 2f59ba7452a7ffb57a6f35c77c48e48a5dbd0ec7..2a9683d3c26f0e378f0a95a1ce36c9d6d10f5ada 100644 (file)
@@ -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()) {
index f15b4e5b6e9b6462a8e97852542204099a049f2d..55737c94bb107fee57f4d9fd8e686bfe38bf31b7 100644 (file)
@@ -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 */
index 7aee9f7ea6a1c66b556ad0251cebe8fd7ad37cab..d3861ebb2c1ca6edb350d5085e9b2df25e44396e 100644 (file)
@@ -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(),
index 6e9679c59e1533de899ac8ec038a60e33daff7fb..b6baffb615c9656ab6e0024d3fa098f0347b1dd1 100644 (file)
@@ -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<CompField*>(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
index 4f51aa3161aee9264164b1dd7942a6d8bf0f8740..a1c1c8a524120905f821fd0d40c3cf373f6d2134 100644 (file)
@@ -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("<erroneous>");
     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);
index 47eedebed82267fef217ef2a761de71a0b979220..cfd3f796b5438d32da68e2cb74b0336f493d6a0b 100644 (file)
@@ -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
index d286ad3051c030ccdbfbb543942eaeafddf8b79e..6e83b0b2a0687d106fdaf714d607f6b8e0e795ae 100644 (file)
@@ -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<Type*, JSON_Tokenizer>& 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<Asn::Assignment*>(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()
   {
index 180d0d117d85a64d5321c375617c65a0264665b4..43eba0332b3df2ed2dcae634c6ceb9b826ddc19a 100644 (file)
@@ -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<Type*, JSON_Tokenizer>&) {}
+    /** 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<Type*, JSON_Tokenizer>& 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();
index b933ea174f9220433dd5e6315410ee7f138f489f..0c7b52f7b4a04418bf1acea1c747ae849dd836c4 100644 (file)
@@ -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());
index 762b4f08d335a7e228000215907e7075c381fbdf..a3416e4b57b16edbc01adf7d6cc92ea89f8399ee 100644 (file)
@@ -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
index 2dc6e6642702670f744191ba06d44c22293dc78c..4d5362d21abed21939a27613479bbd1bfdc1b10a 100644 (file)
@@ -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:
        * <ttcn>type newtype oldtype;</ttcn> */
-     "    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"
index 67133e280b309d9d24837b15c0f0c6642760e3f2..15ad0b576b78d78d49476bd3e1f5a43d1b2e7a54 100644 (file)
@@ -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"
 
index 9f50d8eec061e42f773dec80b0081085e09f2771..fd58f1a80e61eaf0ea53f552cc5eb84d367ac911 100644 (file)
@@ -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
index 0beb371e600b9f2f861ab717547dd2abc5c7ad62..18ec896018586b1989fa053938e0a20360f534b4 100644 (file)
@@ -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;
 
index 746d12652928797028cba09d858ad80764638275..4252d22e3aa82112d27e61c9512f75508e2ceadf 100644 (file)
@@ -13,7 +13,7 @@
 #include <errno.h>
 #include <ctype.h>
 #if defined SOLARIS || defined SOLARIS8
-# include <sys/utsname.h>
+#include <sys/utsname.h>
 #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, "</project_hierarchy_graph>\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;
 }
 
-
index 67b7e96e5c86b8dafd2fb8c781aff85d82e58b83..79e914f389eb431f200ed97bd5a8e96df3739463 100644 (file)
@@ -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_j<exp_embed; ++j_j) {\n"
+      "    for (int j_j = 0; j_j < emb_val->embval_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"
index 0b761652834dbe924d3aac61d14248d021211670..b820722e988d8c3bb1fe6cf705b62500ba558375 100644 (file)
@@ -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<int> 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; i<nof_elements; i++) {\n"
-    "if (is_elem_bound(i)) {\n"
-    "ret_val.val_ptr->value_elements[(i+rc)%%nof_elements] ="
+    "ret_val.set_size(val_ptr->n_elements);\n"
+    "for (int i=0; i<val_ptr->n_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; i<nof_elements; i++) {\n"
-    "if (is_elem_bound(i)) {\n"
+    "ret_val.set_size(val_ptr->n_elements+other_value.val_ptr->n_elements);\n"
+    "for (int i=0; i<val_ptr->n_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; i<other_value_nof_elements; i++) {\n"
-    "if (other_value.is_elem_bound(i)) {\n"
-    "ret_val.val_ptr->value_elements[i + nof_elements] = "
+    "for (int i=0; i<other_value.val_ptr->n_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; i<returncount; i++) {\n"
-    "if (is_elem_bound(i+index)) {\n"
+    "if (val_ptr->value_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;a<get_nof_elements();a++){\n"
+      "  for(int a=0;a<val_ptr->n_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; a<val_ptr->n_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_i<get_nof_elements(); elem_i++) {\n"
+       "    for(int elem_i=0; elem_i<val_ptr->n_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_i<get_nof_elements(); elem_i++) {\n"
+         "  for(int elem_i=0; elem_i<val_ptr->n_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*)\"<a\");\n"
@@ -1413,10 +1278,16 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
       "    TTCN_EncDec_ErrorContext ec_1;\n"
       );
     src=mputprintf(src,
-      "    for (int i = 0; i < nof_elements; ++i) {\n"
+      "    for (int i = 0; i < val_ptr->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*)\"<a\");\n"
@@ -2830,9 +2703,15 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
       );
     src=mputprintf(src,
       "    for (int i = 0; i < 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"
-      "      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");
 
index d59cf5ca0a950fc306aed5e5706e26940c6dbda1..29b0232209e81b958d1b3af0aa73370d5751a592 100644 (file)
@@ -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()");
index a9618aa057fcbfdd166ac10b17d9f60eaf1cbda4..f7fde1aa5ce0eeba292d7096fb7b14d63cb21dda 100644 (file)
@@ -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;
 };
 
 /**
index 02adf32ebf55ebb066d515fe3b57505ca3dddfd0..bc18d923b287a18eba3be87a0346f19a6b7f8b02 100644 (file)
@@ -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
index 86970b385dd6ea914b62f3bed753b95f4572d6dd..473213e7b23bdf12db3c614a450eb9248053ddef 100644 (file)
@@ -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<LIMITTYPE>::get_maximal() const
   return values[values.size()-1];
 }
 
+template <typename LIMITTYPE>
+bool RangeListConstraint<LIMITTYPE>::is_upper_limit_infinity () const
+{
+  if (0 == values.size()) return false;
+  return LIMITTYPE::maximum == values[values.size()-1];
+}
+
+template <typename LIMITTYPE>
+bool RangeListConstraint<LIMITTYPE>::is_lower_limit_infinity () const
+{
+  if (0 == values.size()) return false;
+  return LIMITTYPE::minimum == values[0];
+}
+
 template <typename LIMITTYPE>
 string RangeListConstraint<LIMITTYPE>::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;
 };
 
 ////////////////////////////////////////////////////////////////////////////////
index 80c05634a6db62b39b629ec65a13894d39e0e68c..7b0a70c772029a794009e687918ee49f395483de 100644 (file)
@@ -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<Type*, JSON_Tokenizer>& 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<Def_Type*>(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<Type*, JSON_Tokenizer>& json_refs)
-  {
+    
+    // insert function data
     for (size_t i = 0; i < asss->get_nof_asss(); ++i) {
       Def_ExtFunction* def = dynamic_cast<Def_ExtFunction*>(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);
index 85e69998c10d43e891a9d9a2d9acb468cc7f1db6..06a57a6a9864e5704d0481dd8bd7aec866cb7a09 100644 (file)
@@ -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<Type*, JSON_Tokenizer>& 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<Type*, JSON_Tokenizer>& 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);
   };
 
   /**
index 717c36167101b2085015035b770a42c594e44fbb..2a452a902f4492154e8725b2a74443e9df7f48da 100644 (file)
@@ -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<Def_Testcase*>(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);
index 9a36b1e2dc532cbbcee7e94a36fd379f3ce2cb60..1c1aa6c17015472d912a14eab451ef64e7e42a49 100644 (file)
@@ -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
index ab3410360badca7966f3cd69cc27e5f5c0a8bef7..fb70102fb7e9961aac87c808a86409a89663895b 100644 (file)
@@ -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<Common::Type*, JSON_Tokenizer> 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<Common::Type*, JSON_Tokenizer> 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);
index 8052ecc0c0648542a7aac1c4ee23b6878da0329d..bf646c6aca538013d956dbcc7a19d537a5f639c1 100644 (file)
@@ -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()");
index 9f8675b1858e460d4c7e959125f29716a84aa805..ce428baaa8ddc657992c0bee38d3f71a230926fb 100644 (file)
@@ -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);
index 0393bcc3cd59767237c7ca107965bd1cc47b38c4..e469f4abfd6fa91299c6fd1d7fe8c0741512a6c3 100644 (file)
@@ -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"
index 14c15a6de426974da68545eadfd5222ce30f27e0..d816584384bdfd176bc8acada1ed2590cd7afbd9 100644 (file)
 // 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<const char*> 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<const char*> 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<std::string, ProjectDescriptor>::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<boolean>(projGenHelper.hasReferencedProject());
+  else if(std::string(projName) == projGenHelper.getToplevelProjectName())
+    return static_cast<boolean>(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<cstring, void> excluded_files;
+map<cstring, const char> 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<const char> excluded_folders;
@@ -305,58 +597,80 @@ static void clear_seen_tpd_files(map<cstring, int>& 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<cstring, int>& 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<cstring, int>& 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<cstring, int> 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<cstring, int>& 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<cstring, int>& 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;
 }
index fc5b9fc8d776bae319e720d447921e1fe3a02061..935e2252472b33756ac2b4a44c27904fd978dfbf 100644 (file)
@@ -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_ */
index daf4620534ee7b5b2dc9b5b1e30892b20b2b8ef3..129081b88f10082e55bf94f254907765f58d53ef 100644 (file)
@@ -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'",
index c9c01f027292a866da39aacddc4e28c6d785f77d..f4ae4a5d7b8c5919beb54b2f0a594be8e20e97a9 100644 (file)
@@ -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 <syntaxes>, 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) {
index 5e0c24b61fe2ed9dabd95fb076f266ecb8bea7ab..279bccc0a5809da4764b49e33cf338cdb2018f0c 100644 (file)
@@ -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 {
index 003b81f5571640561d7b18ac3f7f9a5dec3bc3d9..7a05319d6256b070e6852ce3273baf584545eb4c 100644 (file)
@@ -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 <syntaxes>, 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) {
index 6dce034b061ee879eaf56a1d3073cb6fa70ced36..0ee44cf13e43ec043002544f9b3b54f4351a0db9 100644 (file)
@@ -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 {
index 94836ac452cd48f5ea7d768380a545acc112a666..65e7e3dd031367555f19db8d251a2b4c5affdec7 100644 (file)
@@ -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;}
index cb926e1450b3ea58e4103445aa6036950817b16f..9405c254cf29508ddfdc4d774eaad6f67fec9403 100644 (file)
@@ -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 {
index 800c533413b601eae1792b828bbb8599f452936c..ab3c9a2c8c4aa227558fe03bcf59c065ad271bf9 100644 (file)
@@ -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 "
index e83c564e81000c4f9073b0f8e0bb7f2125bad45a..dae43d0f8261ef5d88dff09e4e66de06b1085d95 100644 (file)
@@ -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);
index a85ab09ddc0517b463156a4ca815c96154feb56d..bfbfde7ead30ae240e0763ac08febdb36af47b93 100644 (file)
@@ -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 <typename T_type, unsigned int array_size, int index_offset>
index d253707d07fa546cb89129fc1a988e9d905258d9..104e6b0f94e0408119a16137600614a7f18d3169 100644 (file)
@@ -16,6 +16,7 @@
 #include "JSON.hh"
 #include "XmlReader.hh"
 #include "Module_list.hh"
+#include "Universal_charstring.hh"
 
 #include <openssl/bn.h>
 
@@ -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};
index fca5d1c0e6c47c859db089e93017a3f47a02c5d8..2e49375559337c42d6d56820b847f483917280ab 100644 (file)
@@ -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<int> 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<int> 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. */
index 513bc292b429b516889147624a65d6ebdc4b7c08..d55b1fa8e5bbd61920896caa516e785ae7dba5c4 100644 (file)
@@ -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;
index ed25023a3ffabb6e6f8a2d08026b1fbb9d46c295..f1061615021be15c4b464b03dc299bce5848aecc 100644 (file)
@@ -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. */
index 80bc0ec7bb667f9a60ca40dd119bb3193abf4645..210ff857688f6a802d4d0f85bac33879125c1b14 100644 (file)
@@ -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);
index 2a1c07b99ae6adb875d90cb9b32672d0898e3c6b..0807ea524903684f31f336a5568bbfb49b3e7c8d 100644 (file)
@@ -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. */
index c0cbe337552143c81863b8659b154033c90e5fa1..180fc91fd77c97f1872077105f793f1bb9d152df 100644 (file)
@@ -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;
 
index 22a2c56344a09e88d06c751354aad972e59ac368..4ca62b41b1f1fd21eb851ec16e82b8e64a983212 100644 (file)
@@ -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
index 5a3d83db6188674c451d63b09b288b7d4a5588fc..50c1c919e231a08cc56545ebd49e09e2e2139252 100644 (file)
@@ -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;
index 76e32b47f2cb0a0abd3f0741c643b38ff19d99a0..013d39de728a33e56fd9ec38289b00c3478645bf 100644 (file)
@@ -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. */
index 04c67465a1c2851a9ca27d0757e09a766b0f8e83..27c7e4af461d39b885580b44beb565f65a0d5967 100644 (file)
@@ -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;
index c4392ab1ea9773f1972da9814e343a8534603d46..1fd91e8886313ec78d1d51d27bab0538d272417f 100644 (file)
@@ -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. */
index 331cd944fc75f421fe8f9ac024635ad353ad933a..b997527584ca03e07f2418cfa6d4277153ec18bb 100644 (file)
@@ -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;
index 1e48b62bb2596dbfc5900a9e368c97b3fb3fa0d2..bf6ec359cb3434cef518e310ed897a3cf41421f5 100644 (file)
@@ -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. */
index 59b62db0fd1eb339807bbb1a4d383088a068061c..ad429c4138db16a337fac0414a135bae4b20fe40 100644 (file)
@@ -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 };
index 39cbec482a1eb7f6e4f2541a2816f90d681ff29f..6c9357d694361935591cbd51bdf156ffc22580b9 100644 (file)
@@ -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 {
index bb6ac4d941f77bd73e428363b0e1dcd43cb94581..ff35320ae46f8d33a6447c846b212bf3cb604c8f 100644 (file)
@@ -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
index 00d37bab4372bca4e60343e515824218692d264e..79fe281c049b46672d53435b627e9f6140abce91 100644 (file)
@@ -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()
 {
index c5828b55c80374c8d82387e7e75f179c03083dad..b2b7489c94e37a2034123508f8fb74ae582deb4e 100644 (file)
@@ -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
index 948c225626e8f8357571a1e717aa2098521b554f..644ca5096781ae90a4e07ef2260c65f57c1afbb2 100644 (file)
@@ -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;
index 8c8e9b461d0f2ac8be815655db199056d3f9aa8d..bb1428aab959c1ec59bddc6c0cbeb1621c0eb737 100644 (file)
@@ -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. */
index 7c47aacc933cff2f3d826f6256a853b7b204dee7..85e14757f23dc0710bacbf2bfcc0d525c40cd6b0 100644 (file)
@@ -26,19 +26,23 @@ enum optional_sel { OPTIONAL_UNBOUND, OPTIONAL_OMIT, OPTIONAL_PRESENT };
 
 template <typename T_type>
 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 <typename T_tmp>
   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<typename T_type>
 Base_Type* OPTIONAL<T_type>::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<T_type>::get_opt_value()
 template<typename T_type>
 const Base_Type* OPTIONAL<T_type>::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<T_type>::get_opt_value() const
 template<typename T_type>
 boolean OPTIONAL<T_type>::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<typename T_type>
 const TTCN_Typedescriptor_t* OPTIONAL<T_type>::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<typename T_type>
 OPTIONAL<T_type>::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<T_type>::OPTIONAL(template_sel other_value)
 template<typename T_type>
 OPTIONAL<T_type>::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<T_type>::OPTIONAL(const OPTIONAL& other_value)
 
 template<typename T_type> template<typename T_tmp>
 OPTIONAL<T_type>::OPTIONAL(const OPTIONAL<T_tmp>& 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<T_type>::OPTIONAL(const OPTIONAL<T_tmp>& other_value)
 template<typename T_type>
 void OPTIONAL<T_type>::clean_up()
 {
+#ifdef TITAN_RUNTIME_2
   if (is_present()) {
     if (param_refs > 0) {
       optional_value->clean_up();
@@ -382,6 +453,11 @@ void OPTIONAL<T_type>::clean_up()
       optional_value = NULL;
     }
   }
+#else
+  if (OPTIONAL_PRESENT == optional_selection) {
+    delete optional_value;
+  }
+#endif
   optional_selection = OPTIONAL_UNBOUND;
 }
 
@@ -399,9 +475,13 @@ OPTIONAL<T_type>& OPTIONAL<T_type>::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<T_type>::operator=(const OPTIONAL<T_tmp>& 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<typename T_type> template <typename T_tmp>
 OPTIONAL<T_type>&
 OPTIONAL<T_type>::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<T_type>::operator=(const T_tmp& other_value)
 template<typename T_type>
 boolean OPTIONAL<T_type>::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<typename T_type>
 boolean OPTIONAL<T_type>::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<T_type>::is_equal(const OPTIONAL& other_value) const
 template<typename T_type> template <typename T_tmp>
 boolean OPTIONAL<T_type>::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<T_type>::is_equal(const T_tmp& other_value) const
 template<typename T_type> template <typename T_tmp>
 boolean OPTIONAL<T_type>::is_equal(const OPTIONAL<T_tmp>& 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<typename T_type>
 boolean OPTIONAL<T_type>::is_bound() const
 {
@@ -535,6 +668,7 @@ boolean OPTIONAL<T_type>::is_present() const
     return FALSE;
   }
 }
+#endif
 
 template<typename T_type>
 boolean OPTIONAL<T_type>::ispresent() const
@@ -543,19 +677,24 @@ boolean OPTIONAL<T_type>::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<typename T_type>
 optional_sel OPTIONAL<T_type>::get_selection() const
 {
@@ -568,11 +707,16 @@ optional_sel OPTIONAL<T_type>::get_selection() const
   }
   return OPTIONAL_UNBOUND;
 }
+#endif
 
 template<typename T_type>
 void OPTIONAL<T_type>::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<T_type>::set_param(Module_Param& param) {
 template<typename T_type>
 void OPTIONAL<T_type>::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<T_type>::decode_text(Text_Buf& text_buf)
 template<typename T_type>
 int OPTIONAL<T_type>::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<T_type>::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokeni
 template<typename T_type>
 int OPTIONAL<T_type>::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<typename T_type>
 void OPTIONAL<T_type>::add_refd_index(int index)
 {
@@ -681,15 +836,7 @@ void OPTIONAL<T_type>::remove_refd_index(int index)
   --param_refs;
   optional_value->remove_refd_index(index);
 }
-
-template<typename T_type>
-int OPTIONAL<T_type>::size_of()
-{
-  if (!is_present()) {
-    return 0;
-  }
-  return optional_value->size_of();
-}
+#endif
 
 template<typename T_type>
 OPTIONAL<T_type>::operator T_type&()
@@ -701,7 +848,11 @@ OPTIONAL<T_type>::operator T_type&()
 template<typename T_type>
 OPTIONAL<T_type>::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<T_type>::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<T_type>::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<T_type>::RAW_decode(const TTCN_Typedescriptor_t& p_td,
 
 template<typename T_type>
 int
-OPTIONAL<T_type>::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsigned int flavor, int indent) const
+OPTIONAL<T_type>::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<T_type>::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& buf, unsi
 template<typename T_type>
 int
 OPTIONAL<T_type>::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<T_type>::XER_check_any_elem(XmlReaderWrap& reader, const char* next_fie
 
 template<typename T_type>
 int
-OPTIONAL<T_type>::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor)
+OPTIONAL<T_type>::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<T_type>::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<T_type>::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<typename T_type>
 char ** OPTIONAL<T_type>::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<typename T_type>
 void OPTIONAL<T_type>::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<typename T_type>
 int OPTIONAL<T_type>::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<typename T_type>
 int OPTIONAL<T_type>::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 (file)
index 0000000..860e5c8
--- /dev/null
@@ -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 <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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_item_t> 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 (file)
index 0000000..c84bb97
--- /dev/null
@@ -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<profiler_line_data_t> lines;
+    /** Contains database entries for all the functions in this file (one entry
+      * for each function) */
+    Vector<profiler_function_data_t> 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_item_t> 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_item_t> call_stack_timer_db;
+};
+
+#endif /* PROFILER_HH */
+
index de50db9d15424242314aa365e653a0da8818a1fb..44ccdc483f527ab62c4abf98d57fc2f79626404a 100644 (file)
@@ -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
index 12a39eb1b783dfffdb31876267365f05a1438ba4..330f4f27b4fe44c75b3707cfae2a590c2d3216ef 100644 (file)
@@ -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;
index 5185032792198f26d0d5ac8fceabed457f91124a..62ea9fbf953588f53d5f1a6d1ba90ba31c57a8b7 100644 (file)
@@ -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)
index 9cf0f87333b0c9180c8f53e5a6a06786dd0a1b0f..e8ba46055e11f9e73cf9ea9e788dde461786e1fe 100644 (file)
@@ -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);
index ea0fdd88b3b9c3de2a6896cbaf7e7c121af114d2..4ea1a52c1005293ea63694d478ed70c00fc74689 100644 (file)
@@ -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. */
index 27c6da5c17c9bf420b7dc4f2edfb029d57833ce9..604ca048f95e60730eacac3fbd23723e45ac8eba 100644 (file)
 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
index a1bdde0e32b4f5775435f1e8f903060de8a1489e..4d96260b1aa2990abd05c792e4cf5af9a164cb6b 100644 (file)
@@ -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;
 }
 
-<SC_MODULE_PARAMETERS,SC_LOGGING>
+<SC_MODULE_PARAMETERS,SC_LOGGING,SC_PROFILER>
 {
 true           {
        yylval.bool_val = TRUE;
@@ -957,6 +964,16 @@ LOG_ALL    {
 [Dd]elete  return Delete;
 }
 
+<SC_PROFILER>
+{
+  [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;
+}
+
 <SC_EXECUTE>control            return ControlKeyword;
 
 <SC_EXTERNAL_COMMANDS>
index dad40098c8c825c59a6b40461026317985fb5900..92c2097982d567b54068a04efc47472b24058a26 100644 (file)
@@ -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 <int_val> IntegerValue
 %type <float_val> 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;
 }
 
index 7a2114789412f9091b868161e65dc71cd52147b4..c3389472e8623e0e31ea97b5d804de3f5930128d 100644 (file)
@@ -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<const Enum_Type *>(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<const Enum_Type *>(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<const Enum_Type *>(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<const Enum_Type *>(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<Record_Of_Type*>(get_at(aa_index))->set_size(0);
+      if (!get_at(aa_index)->is_optional()) {
+        static_cast<Record_Of_Type*>(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<Record_Of_Type *>(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<Record_Of_Type*>(get_at(aa_index)->get_opt_value());
+          }
+          else {
+            aa = static_cast<Record_Of_Type*>(get_at(aa_index));
+          }
           UNIVERSAL_CHARSTRING *new_elem = static_cast<UNIVERSAL_CHARSTRING *>
           (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<Record_Of_Type*>(get_at(0));
+      emb_val = new embed_values_dec_struct_t;
+      emb_val->embval_array = static_cast<Record_Of_Type*>(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<Enum_Type*>(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<Enum_Type*>(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 (; i<field_cnt; i++) {
-          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);
             }
-            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;
index 0ec550ab700fcb3901fe78015f5733194c218637..979fb5e2389141ca75419858751efbd2f411395e 100644 (file)
Binary files a/doc/License_handling_in_TITAN.doc and b/doc/License_handling_in_TITAN.doc differ
index d24f964790917179304682512872b53d1bf7be33..68ea35628ceaea02980281347ef0dfd5bfc1fdd3 100644 (file)
@@ -32,4 +32,5 @@ else
 #      cp asciiart/*.txt $(ETCDIR)/asciiart
        mkdir -p $(ETCDIR)/scripts
        cp scripts/*.py $(ETCDIR)/scripts
+       cp scripts/ttcn3_archive.pl $(BINDIR)
 endif
diff --git a/etc/scripts/ttcn3_archive.pl b/etc/scripts/ttcn3_archive.pl
new file mode 100644 (file)
index 0000000..058f5e3
--- /dev/null
@@ -0,0 +1,159 @@
+###############################################################################
+# 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
+###############################################################################
+#!/usr/bin/perl
+###############################################################################
+# This script is intended to archive the project hierarchy from a TPD file structure
+###############################################################################
+use 5.010;
+use strict;
+use warnings;
+use Cwd;
+use File::Copy;
+
+my $ttcn3_dir = $ENV{'TTCN3_DIR'};
+my $bindir = $ttcn3_dir . "/bin"; 
+my $home = cwd();
+my @list = readFile();
+my $tpd = getTPDFileName(\@list);
+chomp ($tpd);
+if (-l $tpd)  #get the path if it is a symlink
+{
+  $tpd = `readlink $tpd`;
+  chomp ($tpd);
+}
+my $root = getPathToRootDir(\@list); # get the workspace directory of the OS
+chomp ($root);
+chdir ($root) or die "cannot change: $!\n";
+my $cutstring = cwd; # this is string generated from the the absolut path to the workspace
+my $archiveDir = getArchiveDir(\@list); #directory to place the archive
+$archiveDir = $home . "/" .  $archiveDir;
+chomp ($archiveDir);
+my $createDir = "mkdir -p " .  $archiveDir;
+my $res = system($createDir);
+my $backupFileName = createBackupFileName();
+my $backupfile = $archiveDir . "/" . $backupFileName;
+if ($res != 0) { die (" creating directory " . $archiveDir ." failed\n"); }
+my $archive = $bindir . "/" . "ttcn3_makefilegen" ." -V -P " . $cutstring .  " -t " .  $tpd . " | xargs tar cfz ". $archiveDir . "/" .  $backupFileName . " 2> /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 = <FILE>;
+  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
index a599afddd723e69280230cc4fe3ab57730e3229d..d56c8e15fb04777f7b88c830a6001a7a7a65677c 100644 (file)
@@ -367,13 +367,22 @@ XML Schema for JunitLogger plugin
           </xs:restriction>
         </xs:simpleType>
       </xs:element>
-      <xs:element name="rerquiredConfiguration" minOccurs="1" maxOccurs="1">
-        <xs:simpleType>
-          <xs:restriction base="xs:normalizedString">
-            <xs:minLength value="1" />
-          </xs:restriction>
-        </xs:simpleType>
-      </xs:element>
+      <xs:choice>
+             <xs:element name="requiredConfiguration" minOccurs="1" maxOccurs="1">
+               <xs:simpleType>
+                 <xs:restriction base="xs:normalizedString">
+                   <xs:minLength value="1" />
+                 </xs:restriction>
+               </xs:simpleType>
+             </xs:element>
+             <xs:element name="rerquiredConfiguration" minOccurs="1" maxOccurs="1">
+               <xs:simpleType>
+                 <xs:restriction base="xs:normalizedString">
+                   <xs:minLength value="1" />
+                 </xs:restriction>
+               </xs:simpleType>
+             </xs:element>
+      </xs:choice>      
     </xs:sequence>
   </xs:complexType>
 
@@ -453,7 +462,7 @@ XML Schema for JunitLogger plugin
   <xs:complexType name="TopLevelProjectType">
   <!--
   This is an extra indirection level. It adds the "version" attribute to
-  ProjecType and the optional element "PackedReferencedProjects"
+  ProjectType and the optional element "PackedReferencedProjects"
   -->
        <xs:complexContent>
                <xs:extension base="ProjectType">         
index c4c266aec1d1afd11b8810b2e46d47e52d5e3375..36678584a8aaba7440509832829d0182cdad269f 100644 (file)
@@ -1114,49 +1114,6 @@ template RoI t_i10 :=  permutation((all from t_RoI2),100);
 error: at or before token `permutation': syntax error, unexpected PermutationKeyword
 <END_RESULT> 
 
-<END_TC>
-:exmp
-*---------------------------------------------------------------------*
-:h3. Component mapping: invalid ports
-.*---------------------------------------------------------------------*
-:xmp tab=0.
-
-<TC -Component mapping: invalid port  >
-
-<COMPILE>
-
-<MODULE TTCN test test.ttcn >
-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);
-
-}
-
-}
-<END_MODULE>
-
-<RESULT COUNT 2>
-Component type `@test.MTCType' does not have port with name `MyPCO_PT'
-<END_RESULT>
-<RESULT COUNT 1>
-Component type `@test.MTCType' does not have port with name `MyPCO_PT2'
-<END_RESULT>
-
 <END_TC>
 :exmp
 
index d08f2a23a9c0dd13008cbb4b946ec85c41539220..db2b40fc7bd0f54e4018c8565317a471f89a5ac2 100644 (file)
@@ -8609,4 +8609,35 @@ Temp.control
 <END_TC>
 :exmp.
 
+*-----------------------------------------------------------*
+:h3.Adhoc:: HT23335: Type Infinity is not a valid value for type `integer' which as subtype (-1..65535)  
+.*-----------------------------------------------------------*
+:xmp tab=0.
+<TC - HT23335: Type Infinity is not a valid value for type `integer' which as subtype (-1..65535)>
+
+<COMPILE>
+<VERDICT_LEAF FAIL>
+<MODULE TTCN Temp Temp.ttcn>
+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) };
+
+}
+<END_MODULE>
+<RESULT IF_FAIL COUNT 2>
+(?im)\Infinity is not a valid value for type\b
+<END_RESULT>
+<END_TC>
+:exmp.
+
 :etext.
index bb3ede923e0998f9e99459a563527c74d8ab2baf..458f786c0c7725b5e73773bf4e43fdc44ffa0591 100644 (file)
Binary files a/function_test/doc/TTCN3_Executor_TestReport.doc and b/function_test/doc/TTCN3_Executor_TestReport.doc differ
index 7d59c229b2d973bc42ed9da2158abe3e441d2074..be8c19348570b7609793f42f1e5d9dc99736f366 100644 (file)
@@ -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);
 }
 
-<SC_MODULE_PARAMETERS,SC_LOGGING>
+<SC_MODULE_PARAMETERS,SC_LOGGING,SC_PROFILER>
 {
 true   |
 false  RETURN(BooleanValue);
@@ -551,6 +558,16 @@ WARNING_UNQUALIFIED RETURN(LoggingBit);
 [Dd]elete RETURN(Delete);
 }
 
+<SC_PROFILER>
+{
+[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;
+}
+
 <SC_EXECUTE>control            RETURN(ControlKeyword);
 
 <SC_EXTERNAL_COMMANDS>
index f70b1606b8a01b6405d53f558c01a45682a12c44..496d4f3994ff8b7c949d82ec3f58e2af4899b305 100644 (file)
@@ -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 <int_val> IntegerValue
 %type <float_val> FloatValue KillTimerValue
 %type <str_val> 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:
index 9ce328c9d4807f87974f64ab4cc489b89c4b0d50..fc5cb934a87687ca7d03259fa0ad414fddc05121 100644 (file)
@@ -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 :=
+"<Outer attr='48'>one" &
+"<Bytes>DEADBEEF</Bytes>two" &
+"<Inner><num>3</num><str>abc</str></Inner>three" &
+"<Inner><num>4</num><str>def</str></Inner>four" &
+"<Inner><num>-6</num><str>red</str></Inner>five" &
+"<Inner><num>118</num><str>blue</str></Inner>six</Outer>\n";
+
+const universal charstring str_emb_array_w_holes :=
+"<Outer attr='48'>one" &
+"<Bytes>DEADBEEF</Bytes>" &
+"<Inner><num>3</num><str>abc</str></Inner>three" &
+"<Inner><num>4</num><str>def</str></Inner>" &
+"<Inner><num>-6</num><str>red</str></Inner>five" &
+"<Inner><num>118</num><str>blue</str></Inner></Outer>\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());
 }
 
 }
index 340501f72c2d10a8e1e5331ef4744c9314d8a539..6d9a50d4b15d0d2faf30e4981e65ed53123916ac 100644 (file)
@@ -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 (file)
index 0000000..843b772
--- /dev/null
@@ -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 (executable)
index 0000000..e587670
--- /dev/null
@@ -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 (file)
index 0000000..11d4230
--- /dev/null
@@ -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 (file)
index 0000000..28b6917
--- /dev/null
@@ -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 (file)
index 0000000..ae4a64a
--- /dev/null
@@ -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}});
+}
+
+}
index facd1dae64377bfe1fa825c50dc963ac7f4d20d8..f5f02fedf4d3f1d8b0d8e0e8e932055de5ab1aeb 100644 (file)
@@ -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
index 57fb440869841bcb13714c92fdff6886c6c611da..e98152720d581ef5a0f835866ac027ddfe8634ce 100644 (file)
@@ -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:
index 051955a15f00fc43d5a27f2042c6976c92f3318b..a4a5665c5a4805866d6c531844f76a8642fc4586 100644 (file)
@@ -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* 
index 18224c8711d10a17560d2ec16beaaf95c3e790c9..6064b626941174e88784b188f88dd6515d1e4f9b 100755 (executable)
@@ -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 ====================
   
index a1006992506a548d7029072a86b7b7844eec0c9e..962186e5f01466830567ebc96ef4f7bd204ee338 100644 (file)
@@ -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
index 81cb2fd2e02fdf8457b48aae6ed621a53296f735..e452ecc24dfe4054b0cadfdf8ce3b89ff3f7d62f 100755 (executable)
@@ -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());
 }
 
 
index f1f372c8c7c07d391b1ac804f68a53067a2ab397..21eef2829d9c1b36e7d0ea9318227633435ca88b 100755 (executable)
@@ -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";
index 654a1d7c719e0b9124831cec0319790cc5dc55fd..e4b9c7a2255f4a937a271e3348780f09cf917a19 100644 (file)
@@ -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:
index a3b9428e8f0a2e68eb03b865e8ec4cfd6ad8500d..eb0d2a5a66fbfa89157ab37222a99639f68e1702 100644 (file)
@@ -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 (file)
index 0000000..8cd9abc
--- /dev/null
@@ -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 (file)
index 0000000..426111b
--- /dev/null
@@ -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;
+}
+
+}
index fa9bfecbd2c7a73575b72211be60404b66707329..3fc889a28b89acb42ca429598d0118e6572da523 100644 (file)
                "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" : {
                        },
                        "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" : {
                        },
                        "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" : {
                        },
                        "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" : {
                        },
                        "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" : {
                        },
                        "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" : {
                        },
                        "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" : {
                        },
                        "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" : {
                        },
                        "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" : {
                        },
                        "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" : {
                                        "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 (file)
index 0000000..258f2a2
--- /dev/null
@@ -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 (file)
index 0000000..40a29b3
--- /dev/null
@@ -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"
+                               ]
+                       }
+               }
+       ]
+}
index a72bacd2a506a4405f1baa218e63f91f6643966c..30664bbb1f2ebec3dcfda293778df10f7f319c74 100755 (executable)
@@ -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 (file)
index 0000000..0be5148
--- /dev/null
@@ -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 (file)
index 0000000..534ec07
--- /dev/null
@@ -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 (file)
index 0000000..4b33888
--- /dev/null
@@ -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
index 7c3d3269cd294c7f47b591597e33cdf86a7d0656..b6ae4a648247aa1331bbc30c6fb24def072f14cc 100644 (file)
@@ -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 (file)
index 0000000..0532083
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+
+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 (file)
index 0000000..7ab618d
--- /dev/null
@@ -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
+
index f8827455e1748ec6e5ddf77e57ecd2d14bef5847..da16123a449949c148de06385b1bb5edbba86548 100644 (file)
                                        "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" : {
                                                "properties" : {
                                                        "bytes" : {
                                                                "type" : "string",
+                                                               "subType" : "octetstring",
                                                                "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$"
                                                        }
                                                },
                                        "Thin",
                                        "Medium",
                                        "Wide"
+                               ],
+                               "numericValues" : [
+                                       0,
+                                       1,
+                                       2
                                ]
                        },
                        "anytype" : {
                                                "properties" : {
                                                        "bitstring" : {
                                                                "type" : "string",
+                                                               "subType" : "bitstring",
                                                                "pattern" : "^[01]*$"
                                                        }
                                                },
                                "subType" : "record of",
                                "items" : {
                                        "type" : "string",
+                                       "subType" : "bitstring",
                                        "pattern" : "^[01]*$"
                                }
                        },
                                "subType" : "record of",
                                "items" : {
                                        "type" : "string",
+                                       "subType" : "hexstring",
                                        "pattern" : "^[0-9A-Fa-f]*$"
                                }
                        },
                                "subType" : "set of",
                                "items" : {
                                        "type" : "string",
+                                       "subType" : "octetstring",
                                        "pattern" : "^([0-9A-Fa-f][0-9A-Fa-f])*$"
                                }
                        },
                                                                        "Small",
                                                                        "Medium",
                                                                        "Large"
+                                                               ],
+                                                               "numericValues" : [
+                                                                       0,
+                                                                       1,
+                                                                       2
                                                                ]
                                                        },
                                                        "filled" : {
                        }
                },
                "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" : [
                                        {
                                        }
                                ]
                        },
-                       "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",
                                                        "blue",
                                                        "green",
                                                        "yellow"
+                                               ],
+                                               "numericValues" : [
+                                                       0,
+                                                       1,
+                                                       2,
+                                                       3
                                                ]
                                        }
                                },
                                        "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",
                                        "$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 (file)
index 0000000..52268ba
--- /dev/null
@@ -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"
+               }
+       ]
+}
index e54a5cbd3219af09e41ee682f02239536d4e2ee9..21eb94e5af1a538ed54b64ed96112d0d51866e58 100644 (file)
@@ -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 (file)
index 0000000..27c91bd
--- /dev/null
@@ -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"
+                               ]
+                       }
+               }
+       ]
+}
index 1ab9eecd8fe083787118b5b8af6f8ad5c8ddf7b4..aaa7e04d316b650004c6cbd8b3e4d7ece6873313 100644 (file)
@@ -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
index efa789f6eb597a366d8ddc7b7e0c52e1ced4811e..62c5615b969dfc39c458f69bc1d57249f37923e2 100755 (executable)
Binary files a/titan_executor_api/doc/Titan_Executor_API_User_Guide.doc and b/titan_executor_api/doc/Titan_Executor_API_User_Guide.doc differ
index be02514ee7798848025802e078cd10906b3a7366..00c44cc529d505b585acab59771ec5c99b70ad80 100644 (file)
@@ -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 (file)
index 0000000..b0e48bf
Binary files /dev/null and b/usrguide/PRI.doc differ
index b70d90274337724b9b0e26c81278a91ffe4de781..6d9e0e61f2044c2b981cb6ec4afec09665d603e6 100644 (file)
Binary files a/usrguide/apiguide.doc and b/usrguide/apiguide.doc differ
index f199061fb04c7cc41cd4a6ee2de78afc59154334..d530d55c31271dabbe32808e08cdfc5737fad0cb 100644 (file)
Binary files a/usrguide/installationguide.doc and b/usrguide/installationguide.doc differ
index 3703a434d4b0828f64206b6a18b15c000c2df8a3..4bc7ce3308253a4c88c9c24b94c0ebee8361d7cd 100644 (file)
Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ
index 6c6bbe792a2814057c443484bacef348924447f1..b9c5b49bcaf02c1f4c612b5cadf5d8d2506adab0 100644 (file)
Binary files a/usrguide/releasenotes.doc and b/usrguide/releasenotes.doc differ
index a31a339b25655fee18a81f70e7e97a58270f2d4f..da7dd72a28d15a2719d0a32bc9680a8633b60cb2 100644 (file)
Binary files a/usrguide/userguide.doc and b/usrguide/userguide.doc differ
This page took 0.310678 seconds and 5 git commands to generate.