From 970ed7958b7d4e41d36fd5904d645aa3aec9f992 Mon Sep 17 00:00:00 2001 From: Elemer Lelik Date: Thu, 15 Jan 2015 10:53:55 +0100 Subject: [PATCH] Titan Core Initial Contribution --- .gitignore | 10 + JNI/.gitignore | 2 + JNI/Makefile | 76 + JNI/jnimw.cc | 286 + JNI/jnimw.h | 92 + JNI/jninativelib.cc | 1495 + ...eclipse_titan_executor_jni_JNIMiddleWare.h | 316 + Makefile | 91 + Makefile.cfg | 359 + Makefile.genrules | 160 + README.cygwin | 116 + README.linux | 89 + common/.gitignore | 16 + common/CharCoding.hh | 31 + common/JSON_Tokenizer.cc | 373 + common/JSON_Tokenizer.hh | 160 + common/Makefile | 116 + common/ModuleVersion.cc | 44 + common/ModuleVersion.hh | 47 + common/NetworkHandler.cc | 440 + common/NetworkHandler.hh | 188 + common/Path2.cc | 97 + common/Path2.hh | 45 + common/Quadruple.cc | 619 + common/Quadruple.hh | 232 + common/cfg_process_utils.hh | 108 + common/config_preproc.cc | 379 + common/config_preproc.h | 98 + common/config_preproc_la.l | 370 + common/config_preproc_p.y | 365 + common/dbgnew.hh | 43 + common/hostid.c | 17 + common/license.c | 607 + common/license.h | 155 + common/memory.c | 929 + common/memory.h | 291 + common/new.cc | 86 + common/path.c | 232 + common/path.h | 86 + common/pattern.hh | 36 + common/pattern_la.l | 277 + common/pattern_p.y | 966 + common/pattern_uni.y | 653 + common/platform.h | 30 + common/static_check.h | 26 + common/ttcn3float.hh | 132 + common/usage_stats.cc | 306 + common/usage_stats.hh | 81 + common/userinfo.c | 63 + common/userinfo.h | 21 + common/version.h | 149 + common/version.py | 61 + common/version_internal.h | 257 + compiler2/.gitignore | 9 + compiler2/AST.cc | 1785 + compiler2/AST.hh | 560 + compiler2/Code.cc | 244 + compiler2/Code.hh | 55 + compiler2/CodeGenHelper.cc | 307 + compiler2/CodeGenHelper.hh | 96 + compiler2/CompField.cc | 205 + compiler2/CompField.hh | 101 + compiler2/CompType.cc | 664 + compiler2/CompType.hh | 176 + compiler2/CompilerError.cc | 325 + compiler2/CompilerError.hh | 105 + compiler2/Constraint.cc | 1137 + compiler2/Constraint.hh | 486 + compiler2/EnumItem.cc | 149 + compiler2/EnumItem.hh | 80 + compiler2/Identifier.cc | 1397 + compiler2/Identifier.hh | 118 + compiler2/Int.cc | 547 + compiler2/Int.hh | 104 + compiler2/Makefile | 192 + compiler2/PredefFunc.cc | 1103 + compiler2/PredefFunc.hh | 64 + compiler2/Real.cc | 90 + compiler2/Real.hh | 88 + compiler2/Setting.cc | 861 + compiler2/Setting.hh | 787 + compiler2/SigParam.cc | 267 + compiler2/SigParam.hh | 111 + compiler2/Stopwatch.cc | 35 + compiler2/Stopwatch.hh | 31 + compiler2/Type.cc | 6836 ++ compiler2/Type.hh | 1161 + compiler2/TypeCompat.cc | 881 + compiler2/TypeCompat.hh | 134 + compiler2/Type_chk.cc | 6443 ++ compiler2/Type_codegen.cc | 2984 + compiler2/Typestuff.cc | 1056 + compiler2/Typestuff.hh | 295 + compiler2/Value.cc | 13630 ++++ compiler2/Value.hh | 988 + compiler2/Valuestuff.cc | 1430 + compiler2/Valuestuff.hh | 319 + compiler2/XerAttributes.cc | 388 + compiler2/XerAttributes.hh | 207 + compiler2/asn1/.gitignore | 8 + compiler2/asn1/AST_asn1.cc | 2307 + compiler2/asn1/AST_asn1.hh | 675 + compiler2/asn1/Block.cc | 53 + compiler2/asn1/Block.hh | 58 + compiler2/asn1/Makefile | 61 + compiler2/asn1/OCSV.cc | 687 + compiler2/asn1/OCSV.hh | 80 + compiler2/asn1/Object.cc | 2175 + compiler2/asn1/Object.hh | 784 + compiler2/asn1/Object0.hh | 210 + compiler2/asn1/Ref.cc | 603 + compiler2/asn1/Ref.hh | 106 + compiler2/asn1/TableConstraint.cc | 304 + compiler2/asn1/TableConstraint.hh | 108 + compiler2/asn1/Tag.cc | 407 + compiler2/asn1/Tag.hh | 132 + compiler2/asn1/TokenBuf.cc | 644 + compiler2/asn1/TokenBuf.hh | 130 + compiler2/asn1/Type_parse.cc | 99 + compiler2/asn1/asn1.hh | 38 + compiler2/asn1/asn1_preparser.h | 23 + compiler2/asn1/asn1_preparser.l | 101 + compiler2/asn1/asn1la.l | 542 + compiler2/asn1/asn1p.y | 3977 ++ compiler2/asn1/asn1p_old.h | 46 + compiler2/compiler.1 | 352 + compiler2/datatypes.h | 183 + compiler2/encdec.c | 351 + compiler2/encdec.h | 40 + compiler2/enum.c | 1373 + compiler2/enum.h | 25 + compiler2/error.h | 127 + compiler2/functionref.c | 793 + compiler2/functionref.h | 25 + compiler2/main.cc | 1063 + compiler2/main.hh | 64 + compiler2/makefile.c | 3662 ++ compiler2/map.hh | 233 + compiler2/record.c | 6958 ++ compiler2/record.h | 25 + compiler2/record_of.c | 4731 ++ compiler2/record_of.h | 28 + compiler2/stack.hh | 98 + compiler2/string.cc | 591 + compiler2/string.hh | 264 + compiler2/subtype.cc | 3016 + compiler2/subtype.hh | 289 + compiler2/subtypestuff.cc | 796 + compiler2/subtypestuff.hh | 2231 + compiler2/tcov.xsd | 67 + compiler2/tcov.xsl | 90 + compiler2/tcov2lcov.cc | 392 + compiler2/tcov2lcov.hh | 51 + compiler2/titanver | 139 + compiler2/ttcn3/.gitignore | 19 + compiler2/ttcn3/AST_ttcn3.cc | 9569 +++ compiler2/ttcn3/AST_ttcn3.hh | 1773 + compiler2/ttcn3/ArrayDimensions.cc | 423 + compiler2/ttcn3/ArrayDimensions.hh | 125 + compiler2/ttcn3/Attributes.cc | 1394 + compiler2/ttcn3/Attributes.hh | 334 + compiler2/ttcn3/BerAST.cc | 35 + compiler2/ttcn3/BerAST.hh | 40 + compiler2/ttcn3/ILT.cc | 459 + compiler2/ttcn3/ILT.hh | 162 + compiler2/ttcn3/JsonAST.cc | 55 + compiler2/ttcn3/JsonAST.hh | 32 + compiler2/ttcn3/Makefile | 82 + compiler2/ttcn3/PatternString.cc | 523 + compiler2/ttcn3/PatternString.hh | 86 + compiler2/ttcn3/RawAST.cc | 295 + compiler2/ttcn3/RawAST.hh | 165 + compiler2/ttcn3/Statement.cc | 10270 +++ compiler2/ttcn3/Statement.hh | 1377 + compiler2/ttcn3/Templatestuff.cc | 1015 + compiler2/ttcn3/Templatestuff.hh | 419 + compiler2/ttcn3/TextAST.cc | 491 + compiler2/ttcn3/TextAST.hh | 92 + compiler2/ttcn3/Ttcn2Json.cc | 100 + compiler2/ttcn3/Ttcn2Json.hh | 49 + compiler2/ttcn3/TtcnTemplate.cc | 4634 ++ compiler2/ttcn3/TtcnTemplate.hh | 577 + compiler2/ttcn3/Ttcnstuff.cc | 2380 + compiler2/ttcn3/Ttcnstuff.hh | 706 + compiler2/ttcn3/charstring_la.l | 158 + compiler2/ttcn3/coding_attrib_la.l | 346 + compiler2/ttcn3/coding_attrib_p.y | 891 + compiler2/ttcn3/compiler.c | 385 + compiler2/ttcn3/compiler.h | 89 + compiler2/ttcn3/compiler.l | 1055 + compiler2/ttcn3/compiler.y | 9170 +++ compiler2/ttcn3/comptype_attrib_la.l | 243 + compiler2/ttcn3/port.c | 3019 + compiler2/ttcn3/port.h | 108 + compiler2/ttcn3/pstring_la.l | 644 + compiler2/ttcn3/rawAST.l | 683 + compiler2/ttcn3/rawAST.y | 1575 + compiler2/ttcn3/rawASTspec.h | 125 + compiler2/ttcn3/signature.c | 1121 + compiler2/ttcn3/signature.h | 60 + compiler2/ttcn3/ttcn3_preparser.h | 23 + compiler2/ttcn3/ttcn3_preparser.l | 109 + compiler2/ttcn3_makefilegen.1 | 154 + compiler2/union.c | 2771 + compiler2/union.h | 25 + compiler2/ustring.cc | 439 + compiler2/ustring.hh | 157 + compiler2/vector.hh | 334 + compiler2/xpather.cc | 1654 + compiler2/xpather.h | 123 + core/.gitignore | 23 + core/ASN_Any.cc | 114 + core/ASN_Any.hh | 49 + core/ASN_CharacterString.cc | 3576 + core/ASN_CharacterString.hh | 501 + core/ASN_EmbeddedPDV.cc | 3595 + core/ASN_EmbeddedPDV.hh | 494 + core/ASN_External.cc | 3679 ++ core/ASN_External.hh | 475 + core/ASN_Null.cc | 588 + core/ASN_Null.hh | 136 + core/Addfunc.cc | 3143 + core/Addfunc.hh | 469 + core/Array.cc | 76 + core/Array.hh | 1955 + core/BER.cc | 673 + core/BER.hh | 250 + core/Basetype.cc | 1184 + core/Basetype.hh | 1021 + core/Bitstring.cc | 1933 + core/Bitstring.hh | 303 + core/Boolean.cc | 1134 + core/Boolean.hh | 189 + core/Charstring.cc | 2694 + core/Charstring.hh | 472 + core/Communication.cc | 1864 + core/Communication.hh | 208 + core/Component.cc | 748 + core/Component.hh | 177 + core/Default.cc | 660 + core/Default.hh | 183 + core/Encdec.cc | 1310 + core/Encdec.hh | 418 + core/Error.cc | 415 + core/Error.hh | 41 + core/Event_Handler.hh | 74 + core/Fd_And_Timeout_User.hh | 552 + core/Float.cc | 1436 + core/Float.hh | 249 + core/Hexstring.cc | 1816 + core/Hexstring.hh | 258 + core/ILoggerPlugin.hh | 68 + core/Integer.cc | 2189 + core/Integer.hh | 334 + core/JSON.cc | 49 + core/JSON.hh | 97 + core/LegacyLogger.cc | 2236 + core/LegacyLogger.hh | 99 + core/Logger.cc | 1562 + core/Logger.hh | 844 + core/LoggerPlugin.cc | 129 + core/LoggerPlugin.hh | 69 + core/LoggerPluginManager.cc | 1811 + core/LoggerPluginManager.hh | 303 + core/LoggerPlugin_dynamic.cc | 108 + core/LoggerPlugin_static.cc | 45 + core/LoggingBits.cc | 152 + core/LoggingBits.hh | 89 + core/LoggingParam.hh | 71 + core/Makefile | 357 + core/Message_types.hh | 113 + core/Module_list.cc | 1116 + core/Module_list.hh | 203 + core/Objid.cc | 906 + core/Objid.hh | 151 + core/Octetstring.cc | 2041 + core/Octetstring.hh | 283 + core/Optional.hh | 976 + core/Parallel_main.cc | 255 + core/Param_Types.cc | 487 + core/Param_Types.hh | 589 + core/Parameters.h | 43 + core/Port.cc | 2413 + core/Port.hh | 328 + core/RAW.cc | 435 + core/RAW.hh | 211 + core/RInt.cc | 291 + core/RInt.hh | 67 + core/Runtime.cc | 2951 + core/Runtime.hh | 337 + core/Single_main.cc | 284 + core/Snapshot.cc | 1215 + core/Snapshot.hh | 32 + core/String_struct.hh | 85 + core/Struct_of.cc | 1428 + core/Struct_of.hh | 77 + core/TCov.cc | 226 + core/TCov.hh | 105 + core/TEXT.cc | 278 + core/TEXT.hh | 127 + core/TTCN3.hh | 74 + core/Template.cc | 2911 + core/Template.hh | 523 + core/Textbuf.cc | 399 + core/Textbuf.hh | 68 + core/Timer.cc | 300 + core/Timer.hh | 107 + core/TitanLoggerApi.xsd | 950 + core/TitanLoggerControl.ttcn | 238 + core/TitanLoggerControlImpl.cc | 173 + core/Types.h | 120 + core/Universal_charstring.cc | 4125 ++ core/Universal_charstring.hh | 614 + core/VIRAG.asn | 115 + core/Vector.hh | 217 + core/Verdicttype.cc | 777 + core/Verdicttype.hh | 176 + core/XER.cc | 158 + core/XER.hh | 470 + core/XmlReader.cc | 490 + core/XmlReader.hh | 300 + core/config_process.l | 1393 + core/config_process.y | 2247 + core/gccversion.c | 82 + core/license_gen.c | 85 + core/simplify.pl | 41 + core2/.gitignore | 12 + core2/Basetype2.cc | 5867 ++ core2/Makefile | 33 + doc/License_handling_in_TITAN.doc | Bin 0 -> 147968 bytes doc/asn1parser/asn1_jackson.vsd | Bin 0 -> 930304 bytes doc/asn1parser/asn1p.vsd | Bin 0 -> 353280 bytes doc/parallelarch/.gitignore | 6 + doc/parallelarch/Makefile | 50 + doc/parallelarch/connect_op.eps | 261 + doc/parallelarch/connect_op.msc | Bin 0 -> 5008 bytes doc/parallelarch/connect_op_local.eps | 226 + doc/parallelarch/connect_op_local.msc | Bin 0 -> 5008 bytes doc/parallelarch/create_op.eps | 235 + doc/parallelarch/create_op.msc | Bin 0 -> 5800 bytes doc/parallelarch/creating_MTC.eps | 249 + doc/parallelarch/creating_MTC.msc | Bin 0 -> 6064 bytes doc/parallelarch/disconnect_op.eps | 269 + doc/parallelarch/disconnect_op.msc | Bin 0 -> 5008 bytes doc/parallelarch/disconnect_op_local.eps | 226 + doc/parallelarch/disconnect_op_local.msc | Bin 0 -> 5008 bytes doc/parallelarch/done_op.eps | 217 + doc/parallelarch/done_op.msc | Bin 0 -> 3952 bytes doc/parallelarch/erilogo_black_on_white.eps | 1761 + doc/parallelarch/eripage.sty | 234 + doc/parallelarch/executing_control.eps | 277 + doc/parallelarch/executing_control.msc | Bin 0 -> 6064 bytes doc/parallelarch/executing_testcase.eps | 247 + doc/parallelarch/executing_testcase.msc | Bin 0 -> 6064 bytes doc/parallelarch/killing_TC.eps | 198 + doc/parallelarch/killing_TC.msc | Bin 0 -> 4216 bytes doc/parallelarch/log.eps | 186 + doc/parallelarch/log.msc | Bin 0 -> 3424 bytes doc/parallelarch/map_op.eps | 206 + doc/parallelarch/map_op.msc | Bin 0 -> 4744 bytes doc/parallelarch/parallel.tex | 730 + doc/parallelarch/parallel_ttcn3.sdt | 67 + doc/parallelarch/parallelarch.eps | 770 + doc/parallelarch/parallelarch.fig | 366 + doc/parallelarch/running_op.eps | 201 + doc/parallelarch/running_op.msc | Bin 0 -> 3688 bytes doc/parallelarch/send_to_op.eps | 247 + doc/parallelarch/start_op.eps | 227 + doc/parallelarch/start_op.msc | Bin 0 -> 5800 bytes doc/parallelarch/starting_HC.eps | 275 + doc/parallelarch/starting_HC.msc | Bin 0 -> 4480 bytes doc/parallelarch/state_mach_conn_endpoint.dot | 51 + doc/parallelarch/state_mach_conn_endpoint.eps | 1144 + doc/parallelarch/state_mach_conn_mc.dot | 54 + doc/parallelarch/state_mach_conn_mc.eps | 1202 + doc/parallelarch/state_mach_hc.eps | 368 + doc/parallelarch/state_mach_hc.fig | 82 + doc/parallelarch/state_mach_hc_mc.dot | 47 + doc/parallelarch/state_mach_hc_mc.eps | 1445 + doc/parallelarch/state_mach_mapping_mc.dot | 48 + doc/parallelarch/state_mach_mapping_mc.eps | 975 + doc/parallelarch/state_mach_mc.dot | 69 + doc/parallelarch/state_mach_mc.eps | 2518 + doc/parallelarch/state_mach_mtc.eps | 307 + doc/parallelarch/state_mach_mtc.fig | 67 + doc/parallelarch/state_mach_ptc_mc.dot | 71 + doc/parallelarch/state_mach_ptc_mc.eps | 2364 + doc/parallelarch/stop_op.eps | 251 + doc/parallelarch/stop_op.msc | Bin 0 -> 4216 bytes doc/parallelarch/stop_op1.eps | 213 + doc/parallelarch/unmap_op.eps | 245 + doc/parallelarch/unmap_op.msc | Bin 0 -> 4744 bytes doc/pri/PRI_1_10_A.doc | Bin 0 -> 122880 bytes doc/pri/PRI_1_9_B.doc | Bin 0 -> 83456 bytes doc/pri/PRI_2_1_A.doc | Bin 0 -> 161280 bytes doc/pri/PRI_2_2_A.doc | Bin 0 -> 129536 bytes doc/pri/PRI_3_1_A.doc | Bin 0 -> 188416 bytes doc/pri/PRI_3_2_A.doc | Bin 0 -> 168448 bytes doc/pri/PRI_4_1_A.doc | Bin 0 -> 109056 bytes doc/pri/PRI_4_2_A.doc | Bin 0 -> 91648 bytes doc/pri/PRI_5_1_A.doc | Bin 0 -> 114688 bytes doc/pri/PRI_8_G.doc | Bin 0 -> 120320 bytes doc/pri/PRI_8_H.doc | Bin 0 -> 131584 bytes etc/Makefile | 35 + etc/TXDSample.xml | 66 + etc/autotest/.titan_builder-esekilxxen1843 | 39 + etc/autotest/.titan_builder-esekits1064 | 30 + etc/autotest/.titan_builder-esekits3013 | 33 + etc/autotest/.titan_builder-esekits5013 | 39 + etc/autotest/.titan_builder-rhea | 26 + etc/autotest/.titan_builder-tcclab1 | 23 + etc/autotest/README | 286 + etc/autotest/freshbuild.sh | 17 + etc/autotest/mountall.sh | 15 + etc/autotest/product_handler.py | 282 + etc/autotest/titan_builder.py | 1123 + etc/autotest/titan_builder.sh | 18 + etc/autotest/titan_builder_cfg.py | 785 + etc/autotest/titan_publisher.py | 1286 + etc/autotest/web/titan_builder.css | 46 + etc/autotest/web/titan_builder.php | 228 + etc/download_stats/README | 15 + etc/download_stats/addDownloadStats.sh | 37 + etc/download_stats/addDownloadStats.xsl | 61 + etc/download_stats/eclipsestats-old.php | 33 + etc/download_stats/eclipsestats.php | 8 + etc/howto/pqb_stats_howto.txt | 17 + etc/howto/titan_release_howto.txt | 293 + etc/scripts/cfg_msg_maker.py | 30 + etc/scripts/stacklogger.pl | 686 + etc/scripts/tpd_graph_xml2dot.py | 23 + etc/skeleton/altstep.skeleton | 30 + etc/skeleton/asn1_module.skeleton | 13 + etc/skeleton/component_type.skeleton | 30 + etc/skeleton/constant.skeleton | 16 + etc/skeleton/control_part.skeleton | 14 + etc/skeleton/data_type.skeleton | 56 + etc/skeleton/function.skeleton | 147 + etc/skeleton/import_part.skeleton | 18 + etc/skeleton/module_param.skeleton | 8 + etc/skeleton/port_type.skeleton | 22 + etc/skeleton/signature.skeleton | 7 + etc/skeleton/template.skeleton | 71 + etc/skeleton/testcase.skeleton | 31 + etc/skeleton/ttcn3_module.skeleton | 97 + etc/solaris/README | 17 + etc/solaris/build.sh | 143 + etc/solaris/get.sh | 51 + etc/solaris/path.sh | 36 + etc/solaris/titan.sh | 24 + etc/xsd/Junit.xsd | 52 + etc/xsd/TPD.xsd | 467 + etc/xsd/TXD.xsd | 174 + function_test/BER_EncDec/.gitignore | 16 + .../BER_EncDec/BER_EncDec_TD.fast_script | 11118 ++++ function_test/BER_EncDec/BER_EncDec_TD.script | 54322 ++++++++++++++++ function_test/BER_EncDec/Makefile | 143 + function_test/BER_EncDec/Temp.cfg | 15 + function_test/BER_EncDec/run_test | 7 + function_test/Config_Parser/.gitignore | 14 + .../Config_Parser/Logging_1_TD.script | 2530 + .../Config_Parser/OrderedInclude.script | 965 + .../PreprocessingCfgFiles_TD.script | 1839 + function_test/Config_Parser/begin_script.sh | 12 + function_test/Config_Parser/end_script.sh | 12 + function_test/Config_Parser/extfunc.cc | 52 + function_test/Config_Parser/run_test | 32 + function_test/Config_Parser/run_test_all | 16 + function_test/Makefile | 93 + function_test/RAW_EncDec/.gitignore | 10 + function_test/RAW_EncDec/Makefile | 142 + .../RAW_EncDec/RAW_EncDec_TD.fast_script | 7340 +++ function_test/RAW_EncDec/RAW_EncDec_TD.script | 13673 ++++ function_test/RAW_EncDec/Temp.cfg | 15 + function_test/RAW_EncDec/run_test | 7 + function_test/README.txt | 35 + function_test/Semantic_Analyser/.gitignore | 11 + .../Semantic_Analyser/ASN_SA_1_TD.script | 7136 ++ .../ASN_SA_asn1adhoc_TD.script | 408 + .../Semantic_Analyser/Makefile.semantic | 14 + .../Semantic_Analyser/SA_6_TD.script | 6327 ++ .../Semantic_Analyser/TTCN3_SA_10_TD.script | 2099 + .../Semantic_Analyser/TTCN3_SA_11_TD.script | 326 + .../TTCN3_SA_12_TD.script_not_running | 1559 + .../Semantic_Analyser/TTCN3_SA_13_TD.script | 1193 + .../Semantic_Analyser/TTCN3_SA_1_TD.script | 11143 ++++ .../Semantic_Analyser/TTCN3_SA_3_TD.script | 9547 +++ .../Semantic_Analyser/TTCN3_SA_4_TD.script | 6080 ++ .../Semantic_Analyser/TTCN3_SA_5_TD.script | 10052 +++ .../Semantic_Analyser/TTCN3_SA_6_TD.script | 16763 +++++ .../Semantic_Analyser/TTCN3_SA_7_TD.script | 2196 + .../Semantic_Analyser/TTCN3_SA_9_TD.script | 4918 ++ .../TTCN3_SA_ttcn3adhoc_TD.script | 8612 +++ function_test/Semantic_Analyser/common.mk | 121 + function_test/Semantic_Analyser/cw.pl | 374 + function_test/Semantic_Analyser/defpars/t | 9 + function_test/Semantic_Analyser/encode/t | 9 + .../Semantic_Analyser/float/run_test_all | 3 + function_test/Semantic_Analyser/float/t | 9 + function_test/Semantic_Analyser/harness.pl | 52 + .../import_of_iports/run_test_all | 3 + .../Semantic_Analyser/import_of_iports/t | 9 + .../Semantic_Analyser/options/.gitignore | 1 + .../Semantic_Analyser/options/run_test_all | 23 + function_test/Semantic_Analyser/param/t | 9 + function_test/Semantic_Analyser/run_test | 37 + function_test/Semantic_Analyser/run_test_all | 16 + .../Semantic_Analyser/ver/.gitignore | 5 + .../Semantic_Analyser/ver/run_test_all | 3 + function_test/Semantic_Analyser/ver/t | 9 + .../Semantic_Analyser/xer/.gitignore | 5 + .../Semantic_Analyser/xer/run_test_all | 3 + function_test/Semantic_Analyser/xer/t | 9 + function_test/Text_EncDec/.gitignore | 9 + function_test/Text_EncDec/Makefile | 143 + .../Text_EncDec/TEXT_1_TD.fast_script | 1218 + function_test/Text_EncDec/TEXT_1_TD.script | 2051 + function_test/Text_EncDec/Temp.cfg | 15 + function_test/Text_EncDec/run_test | 7 + function_test/Tools/SAtester | 286 + function_test/Tools/SAtester.pl | 954 + function_test/XER_EncDec/Makefile | 142 + function_test/XER_EncDec/Temp.cfg | 15 + function_test/XER_EncDec/XER_EncDec_TD.script | 1236 + function_test/XER_EncDec/run_test | 6 + .../doc/TTCN3_Executor_TestReport.doc | Bin 0 -> 1476608 bytes hello/Makefile | 32 + hello/MyExample.cfg | 14 + hello/MyExample.ttcn | 46 + hello/PCOType.cc | 114 + hello/PCOType.hh | 52 + help/.gitignore | 2 + help/Makefile | 83 + help/chm_refact.sh | 65 + help/docs/TTCN-3_Naming_convention.doc | Bin 0 -> 524288 bytes help/images/ao.jpg | Bin 0 -> 1155 bytes help/images/left.jpg | Bin 0 -> 1184 bytes help/images/right.jpg | Bin 0 -> 1129 bytes help/images/titan.gif | Bin 0 -> 25213 bytes help/images/titan_511x511.png | Bin 0 -> 21524 bytes help/images/titan_icon.gif | Bin 0 -> 40926 bytes help/images/titan_icon_transparent.gif | Bin 0 -> 40926 bytes help/images/titan_old.gif | Bin 0 -> 54199 bytes help/images/titan_selected.gif | Bin 0 -> 5780 bytes help/images/titan_text.gif | Bin 0 -> 9746 bytes help/images/titan_text_transparent.gif | Bin 0 -> 9746 bytes help/images/titan_transparent.gif | Bin 0 -> 46946 bytes help/images/up.jpg | Bin 0 -> 1146 bytes help/info/BNF.html | 7422 +++ help/info/action.html | 91 + help/info/activate.html | 80 + help/info/address.html | 71 + help/info/alive.html | 106 + help/info/all.html | 70 + help/info/alt.html | 104 + help/info/altstep.html | 125 + help/info/and.html | 66 + help/info/and4b.html | 80 + help/info/any.html | 72 + help/info/anytype.html | 110 + help/info/bit2hex.html | 71 + help/info/bit2int.html | 64 + help/info/bit2oct.html | 66 + help/info/bit2str.html | 66 + help/info/bitstring.html | 162 + help/info/boolean.html | 72 + help/info/break.html | 97 + help/info/call.html | 251 + help/info/case.html | 42 + help/info/catch.html | 165 + help/info/char.html | 63 + help/info/char2int.html | 64 + help/info/char2oct.html | 67 + help/info/charstring.html | 208 + help/info/check.html | 173 + help/info/clear.html | 83 + help/info/complement.html | 62 + help/info/component.html | 107 + help/info/connect.html | 89 + help/info/const.html | 378 + help/info/continue.html | 75 + help/info/control.html | 79 + help/info/create.html | 99 + help/info/deactivate.html | 78 + help/info/decode_base64.html | 65 + help/info/decvalue.html | 69 + help/info/default.html | 74 + help/info/disconnect.html | 86 + help/info/display.html | 74 + help/info/do.html | 82 + help/info/done.html | 124 + help/info/else.html | 62 + help/info/encode.html | 77 + help/info/encode_base64.html | 68 + help/info/encvalue.html | 69 + help/info/enumerated.html | 97 + help/info/error.html | 73 + help/info/except.html | 67 + help/info/exception.html | 57 + help/info/execute.html | 79 + help/info/extension.html | 89 + help/info/external.html | 62 + help/info/fail.html | 68 + help/info/false.html | 62 + help/info/float.html | 133 + help/info/float2int.html | 63 + help/info/float2str.html | 63 + help/info/for.html | 90 + help/info/friend.html | 95 + help/info/from.html | 65 + help/info/function.html | 190 + help/info/get_stringencoding.html | 64 + help/info/getcall.html | 150 + help/info/getreply.html | 165 + help/info/getverdict.html | 71 + help/info/goto.html | 70 + help/info/group.html | 98 + help/info/hex2bit.html | 69 + help/info/hex2int.html | 64 + help/info/hex2oct.html | 68 + help/info/hex2str.html | 65 + help/info/hexstring.html | 163 + help/info/if.html | 167 + help/info/ifpresent.html | 62 + help/info/import.html | 306 + help/info/in.html | 67 + help/info/inconc.html | 68 + help/info/infinity.html | 91 + help/info/inout.html | 67 + help/info/int2bit.html | 66 + help/info/int2char.html | 67 + help/info/int2float.html | 62 + help/info/int2hex.html | 66 + help/info/int2oct.html | 68 + help/info/int2str.html | 67 + help/info/int2unichar.html | 64 + help/info/integer.html | 112 + help/info/interleave.html | 104 + help/info/isbound.html | 82 + help/info/ischosen.html | 78 + help/info/ispresent.html | 79 + help/info/isvalue.html | 81 + help/info/kill.html | 97 + help/info/killed.html | 119 + help/info/label.html | 70 + help/info/language.html | 58 + help/info/length.html | 85 + help/info/lengthof.html | 81 + help/info/log.html | 93 + help/info/map.html | 93 + help/info/match.html | 81 + help/info/message.html | 55 + help/info/mixed.html | 66 + help/info/mod.html | 68 + help/info/modifies.html | 76 + help/info/module.html | 101 + help/info/modulepar.html | 84 + help/info/mtc.html | 66 + help/info/noblock.html | 58 + help/info/none.html | 68 + help/info/not.html | 64 + help/info/not4b.html | 77 + help/info/nowait.html | 57 + help/info/null.html | 71 + help/info/objid.html | 98 + help/info/oct2bit.html | 66 + help/info/oct2char.html | 67 + help/info/oct2hex.html | 66 + help/info/oct2int.html | 65 + help/info/oct2str.html | 70 + help/info/oct2unichar.html | 68 + help/info/octetstring.html | 195 + help/info/of.html | 61 + help/info/omit.html | 76 + help/info/on.html | 61 + help/info/operators.html | 234 + help/info/optional.html | 60 + help/info/or.html | 66 + help/info/or4b.html | 80 + help/info/out.html | 67 + help/info/override.html | 55 + help/info/param.html | 58 + help/info/pass.html | 68 + help/info/pattern.html | 57 + help/info/permutation.html | 72 + help/info/port.html | 266 + help/info/private.html | 78 + help/info/procedure.html | 55 + help/info/public.html | 78 + help/info/raise.html | 106 + help/info/read.html | 100 + help/info/receive.html | 150 + help/info/record.html | 170 + help/info/recursive.html | 57 + help/info/regexp.html | 71 + help/info/rem.html | 68 + help/info/remove_bom.html | 62 + help/info/repeat.html | 65 + help/info/replace.html | 79 + help/info/reply.html | 146 + help/info/return.html | 64 + help/info/rnd.html | 67 + help/info/running.html | 183 + help/info/runs.html | 60 + help/info/select.html | 128 + help/info/self.html | 66 + help/info/send.html | 116 + help/info/sender.html | 59 + help/info/set.html | 165 + help/info/setverdict.html | 76 + help/info/signature.html | 171 + help/info/sizeof.html | 98 + help/info/start.html | 232 + help/info/stop.html | 258 + help/info/str2bit.html | 67 + help/info/str2float.html | 66 + help/info/str2hex.html | 69 + help/info/str2int.html | 69 + help/info/str2oct.html | 67 + help/info/subset.html | 63 + help/info/substr.html | 67 + help/info/superset.html | 63 + help/info/system.html | 65 + help/info/template.html | 214 + help/info/testcase.html | 118 + help/info/testcasename.html | 82 + help/info/timeout.html | 117 + help/info/timer.html | 128 + help/info/to.html | 60 + help/info/trigger.html | 164 + help/info/true.html | 62 + help/info/type.html | 142 + help/info/unichar2char.html | 63 + help/info/unichar2int.html | 64 + help/info/unichar2oct.html | 69 + help/info/union.html | 109 + help/info/universal.html | 169 + help/info/unmap.html | 87 + help/info/value.html | 70 + help/info/valueof.html | 83 + help/info/var.html | 348 + help/info/variant.html | 105 + help/info/verdicttype.html | 76 + help/info/while.html | 78 + help/info/with.html | 98 + help/info/xor.html | 66 + help/info/xor4b.html | 80 + help/titan.chm | Bin 0 -> 290706 bytes help/titan.hhc | 804 + help/titan.hhp | 215 + help/titan_index.html | 391 + help/titan_main.html | 121 + help/ttcn3_help | 118 + langviz/.gitignore | 11 + langviz/Grammar.cc | 159 + langviz/Grammar.hh | 55 + langviz/Graph.cc | 36 + langviz/Graph.hh | 19 + langviz/Iterator.cc | 63 + langviz/Iterator.hh | 43 + langviz/Makefile | 50 + langviz/Node.cc | 71 + langviz/Node.hh | 40 + langviz/Rule.cc | 109 + langviz/Rule.hh | 76 + langviz/Symbol.cc | 184 + langviz/Symbol.hh | 132 + langviz/bison_la.l | 647 + langviz/bison_p.y | 397 + langviz/error.c | 87 + langviz/error.h | 107 + langviz/main.cc | 46 + license/.gitignore | 3 + license/Makefile | 40 + license/Makefile_renew_license | 27 + license/license.dat | 15 + license/license_gen.c | 605 + license/renew_license.c | 157 + license/renew_license.html | 37 + loggerplugins/JUnitLogger/.gitignore | 3 + loggerplugins/JUnitLogger/JUnitLogger.cc | 309 + loggerplugins/JUnitLogger/JUnitLogger.hh | 49 + loggerplugins/JUnitLogger/Makefile | 96 + loggerplugins/Makefile | 12 + loggerplugins/TSTLogger/.gitignore | 3 + loggerplugins/TSTLogger/Makefile | 96 + loggerplugins/TSTLogger/TSTLogger.cc | 628 + loggerplugins/TSTLogger/TSTLogger.hh | 81 + makefiles/Makefile.personal.MinGW | 3 + makefiles/Makefile.personal.bangjohansen | 32 + makefiles/Makefile.personal.cygwin15 | 29 + makefiles/Makefile.personal.ehubuux110 | 23 + ...le.personal.esekilxxen1843.rnd.ericsson.se | 16 + makefiles/Makefile.personal.esekits1024 | 33 + makefiles/Makefile.personal.esekits1080 | 18 + makefiles/Makefile.personal.esekits3013 | 18 + makefiles/Makefile.personal.tcclab1 | 32 + makefiles/Makefile.personal.tcclab2 | 33 + makefiles/Makefile.personal.tcclab3 | 28 + makefiles/Makefile.personal.tcclab4 | 28 + makefiles/Makefile.personal.tcclab5 | 24 + makefiles/Makefile.personal.tcclab6 | 34 + mctr2/Makefile | 27 + mctr2/cli/.gitignore | 7 + mctr2/cli/Cli.cc | 1073 + mctr2/cli/Cli.h | 202 + mctr2/cli/Makefile | 55 + mctr2/cli/config_read.l | 941 + mctr2/cli/config_read.y | 1070 + mctr2/editline/.gitignore | 2 + mctr2/editline/Makefile | 80 + mctr2/editline/libedit/.gitignore | 8 + mctr2/editline/libedit/COPYING | 30 + mctr2/editline/libedit/ChangeLog | 294 + mctr2/editline/libedit/INSTALL | 229 + mctr2/editline/libedit/Makefile.am | 8 + mctr2/editline/libedit/Makefile.in | 780 + mctr2/editline/libedit/THANKS | 1 + mctr2/editline/libedit/acinclude.m4 | 85 + mctr2/editline/libedit/aclocal.m4 | 8945 +++ mctr2/editline/libedit/config.guess | 1502 + mctr2/editline/libedit/config.h.in | 278 + mctr2/editline/libedit/config.sub | 1714 + mctr2/editline/libedit/configure | 14480 ++++ mctr2/editline/libedit/configure.ac | 94 + mctr2/editline/libedit/depcomp | 630 + mctr2/editline/libedit/doc/.gitignore | 3 + mctr2/editline/libedit/doc/Makefile.am | 33 + mctr2/editline/libedit/doc/Makefile.in | 510 + mctr2/editline/libedit/examples/.gitignore | 7 + mctr2/editline/libedit/examples/Makefile.am | 14 + mctr2/editline/libedit/examples/Makefile.in | 514 + mctr2/editline/libedit/install-sh | 520 + mctr2/editline/libedit/libedit.pc.in | 12 + mctr2/editline/libedit/ltmain.sh | 8413 +++ mctr2/editline/libedit/missing | 376 + mctr2/editline/libedit/src/.gitignore | 13 + mctr2/editline/libedit/src/Makefile.am | 57 + mctr2/editline/libedit/src/Makefile.in | 664 + mctr2/editline/libedit/src/chared.c | 784 + mctr2/editline/libedit/src/chared.h | 166 + mctr2/editline/libedit/src/chartype.c | 360 + mctr2/editline/libedit/src/chartype.h | 249 + mctr2/editline/libedit/src/common.c | 921 + .../editline/libedit/src/editline/readline.h | 221 + mctr2/editline/libedit/src/el.c | 607 + mctr2/editline/libedit/src/el.h | 161 + mctr2/editline/libedit/src/el_term.h | 134 + mctr2/editline/libedit/src/eln.c | 365 + mctr2/editline/libedit/src/emacs.c | 508 + mctr2/editline/libedit/src/fgetln.c | 107 + mctr2/editline/libedit/src/filecomplete.c | 566 + mctr2/editline/libedit/src/filecomplete.h | 44 + mctr2/editline/libedit/src/hist.c | 223 + mctr2/editline/libedit/src/hist.h | 87 + mctr2/editline/libedit/src/histedit.h | 322 + mctr2/editline/libedit/src/history.c | 1097 + mctr2/editline/libedit/src/key.c | 665 + mctr2/editline/libedit/src/key.h | 80 + mctr2/editline/libedit/src/makelist | 259 + mctr2/editline/libedit/src/map.c | 1421 + mctr2/editline/libedit/src/map.h | 77 + mctr2/editline/libedit/src/parse.c | 285 + mctr2/editline/libedit/src/parse.h | 48 + mctr2/editline/libedit/src/prompt.c | 199 + mctr2/editline/libedit/src/prompt.h | 60 + mctr2/editline/libedit/src/read.c | 714 + mctr2/editline/libedit/src/read.h | 50 + mctr2/editline/libedit/src/readline.c | 2235 + mctr2/editline/libedit/src/refresh.c | 1183 + mctr2/editline/libedit/src/refresh.h | 59 + mctr2/editline/libedit/src/search.c | 639 + mctr2/editline/libedit/src/search.h | 66 + mctr2/editline/libedit/src/shlib_version | 5 + mctr2/editline/libedit/src/sig.c | 200 + mctr2/editline/libedit/src/sig.h | 72 + mctr2/editline/libedit/src/strlcat.c | 74 + mctr2/editline/libedit/src/strlcpy.c | 70 + mctr2/editline/libedit/src/sys.h | 161 + mctr2/editline/libedit/src/term.c | 1745 + mctr2/editline/libedit/src/tokenizer.c | 453 + mctr2/editline/libedit/src/tty.c | 1349 + mctr2/editline/libedit/src/tty.h | 481 + mctr2/editline/libedit/src/unvis.c | 345 + mctr2/editline/libedit/src/vi.c | 1159 + mctr2/editline/libedit/src/vis.c | 423 + mctr2/editline/libedit/src/vis.h | 88 + mctr2/editline/libedit/src/wcsdup.c | 44 + mctr2/mctr/.gitignore | 7 + mctr2/mctr/MainController.cc | 6291 ++ mctr2/mctr/MainController.h | 614 + mctr2/mctr/Makefile | 94 + mctr2/mctr/MctrError.cc | 24 + mctr2/mctr/UserInterface.cc | 39 + mctr2/mctr/UserInterface.h | 82 + mctr2/mctr/config_data.cc | 91 + mctr2/mctr/config_data.h | 111 + mctr2/mctr/main.cc | 318 + mctr2/mctr/ttcn3_start | 338 + parser/.gitignore | 5 + parser/Makefile | 28 + parser/parser.l | 287 + parser/parser.y | 2984 + regression_test/.gitignore | 3 + regression_test/ASN1/Makefile | 16 + regression_test/ASN1/Test303/.gitignore | 13 + regression_test/ASN1/Test303/Makefile | 48 + regression_test/ASN1/Test303/Test303A.asn | 25 + regression_test/ASN1/Test303/Test303T.ttcn | 51 + regression_test/ASN1/Test303/config.cfg | 11 + regression_test/ASN1/Test307/.gitignore | 13 + regression_test/ASN1/Test307/Makefile | 48 + regression_test/ASN1/Test307/Test307A.asn | 23 + regression_test/ASN1/Test307/Test307T.ttcn | 86 + regression_test/ASN1/Test308/.gitignore | 13 + regression_test/ASN1/Test308/Makefile | 48 + regression_test/ASN1/Test308/Test308A.asn | 23 + regression_test/ASN1/Test308/Test308T.ttcn | 86 + regression_test/ASN1/Test309/.gitignore | 3 + regression_test/ASN1/Test309/Makefile | 46 + regression_test/ASN1/Test309/Test309A.asn | 22 + regression_test/ASN1/Test309/Test309T.ttcn | 86 + regression_test/ASN1/Test310/.gitignore | 3 + regression_test/ASN1/Test310/Makefile | 46 + regression_test/ASN1/Test310/Test310A.asn | 21 + regression_test/ASN1/Test310/Test310T.ttcn | 86 + regression_test/ASN1/Test330/Makefile | 47 + regression_test/ASN1/Test330/Test330A.asn | 64 + regression_test/ASN1/Test330/Test330T.ttcn | 162 + regression_test/ASN1/Test332/Makefile | 46 + regression_test/ASN1/Test332/Test332A.asn | 102 + regression_test/ASN1/Test332/Test332T.ttcn | 144 + regression_test/ASN1/Test338/.gitignore | 13 + regression_test/ASN1/Test338/Makefile | 48 + regression_test/ASN1/Test338/Test338A.asn | 23 + regression_test/ASN1/Test338/Test338T.ttcn | 70 + regression_test/ASN1/Test340/.gitignore | 13 + regression_test/ASN1/Test340/Makefile | 48 + regression_test/ASN1/Test340/Test340A.asn | 23 + regression_test/ASN1/Test340/Test340T.ttcn | 70 + regression_test/ASN1/Test342/.gitignore | 3 + regression_test/ASN1/Test342/Makefile | 46 + regression_test/ASN1/Test342/Test342A.asn | 21 + regression_test/ASN1/Test342/Test342T.ttcn | 70 + regression_test/ASN1/Test344/.gitignore | 4 + regression_test/ASN1/Test344/Makefile | 58 + regression_test/ASN1/Test344/Test344A.asn | 21 + regression_test/ASN1/Test344/Test344T.ttcn | 70 + regression_test/ASN1/Test346/.gitignore | 13 + regression_test/ASN1/Test346/Makefile | 48 + regression_test/ASN1/Test346/Test346A.asn | 23 + regression_test/ASN1/Test346/Test346T.ttcn | 70 + regression_test/ASN1/Test348/.gitignore | 13 + regression_test/ASN1/Test348/Makefile | 48 + regression_test/ASN1/Test348/Test348A.asn | 23 + regression_test/ASN1/Test348/Test348T.ttcn | 70 + regression_test/ASN1/Test350/.gitignore | 13 + regression_test/ASN1/Test350/Makefile | 48 + regression_test/ASN1/Test350/Test350A.asn | 128 + regression_test/ASN1/Test350/Test350T.ttcn | 82 + regression_test/ASN1/Test350/config.cfg | 11 + regression_test/ASN1/Test352/.gitignore | 13 + regression_test/ASN1/Test352/Makefile | 48 + regression_test/ASN1/Test352/Test352A.asn | 127 + regression_test/ASN1/Test352/Test352T.ttcn | 111 + regression_test/ASN1/Test352/config.cfg | 11 + regression_test/ASN1/Test354/.gitignore | 13 + regression_test/ASN1/Test354/Makefile | 48 + regression_test/ASN1/Test354/Test354A.asn | 129 + regression_test/ASN1/Test354/Test354T.ttcn | 82 + regression_test/ASN1/Test354/config.cfg | 11 + regression_test/ASN1/Test356/.gitignore | 13 + regression_test/ASN1/Test356/Makefile | 48 + regression_test/ASN1/Test356/Test356A.asn | 132 + regression_test/ASN1/Test356/Test356T.ttcn | 111 + regression_test/ASN1/Test356/config.cfg | 11 + regression_test/ASN1/Test358/.gitignore | 13 + regression_test/ASN1/Test358/Makefile | 48 + regression_test/ASN1/Test358/Test358A.asn | 26 + regression_test/ASN1/Test358/Test358T.ttcn | 39 + regression_test/ASN1/Test358/config.cfg | 11 + regression_test/ASN1/Test360/.gitignore | 13 + regression_test/ASN1/Test360/Makefile | 48 + regression_test/ASN1/Test360/Test360A.asn | 125 + regression_test/ASN1/Test360/Test360T.ttcn | 71 + regression_test/ASN1/Test360/config.cfg | 11 + regression_test/ASN1/Test38/.gitignore | 10 + regression_test/ASN1/Test38/Makefile | 35 + regression_test/ASN1/Test38/Test38A.asn | 61 + regression_test/ASN1/Test38/Test38B.asn | 61 + regression_test/ASN1/Test38/Test38compare | 35 + .../ASN1/codeGeneration2/.gitignore | 145 + regression_test/ASN1/codeGeneration2/Makefile | 41 + .../ASN1/codeGeneration2/Test46.asn | 25 + .../ASN1/codeGeneration2/Test48.asn | 25 + .../ASN1/codeGeneration2/Test49.asn | 25 + .../ASN1/codeGeneration2/Test51.asn | 27 + .../ASN1/codeGeneration2/Test52.asn | 27 + .../ASN1/codeGeneration2/Test53.asn | 27 + .../ASN1/codeGeneration2/Test54.asn | 24 + .../ASN1/codeGeneration2/Test55.asn | 25 + .../ASN1/codeGeneration2/Test56.asn | 25 + .../ASN1/codeGeneration2/Test57.asn | 33 + .../ASN1/codeGeneration2/Test60.asn | 35 + .../ASN1/codeGeneration2/Test61.asn | 42 + .../ASN1/codeGeneration2/Test62.asn | 38 + .../ASN1/codeGeneration2/Test63.asn | 31 + .../ASN1/codeGeneration2/Test64.asn | 26 + .../ASN1/codeGeneration2/Test65.asn | 26 + .../ASN1/codeGeneration2/Test66.asn | 28 + .../ASN1/codeGeneration2/Test68.asn | 71 + .../ASN1/codeGeneration2/Test71.asn | 64 + .../ASN1/codeGeneration2/Test74.asn | 143 + .../ASN1/codeGeneration2/Test75.asn | 25 + .../ASN1/codeGeneration2/Test76.asn | 143 + .../ASN1/codeGeneration2/Test77.asn | 25 + .../ASN1/codeGeneration2/Test78.asn | 41 + .../ASN1/codeGeneration2/Test80.asn | 40 + .../ASN1/codeGeneration2/Test81.asn | 37 + .../ASN1/codeGeneration2/Test83.asn | 83 + .../ASN1/codeGeneration2/Test86.asn | 40 + .../ASN1/codeGeneration2/Test87.asn | 40 + .../ASN1/codeGeneration2/codeGeneration2 | 67 + regression_test/ASN1/enum1/.gitignore | 5 + regression_test/ASN1/enum1/Makefile | 35 + regression_test/ASN1/enum1/Test23.asn | 25 + regression_test/ASN1/enum1/enum1 | 44 + regression_test/ASN1/enum2/.gitignore | 5 + regression_test/ASN1/enum2/Makefile | 35 + regression_test/ASN1/enum2/Test25.asn | 24 + regression_test/ASN1/enum2/enum2 | 42 + regression_test/ASN1/errorMessages/Makefile | 21 + regression_test/ASN1/errorMessages/Test11.asn | 22 + regression_test/ASN1/errorMessages/Test12.asn | 23 + regression_test/ASN1/errorMessages/Test13.asn | 23 + regression_test/ASN1/errorMessages/Test14.asn | 23 + regression_test/ASN1/errorMessages/Test15.asn | 23 + regression_test/ASN1/errorMessages/Test16.asn | 23 + regression_test/ASN1/errorMessages/Test17.asn | 22 + regression_test/ASN1/errorMessages/Test18.asn | 29 + .../ASN1/errorMessages/Test19_1.asn | 21 + .../ASN1/errorMessages/Test19_2.asn | 19 + regression_test/ASN1/errorMessages/Test20.asn | 20 + regression_test/ASN1/errorMessages/Test21.asn | 19 + regression_test/ASN1/errorMessages/Test22.asn | 19 + regression_test/ASN1/errorMessages/Test24.asn | 19 + regression_test/ASN1/errorMessages/Test26.asn | 28 + regression_test/ASN1/errorMessages/Test28.asn | 28 + regression_test/ASN1/errorMessages/Test32.asn | 27 + regression_test/ASN1/errorMessages/Test33.asn | 27 + regression_test/ASN1/errorMessages/Test34.asn | 28 + regression_test/ASN1/errorMessages/Test39.asn | 29 + regression_test/ASN1/errorMessages/Test40.asn | 29 + regression_test/ASN1/errorMessages/Test41.asn | 25 + regression_test/ASN1/errorMessages/Test42.asn | 19 + regression_test/ASN1/errorMessages/Test43.asn | 21 + regression_test/ASN1/errorMessages/Test44.asn | 21 + regression_test/ASN1/errorMessages/Test45.asn | 21 + regression_test/ASN1/errorMessages/Test47.asn | 21 + regression_test/ASN1/errorMessages/Test50.asn | 21 + regression_test/ASN1/errorMessages/Test67.asn | 22 + regression_test/ASN1/errorMessages/Test69.asn | 31 + regression_test/ASN1/errorMessages/Test70.asn | 31 + regression_test/ASN1/errorMessages/Test72.asn | 31 + regression_test/ASN1/errorMessages/Test73.asn | 33 + regression_test/ASN1/errorMessages/Test79.asn | 38 + regression_test/ASN1/errorMessages/Test82.asn | 39 + regression_test/ASN1/errorMessages/Test84.asn | 36 + regression_test/ASN1/errorMessages/Test85.asn | 38 + regression_test/ASN1/errorMessages/error | 74 + regression_test/ASN1/errorMessages2/Makefile | 23 + .../ASN1/errorMessages2/Test10.asn | 37 + regression_test/ASN1/errorMessages2/error2 | 39 + regression_test/ASN1/hyphen/.gitignore | 5 + regression_test/ASN1/hyphen/Makefile | 35 + regression_test/ASN1/hyphen/Test284.asn | 23 + regression_test/ASN1/hyphen/hyphen | 27 + regression_test/ASN1/keyword/.gitignore | 4 + regression_test/ASN1/keyword/Makefile | 40 + regression_test/ASN1/keyword/Test283.asn | 232 + regression_test/ASN1/keyword/Test283T.ttcn | 234 + regression_test/ASN1/keyword/keyword | 233 + regression_test/ASN1/parse/Makefile | 21 + regression_test/ASN1/parse/Test1.asn | 936 + .../ASN1/parse/Test1_known_errors.asn | 131 + regression_test/ASN1/parse/Test2.asn | 329 + .../ASN1/parse/Test2_known_errors.asn | 447 + regression_test/ASN1/parse/Test3.asn | 263 + .../ASN1/parse/Test3_known_errors.asn | 18 + regression_test/ASN1/parse/Test4.asn | 480 + .../ASN1/parse/Test4_known_errors.asn | 104 + regression_test/ASN1/parse/parse | 36 + .../ASN1/transformations/.gitignore | 60 + regression_test/ASN1/transformations/Makefile | 35 + .../ASN1/transformations/Test289A.asn | 22 + .../ASN1/transformations/Test289B.asn | 22 + .../ASN1/transformations/Test5A.asn | 46 + .../ASN1/transformations/Test5B.asn | 50 + .../ASN1/transformations/Test6A.asn | 39 + .../ASN1/transformations/Test6B.asn | 39 + .../ASN1/transformations/Test7A.asn | 39 + .../ASN1/transformations/Test7B.asn | 39 + .../ASN1/transformations/Test8A.asn | 66 + .../ASN1/transformations/Test8B.asn | 66 + .../ASN1/transformations/Test9A.asn | 49 + .../ASN1/transformations/Test9B.asn | 49 + regression_test/ASN1/transformations/compare3 | 68 + regression_test/BER/.gitignore | 17 + regression_test/BER/Makefile | 63 + regression_test/BER/MyPort1.cc | 107 + regression_test/BER/MyPort1.hh | 65 + regression_test/BER/MyPort2.cc | 116 + regression_test/BER/MyPort2.hh | 51 + regression_test/BER/Regr.cfg | 19 + regression_test/BER/Regr.ttcn | 1168 + regression_test/BER/Regr1.asn | 138 + regression_test/BER/Regr2.asn | 181 + regression_test/BER_x682/.gitignore | 13 + regression_test/BER_x682/Makefile | 60 + regression_test/BER_x682/MyPort1.cc | 80 + regression_test/BER_x682/MyPort1.hh | 54 + regression_test/BER_x682/MyPort2.cc | 82 + regression_test/BER_x682/MyPort2.hh | 51 + regression_test/BER_x682/X.cfg | 19 + regression_test/BER_x682/X.ttcn | 84 + regression_test/BER_x682/X682.asn | 79 + regression_test/BER_x682_wa/Makefile | 55 + regression_test/BER_x682_wa/MyPort1.cc | 66 + regression_test/BER_x682_wa/MyPort1.hh | 41 + regression_test/BER_x682_wa/MyPort2.cc | 70 + regression_test/BER_x682_wa/MyPort2.hh | 42 + regression_test/BER_x682_wa/X.cfg | 18 + regression_test/BER_x682_wa/X.ttcn | 84 + regression_test/BER_x682_wa/x682.asn | 88 + regression_test/CRTR00015758/.gitignore | 6 + regression_test/CRTR00015758/Makefile | 125 + regression_test/CRTR00015758/config.cfg | 14 + regression_test/CRTR00015758/logfilecheck | 112 + regression_test/CRTR00015758/no.ttcn | 40 + regression_test/CRTR00015758/run.cfg | 15 + regression_test/CRTR00015758/trouble.cfg | 18 + regression_test/ERC/.gitignore | 8 + regression_test/ERC/Makefile | 57 + regression_test/ERC/base.cfg | 34 + regression_test/ERC/config.cfg | 52 + regression_test/ERC/erc.ttcn | 155 + regression_test/ERC/included1.cfg | 26 + regression_test/ERC/included2.cfg | 23 + regression_test/ERC/subdir/subdir_config.cfg | 7 + regression_test/HP17080/.gitignore | 4 + regression_test/HQ16404/.gitignore | 6 + regression_test/HQ16404/HQ16404.ttcn | 378 + regression_test/HQ16404/Makefile | 145 + regression_test/HQ16404/config.cfg | 10 + regression_test/Makefile | 91 + regression_test/Makefile.regression | 232 + regression_test/RAW/Examples/.gitignore | 34 + .../RAW/Examples/DTAP_RAW_Samples.ttcn | 312 + .../RAW/Examples/DTAP_typedefs.ttcn | 1587 + regression_test/RAW/Examples/Makefile | 54 + regression_test/RAW/Examples/RAW_Test.ttcn | 202 + regression_test/RAW/Examples/RAWtest.cfg | 16 + .../RAW/Examples/SCCP_RAW_Samples.ttcn | 209 + .../RAW/Examples/SCCP_typedefs.ttcn | 1519 + .../RAW/Examples/general_typedefs.ttcn | 138 + regression_test/RAW/HN25015/.gitignore | 7 + .../RAW/HN25015/General_Types.ttcn | 94 + regression_test/RAW/HN25015/HN25015.ttcn | 54 + regression_test/RAW/HN25015/Makefile | 138 + regression_test/RAW/HN25015/SGsAP_Types.ttcn | 104 + regression_test/RAW/HN25015/config.cfg | 10 + regression_test/RAW/HQ26535/.gitignore | 7 + regression_test/RAW/HQ26535/GTPv2_Types.ttcn | 322 + .../RAW/HQ26535/General_Types.ttcn | 65 + regression_test/RAW/HQ26535/Makefile | 135 + regression_test/RAW/HQ26535/gtpctest.ttcn | 30 + regression_test/RAW/HQ49956/Makefile | 135 + regression_test/RAW/HQ49956/Module.ttcn | 57 + regression_test/RAW/HQ49956/Test.ttcn | 88 + .../RAW/HS16977/HS16977_Constants.ttcn | 17 + regression_test/RAW/HS16977/HS16977_Test.ttcn | 59 + .../RAW/HS16977/HS16977_Types.ttcn | 37 + regression_test/RAW/HS16977/Makefile | 135 + regression_test/RAW/HS16977/config.cfg | 14 + regression_test/RAW/Makefile | 15 + .../XML/EXER-whitepaper/.gitignore | 113 + .../XML/EXER-whitepaper/AnyAttributes.ttcnpp | 365 + .../XML/EXER-whitepaper/AnyElement.ttcnpp | 369 + .../EXER-whitepaper/AnyElementOptional.ttcnpp | 194 + .../AnyElementOptional2.ttcnpp | 265 + .../XML/EXER-whitepaper/Attribute.ttcnpp | 438 + .../EXER-whitepaper/DefaultForEmpty.ttcnpp | 85 + .../XML/EXER-whitepaper/EmbedValues.ttcnpp | 169 + .../XML/EXER-whitepaper/List.ttcnpp | 100 + regression_test/XML/EXER-whitepaper/Makefile | 189 + .../XML/EXER-whitepaper/Name.ttcnpp | 206 + .../XML/EXER-whitepaper/Namespaces.ttcnpp | 344 + .../XML/EXER-whitepaper/NamespacesDup.ttcnpp | 102 + .../XML/EXER-whitepaper/Order.ttcnpp | 345 + .../XML/EXER-whitepaper/Qname.ttcnpp | 309 + .../XML/EXER-whitepaper/Text.ttcnpp | 257 + .../XML/EXER-whitepaper/Untagged.ttcnpp | 702 + .../XML/EXER-whitepaper/Untagged1.ttcnpp | 483 + .../XML/EXER-whitepaper/UseNil.ttcnpp | 572 + .../XML/EXER-whitepaper/UseNilSimple.ttcnpp | 275 + .../XML/EXER-whitepaper/UseNumber.ttcnpp | 71 + .../XML/EXER-whitepaper/UseOrder.ttcnpp | 330 + .../XML/EXER-whitepaper/UseType.ttcnpp | 136 + .../XML/EXER-whitepaper/UseUnion.ttcnpp | 479 + .../XML/EXER-whitepaper/Whitespace.ttcnpp | 70 + .../XML/EXER-whitepaper/config.cfg | 43 + regression_test/XML/HM60295/.gitignore | 8 + regression_test/XML/HM60295/Importer.xsd | 26 + regression_test/XML/HM60295/Makefile | 111 + regression_test/XML/HM60295/Schema1.xsd | 29 + regression_test/XML/HM60295/Schema2.xsd | 31 + regression_test/XML/HM60295/config.cfg | 10 + regression_test/XML/HM60295/tester.ttcn | 29 + regression_test/XML/HN15589/.gitignore | 10 + regression_test/XML/HN15589/A.xsd | 26 + regression_test/XML/HN15589/B.xsd | 35 + regression_test/XML/HN15589/HN15589.ttcnpp | 324 + regression_test/XML/HN15589/Makefile | 184 + regression_test/XML/HN15589/config.cfg | 16 + .../XML/HN15589/flipflop-check.xsd | 65 + regression_test/XML/HN15589/log2xml.pl | 16 + regression_test/XML/HN15589/xsd/XTDL.xsd | 111 + .../XML/HN15589/xsd/XTDP-Message.xsd | 74 + regression_test/XML/HN15589/xtdl.ttcn | 188 + regression_test/XML/HN15589/xtdp.cfg | 16 + regression_test/XML/HN15589/xtdp.ttcn | 98 + regression_test/XML/HN34094/.gitignore | 10 + regression_test/XML/HQ30408/.gitignore | 5 + regression_test/XML/HQ30408/HQ30408.ttcn | 59 + regression_test/XML/HQ30408/Makefile | 138 + regression_test/XML/HR49727/.gitignore | 6 + regression_test/XML/HR49727/HR49727.ttcn | 137 + regression_test/XML/HR49727/Makefile | 138 + .../XML/HR49727/UsefulTtcn3Types.ttcn | 82 + regression_test/XML/HR49727/XSD.ttcn | 322 + regression_test/XML/HR49727/config.cfg | 12 + .../http_jabber_org_protocol_pubsub.ttcn | 363 + ...http_jabber_org_protocol_pubsub_event.ttcn | 264 + .../XML/HR49727/jabber_x_data.ttcn | 181 + regression_test/XML/Makefile | 40 + regression_test/XML/NegativeTest/.gitignore | 13 + regression_test/XML/NegativeTest/Makefile | 151 + regression_test/XML/NegativeTest/ReadXml.ttcn | 117 + .../XML/NegativeTest/ReadXmlImpl.cc | 84 + .../XML/NegativeTest/exer_rec.ttcn | 1380 + .../XML/NegativeTest/exer_rec_of.ttcn | 258 + .../XML/NegativeTest/exer_uni.ttcn | 306 + regression_test/XML/NegativeTest/indent.pl | 19 + regression_test/XML/NegativeTest/rec.ttcn | 798 + regression_test/XML/NegativeTest/rec_of.ttcn | 822 + regression_test/XML/NegativeTest/run.cfg | 14 + regression_test/XML/NegativeTest/runner.ttcn | 93 + regression_test/XML/NegativeTest/uni.ttcn | 201 + regression_test/XML/TTCNandXML/.gitignore | 24 + regression_test/XML/TTCNandXML/AnnexB1.ttcn | 80 + .../XML/TTCNandXML/AnnexB1Template.ttcnpp | 97 + regression_test/XML/TTCNandXML/AnnexB2.ttcn | 89 + .../XML/TTCNandXML/AnnexB2Template.ttcnpp | 121 + regression_test/XML/TTCNandXML/AnnexB3.ttcn | 83 + .../XML/TTCNandXML/AnnexB3Template.ttcnpp | 112 + regression_test/XML/TTCNandXML/AnnexB4.ttcn | 45 + .../XML/TTCNandXML/AnnexB4Template.ttcnpp | 81 + .../XML/TTCNandXML/AnyStuff.ttcnpp | 155 + .../XML/TTCNandXML/AttribPath.ttcn | 57 + .../XML/TTCNandXML/AttribPathTest.ttcnpp | 267 + .../XML/TTCNandXML/AttributesTest.ttcnpp | 249 + .../XML/TTCNandXML/Base64Test.ttcnpp | 120 + .../XML/TTCNandXML/DFEAttribTest.ttcnpp | 216 + regression_test/XML/TTCNandXML/DFETest.ttcnpp | 626 + regression_test/XML/TTCNandXML/E0.ttcn | 38 + .../XML/TTCNandXML/EmbedValues.ttcnpp | 406 + .../XML/TTCNandXML/EnumTest.ttcnpp | 210 + regression_test/XML/TTCNandXML/Flattener.ttcn | 13 + regression_test/XML/TTCNandXML/Makefile | 199 + regression_test/XML/TTCNandXML/Marx.ttcnpp | 178 + .../XML/TTCNandXML/NamespaceDef.ttcn | 44 + .../XML/TTCNandXML/NamespaceTest.ttcnpp | 321 + .../XML/TTCNandXML/Regressions.ttcnpp | 77 + regression_test/XML/TTCNandXML/UTF8.ttcn | 99 + .../XML/TTCNandXML/WhitespaceTest.ttcnpp | 457 + regression_test/XML/TTCNandXML/X693amd1.ttcn | 191 + .../XML/TTCNandXML/X693amd1Test.ttcnpp | 628 + .../XML/TTCNandXML/XSDAttributes.ttcn | 59 + regression_test/XML/TTCNandXML/config.cfg | 35 + regression_test/XML/XER/.gitignore | 22 + regression_test/XML/XER/AsnValues.asn | 570 + regression_test/XML/XER/Asntypes.asn | 171 + regression_test/XML/XER/EmptyUnion.asn | 81 + regression_test/XML/XER/Flatten.cc | 103 + regression_test/XML/XER/Makefile | 211 + regression_test/XML/XER/ObjectClass.asn | 149 + .../XML/XER/ObjectClassWithSyntax.asn | 214 + regression_test/XML/XER/SetValues.asn | 226 + regression_test/XML/XER/Sets.asn | 73 + regression_test/XML/XER/Txerasntypes.ttcnpp | 2032 + regression_test/XML/XER/Txerbinstr.ttcnpp | 262 + regression_test/XML/XER/Txerboolean.ttcnpp | 230 + regression_test/XML/XER/Txerenum.ttcnpp | 157 + regression_test/XML/XER/Txerfloat.ttcnpp | 148 + regression_test/XML/XER/Txerint.ttcnpp | 165 + regression_test/XML/XER/Txernested.ttcnpp | 463 + regression_test/XML/XER/Txerobjclass.ttcnpp | 612 + regression_test/XML/XER/Txersets.ttcnpp | 1670 + regression_test/XML/XER/Txerstring.ttcnpp | 150 + regression_test/XML/XER/checkit.pl | 103 + regression_test/XML/XER/config.cfg | 33 + regression_test/XML/XER/junk.ttcn3 | 15 + regression_test/XML/XMLqualif/.gitignore | 25 + regression_test/XML/XMLqualif/Makefile | 224 + regression_test/XML/XMLqualif/POtest.ttcnpp | 181 + regression_test/XML/XMLqualif/config.cfg | 15 + regression_test/XML/XMLqualif/globall.xsd | 74 + regression_test/XML/XMLqualif/po_qual.xsd | 39 + regression_test/XML/XMLqualif/po_qual_atr.xsd | 39 + .../XML/XMLqualif/po_qual_both.xsd | 39 + .../XML/XMLqualif/po_qual_default.xml | 24 + .../XML/XMLqualif/po_qual_explicit.xml | 24 + regression_test/XML/XMLqualif/po_unqual.xml | 24 + regression_test/XML/XMLqualif/po_unqual.xsd | 39 + regression_test/XML/XmlWorkflow/Makefile | 69 + .../PIPEasp_CNL113334/demo/PIPE.cfg | 36 + .../demo/PIPEasp_Templates.ttcn | 93 + .../PIPEasp_CNL113334/demo/PipeTest.prj | 48 + .../PIPEasp_CNL113334/demo/PipeTest.ttcn | 334 + .../PIPEasp_CNL113334/demo/ShellNotice.sh | 21 + .../demo/ShellQuestionString.sh | 23 + .../demo/ShellQuestionYesNo.sh | 35 + .../PIPEasp_CNL113334/src/PIPEasp_PT.cc | 738 + .../PIPEasp_CNL113334/src/PIPEasp_PT.hh | 106 + .../src/PIPEasp_PortType.ttcn | 46 + .../PIPEasp_CNL113334/src/PIPEasp_Types.ttcn | 180 + .../PIPEasp_CNL113334/test/Makefile | 147 + .../PIPEasp_CNL113334/test/PIPEasp_PT.cc | 739 + .../PIPEasp_CNL113334/test/PIPEasp_PT.hh | 108 + .../test/PIPEasp_PortType.ttcn | 46 + .../PIPEasp_CNL113334/test/PIPEasp_Types.ttcn | 180 + .../XML/XmlWorkflow/Tgc/IsTypes.xsd | 67 + regression_test/XML/XmlWorkflow/Tgc/Tgc.ttcn | 3689 ++ regression_test/XML/XmlWorkflow/Tgc/Tgc.xsd | 7954 +++ .../XML/XmlWorkflow/Tgc/UsefulTtcn3Types.ttcn | 82 + .../XML/XmlWorkflow/Tgc/XMLSchema.xsd | 1552 + regression_test/XML/XmlWorkflow/Tgc/XSD.ttcn | 322 + regression_test/XML/XmlWorkflow/Tgc/confd.xsd | 163 + .../Tgc/tail_f_com_ns_confd_1_0.ttcn | 198 + ...sson_com_is_isco_IsTypes_R4L06_R4AF11.ttcn | 69 + ..._ericsson_com_is_isco_Tgc_R6A48_R6H01.ttcn | 3352 + .../Tgc/www_w3_org_XML_1998_namespace.ttcn | 86 + regression_test/XML/XmlWorkflow/Tgc/xml.xsd | 49 + .../ETSI_CR5852_union_e.ttcn | 117 + .../NoTargetNamespace_CCAPI_e.ttcn | 129 + .../NoTargetNamespace_JMdict_e.ttcn | 328 + .../NoTargetNamespace_PAP_e.ttcn | 459 + .../NoTargetNamespace_RLP_e.ttcn | 2315 + .../NoTargetNamespace_XML_RPC_e.ttcn | 168 + .../NoTargetNamespace_e.ttcn | 62 + .../XmlTest_imsike_e.ttcn | 134 + .../http_www_XmlTest_org_po_e.ttcn | 118 + ...http_www_example_org_ttcn_wildcards_e.ttcn | 203 + .../ietf_params_xml_ns_pidf_e.ttcn | 161 + .../ietf_params_xml_ns_pidf_status_e.ttcn | 54 + .../ietf_params_xml_ns_resource_lists_e.ttcn | 105 + .../ietf_params_xml_ns_rlmi_e.ttcn | 125 + .../schemas_ericsson_com_cai3g1_1_e.ttcn | 543 + .../schemas_ericsson_com_cai3g1_2_e.ttcn | 525 + .../schemas_ericsson_com_ma_HSS_e.ttcn | 308 + ...icsson_com_upg_bulkprovisioning_1_0_e.ttcn | 91 + ...emas_ericsson_com_upg_dm_hss_sh_4_1_e.ttcn | 819 + ...s_ericsson_com_upg_provisioning_1_0_e.ttcn | 397 + .../tail_f_com_ns_confd_1_0_e.ttcn | 201 + ...tsi_org_ngn_params_xml_simservs_sci_e.ttcn | 239 + ..._ietf_params_xml_ns_conference_info_e.ttcn | 563 + .../www_XmlTest_org_annotation_c_e.ttcn | 61 + .../www_XmlTest_org_annotation_e.ttcn | 70 + .../www_XmlTest_org_annotation_e_e.ttcn | 57 + .../www_XmlTest_org_annotation_t_e.ttcn | 69 + .../www_XmlTest_org_boolean_e.ttcn | 62 + .../www_XmlTest_org_complex1_e.ttcn | 65 + .../www_XmlTest_org_complex2_e.ttcn | 100 + .../www_XmlTest_org_complex_all_e.ttcn | 115 + .../www_XmlTest_org_complex_any_e.ttcn | 83 + .../www_XmlTest_org_complex_choice_e.ttcn | 168 + .../www_XmlTest_org_complex_e.ttcn | 60 + .../www_XmlTest_org_complex_extension_e.ttcn | 93 + .../www_XmlTest_org_complex_import_AB_e.ttcn | 74 + .../www_XmlTest_org_complex_import_A_e.ttcn | 62 + .../www_XmlTest_org_complex_import_B_e.ttcn | 62 + .../www_XmlTest_org_complex_import_e.ttcn | 76 + .../www_XmlTest_org_complex_include1_e.ttcn | 121 + .../www_XmlTest_org_complex_include2_e.ttcn | 94 + .../www_XmlTest_org_complex_include_e.ttcn | 94 + ...Test_org_complex_minOccursMaxOccurs_e.ttcn | 243 + .../www_XmlTest_org_complex_mixed_e.ttcn | 64 + ...www_XmlTest_org_complex_restriction_e.ttcn | 90 + ...w_XmlTest_org_complex_simpleContent_e.ttcn | 81 + .../www_XmlTest_org_decimal_e.ttcn | 56 + .../www_XmlTest_org_decimal_withEnum_e.ttcn | 56 + .../www_XmlTest_org_decimal_withLength_e.ttcn | 51 + ...est_org_decimal_withMinMaxExclusive_e.ttcn | 65 + ...est_org_decimal_withMinMaxInclusive_e.ttcn | 62 + .../www_XmlTest_org_element_anyType_e.ttcn | 66 + ...XmlTest_org_element_nameInheritance_e.ttcn | 67 + ...lTest_org_element_recordOfElements3_e.ttcn | 69 + ...lTest_org_element_recordOfElements4_e.ttcn | 64 + ...lTest_org_element_recordOfElements5_e.ttcn | 70 + ...mlTest_org_element_recordOfElements_e.ttcn | 84 + .../www_XmlTest_org_empty_e.ttcn | 50 + .../www_XmlTest_org_integer_MaxExcl_e.ttcn | 58 + .../www_XmlTest_org_integer_MaxIncl_e.ttcn | 58 + .../www_XmlTest_org_integer_MinExcl_e.ttcn | 58 + .../www_XmlTest_org_integer_MinIncl_e.ttcn | 59 + .../www_XmlTest_org_integer_e.ttcn | 58 + .../www_XmlTest_org_integer_withEnum_e.ttcn | 74 + ...www_XmlTest_org_integer_withMaxExcl_e.ttcn | 64 + ...www_XmlTest_org_integer_withMaxIncl_e.ttcn | 64 + ...www_XmlTest_org_integer_withMinExcl_e.ttcn | 64 + ...www_XmlTest_org_integer_withMinIncl_e.ttcn | 64 + .../www_XmlTest_org_list_e.ttcn | 310 + .../www_XmlTest_org_list_integer_e.ttcn | 64 + .../www_XmlTest_org_simple_enum_e.ttcn | 78 + .../www_XmlTest_org_string_e.ttcn | 177 + ..._XmlTest_org_string_withEmptyLength_e.ttcn | 54 + ...www_XmlTest_org_string_withEmptyMax_e.ttcn | 54 + ...www_XmlTest_org_string_withEmptyMin_e.ttcn | 54 + .../www_XmlTest_org_string_withEnum_e.ttcn | 79 + ...XmlTest_org_string_withFaultyMinMax_e.ttcn | 54 + ..._XmlTest_org_string_withFixedLength_e.ttcn | 65 + ..._XmlTest_org_string_withFloatLength_e.ttcn | 52 + ...ww_XmlTest_org_string_withMinLength_e.ttcn | 58 + ...lTest_org_string_withNegativeLength_e.ttcn | 54 + ..._XmlTest_org_string_withNegativeMin_e.ttcn | 54 + ...lTest_org_string_withOverDefinition_e.ttcn | 59 + ...ww_XmlTest_org_string_withPosLength_e.ttcn | 58 + .../www_XmlTest_org_string_withPosMax_e.ttcn | 59 + ..._XmlTest_org_string_withTypeAndBase_e.ttcn | 54 + ...w_XmlTest_org_string_withWhitespace_e.ttcn | 80 + .../www_XmlTest_org_time_e.ttcn | 82 + .../www_XmlTest_org_time_withEnum_e.ttcn | 157 + .../www_XmlTest_org_union_e.ttcn | 102 + ...sapi_org_schema_parlayx_common_v2_0_e.ttcn | 139 + ..._payment_amount_charging_v2_0_local_e.ttcn | 119 + ..._reserve_amount_charging_v2_0_local_e.ttcn | 184 + ..._reserve_volume_charging_v2_0_local_e.ttcn | 220 + ...api_org_schema_parlayx_payment_v2_0_e.ttcn | 52 + ..._payment_volume_charging_v2_0_local_e.ttcn | 155 + ...egratedSite_R4L06_R4AB_1_02_HK84933_e.ttcn | 104 + ...isco_IntegratedSite_R4L06_R4AB_1_02_e.ttcn | 1721 + ...com_is_isco_IsTypes_R4L06_R4AB_1_02_e.ttcn | 72 + ...on_com_is_isco_IsTypes_R4L06_R4AF11_e.ttcn | 72 + ..._is_isco_MainSwitch_R4L06_R4AB_1_02_e.ttcn | 719 + .../www_ericsson_com_is_isco_Mgw_R9B27_e.ttcn | 5177 ++ ...on_com_is_isco_Misc_R4L06_R4AB_1_02_e.ttcn | 55 + ...ricsson_com_is_isco_Tgc_R6A48_R6H01_e.ttcn | 3355 + .../www_example_org_e.ttcn | 80 + .../www_w3_org_XML_1998_namespace_PIDF_e.ttcn | 160 + .../www_w3_org_XML_1998_namespace_e.ttcn | 89 + .../XmlTest_protocolXSDs/CAI3G/Bulk.xsd | 61 + .../CAI3G/GenericCai3gType.xsd | 343 + .../CAI3G/Provisioning.xsd | 267 + .../XmlTest_protocolXSDs/CCAPI/CCAPI.xsd | 79 + .../XmlTest_protocolXSDs/HSS/avg.xsd | 100 + .../HSS/cai3g1.2_provisioning.xsd | 351 + .../XmlTest_protocolXSDs/HSS/eps.xsd | 92 + .../XmlTest_protocolXSDs/HSS/hssla_types.xsd | 86 + .../JMdict/jmdict-good.xsd | 118 + .../MGW/IntegratedSite.xsd | 3757 ++ .../MGW/IntegratedSite_HK84933.xsd | 97 + .../XmlTest_protocolXSDs/MGW/IsTypes.xsd | 67 + .../XmlTest_protocolXSDs/MGW/MainSwitch.xsd | 1751 + .../XmlTest_protocolXSDs/MGW/Mgw_R9B27.xsd | 11363 ++++ .../XmlTest_protocolXSDs/MGW/Misc.xsd | 26 + .../XmlTest_protocolXSDs/MGW/XMLSchema.xsd | 2542 + .../XmlTest_protocolXSDs/MGW/confd.xsd | 374 + .../XmlTest_protocolXSDs/MGW/xml.xsd | 134 + .../XmlTest_protocolXSDs/PAP/PAP.xsd | 262 + .../XmlTest_protocolXSDs/PIDF/pidf.xsd | 97 + .../XmlTest_protocolXSDs/PIDF/rlmi.xsd | 75 + .../XmlTest_protocolXSDs/PIDF/testschema.xsd | 25 + .../XmlTest_protocolXSDs/PIDF/xml_PIDF.xsd | 128 + .../ParlayX/parlayx_common_types_2_0.xsd | 78 + ..._payment_amount_charging_interface_2_0.xsd | 51 + ..._reserve_amount_charging_interface_2_0.xsd | 77 + ..._reserve_volume_charging_interface_2_0.xsd | 93 + .../ParlayX/parlayx_payment_types_2_0.xsd | 22 + ..._payment_volume_charging_interface_2_0.xsd | 65 + .../XmlTest_protocolXSDs/RLP/RLP_SVC.xsd | 1349 + .../RLXML/RLXML_small.xsd | 57 + .../XmlTest_protocolXSDs/RLXML/rlxml.xml | 23 + .../XmlTest_protocolXSDs/SIP/SIP.xsd | 181 + .../ShData/ShDataType.xsd | 620 + .../XmlTest_protocolXSDs/XML_RPC/XML_RPC.xsd | 141 + .../XmlTest_xsds/ETSI_CR5852_union.xsd | 67 + .../XmlTest_xsds/UsefulTtcn3Types.ttcn | 82 + .../XML/XmlWorkflow/XmlTest_xsds/XSD.ttcn | 322 + .../XmlTest_xsds/XmlTest_annotation.xsd | 53 + .../XmlTest_xsds/XmlTest_annotation1.xsd | 19 + .../XmlTest_xsds/XmlTest_annotation2.xsd | 19 + .../XmlTest_xsds/XmlTest_boolean.xsd | 33 + .../XmlTest_boolean_withTypeAndBase.xsd | 30 + .../XmlTest_xsds/XmlTest_complex1.xsd | 31 + .../XmlTest_xsds/XmlTest_complex2.xsd | 51 + .../XmlTest_xsds/XmlTest_complex_all.xsd | 46 + .../XmlTest_xsds/XmlTest_complex_any.xsd | 45 + .../XmlTest_xsds/XmlTest_complex_choice.xsd | 86 + .../XmlTest_complex_extension.xsd | 41 + .../XmlTest_xsds/XmlTest_complex_import_A.xsd | 26 + .../XmlTest_complex_import_AB.xsd | 40 + .../XmlTest_xsds/XmlTest_complex_import_B.xsd | 26 + .../XmlTest_complex_import_neg1.xsd | 42 + .../XmlTest_complex_import_pos.xsd | 40 + ...Test_complex_import_withSchemaLocation.xsd | 40 + .../XmlTest_xsds/XmlTest_complex_include.xsd | 39 + .../XmlTest_xsds/XmlTest_complex_include1.xsd | 62 + .../XmlTest_xsds/XmlTest_complex_include2.xsd | 62 + .../XmlTest_complex_minOccursMaxOccurs.xsd | 127 + .../XmlTest_xsds/XmlTest_complex_mixed.xsd | 28 + .../XmlTest_complex_restriction.xsd | 44 + .../XmlTest_complex_restriction_neg1.xsd | 44 + .../XmlTest_complex_restriction_neg2.xsd | 44 + .../XmlTest_complex_simpleContent.xsd | 36 + .../XmlTest_xsds/XmlTest_complex_unique.xsd | 88 + .../XmlTest_xsds/XmlTest_decimal.xsd | 27 + .../XmlTest_xsds/XmlTest_decimal_withEnum.xsd | 32 + .../XmlTest_decimal_withLength.xsd | 29 + .../XmlTest_decimal_withMinMaxExclusive.xsd | 49 + .../XmlTest_decimal_withMinMaxInclusive.xsd | 42 + .../XmlTest_xsds/XmlTest_element_abstract.xsd | 36 + .../XmlTest_xsds/XmlTest_element_anyType.xsd | 25 + .../XmlTest_element_nameInheritance.xsd | 36 + .../XmlTest_element_recordOfElements.xsd | 41 + .../XmlTest_element_recordOfElements3.xsd | 31 + .../XmlTest_element_recordOfElements4.xsd | 30 + .../XmlTest_element_recordOfElements5.xsd | 38 + .../XmlTest_xsds/XmlTest_files1.txt | 1 + .../XmlTest_xsds/XmlTest_imsike.xsd | 60 + .../XmlTest_xsds/XmlTest_integer.xsd | 28 + .../XmlTest_xsds/XmlTest_integer_empty1.xsd | 25 + .../XmlTest_xsds/XmlTest_integer_withEnum.xsd | 35 + .../XmlTest_integer_withLength.xsd | 29 + .../XmlTest_integer_withMaxExcl.xsd | 41 + .../XmlTest_integer_withMaxIncl.xsd | 41 + .../XmlTest_integer_withMinExcl.xsd | 41 + .../XmlTest_integer_withMinIncl.xsd | 41 + .../XmlWorkflow/XmlTest_xsds/XmlTest_list.xsd | 188 + .../XmlTest_xsds/XmlTest_list_integer.xsd | 37 + .../XmlTest_xsds/XmlTest_simple_enum.xsd | 57 + .../XmlTest_xsds/XmlTest_string.xsd | 149 + .../XmlTest_string_withEmptyLength.xsd | 27 + .../XmlTest_string_withEmptyMax.xsd | 29 + .../XmlTest_string_withEmptyMin.xsd | 27 + .../XmlTest_xsds/XmlTest_string_withEnum.xsd | 45 + .../XmlTest_string_withFaultyMinMax.xsd | 28 + .../XmlTest_string_withFixedLength.xsd | 39 + .../XmlTest_string_withFloatLength.xsd | 28 + .../XmlTest_string_withMinLength.xsd | 29 + .../XmlTest_string_withNegativeLength.xsd | 27 + .../XmlTest_string_withNegativeMax.xsd | 27 + .../XmlTest_string_withNegativeMin.xsd | 27 + .../XmlTest_string_withOverDefinition.xsd | 35 + .../XmlTest_string_withPosLength.xsd | 30 + .../XmlTest_string_withPosMax.xsd | 29 + .../XmlTest_string_withTypeAndBase.xsd | 31 + .../XmlTest_string_withWhitespace.xsd | 53 + .../XmlWorkflow/XmlTest_xsds/XmlTest_time.xsd | 70 + .../XmlTest_xsds/XmlTest_time_withEnum.xsd | 86 + .../XmlTest_xsds/XmlTest_union.xsd | 43 + .../XmlTest_xsds/XmlTest_union2.xsd | 41 + .../XmlTest_xsds/XmlTest_version.xsd | 19 + .../XML/XmlWorkflow/XmlTest_xsds/empty.xsd | 19 + .../XmlTest_xsds/noTargetNamespace.xsd | 22 + .../XML/XmlWorkflow/XmlTest_xsds/po.xsd | 77 + .../XML/XmlWorkflow/bin/.gitignore | 12 + regression_test/XML/XmlWorkflow/bin/prj2mk.pl | 154 + .../XML/XmlWorkflow/bin2/.gitignore | 14 + .../XML/XmlWorkflow/bin2/prj2mk.pl | 154 + .../XML/XmlWorkflow/src/UsefulTtcn3Types.ttcn | 82 + regression_test/XML/XmlWorkflow/src/XSD.ttcn | 322 + .../XML/XmlWorkflow/src/XmlTest.cfg | 46 + .../XmlWorkflow/src/XmlTest_protocolXsds.cfg | 41 + .../XML/XmlWorkflow/src/my_xml_test_script | 11 + .../XML/XmlWorkflow/src/xmlTest.prj | 249 + .../src/xmlTest_Functions_complex.ttcn | 1386 + .../src/xmlTest_Functions_complex1.ttcn | 60 + .../src/xmlTest_Functions_complex2.ttcn | 158 + .../src/xmlTest_Functions_element.ttcn | 1121 + .../src/xmlTest_Functions_list.ttcn | 70 + .../src/xmlTest_Functions_string.ttcn | 423 + .../XML/XmlWorkflow/src/xmlTest_Shell.ttcn | 325 + .../XmlWorkflow/src/xmlTest_Testcases.ttcn | 1803 + .../XML/XmlWorkflow/src/xmlTest_encDec.ttcn | 73 + .../src/xmlTest_protocolXsd_Testcases.ttcn | 590 + .../XmlWorkflow/src/xmlTest_protocolXsds.prj | 138 + .../XML/XmlWorkflow/xsd/HQ73011.xsd | 391 + .../XML/XmlWorkflow/xsd/PDUexample.xsd | 43 + regression_test/XML/XmlWorkflow/xsd/all.xsd | 69 + .../XML/XmlWorkflow/xsd/any_anyAttribute.xsd | 100 + .../XML/XmlWorkflow/xsd/attributeGroup.xsd | 40 + .../XML/XmlWorkflow/xsd/attribute_use.xsd | 91 + .../XmlWorkflow/xsd/attribute_use_noTNS.xsd | 72 + .../XML/XmlWorkflow/xsd/complexTypes.xsd | 465 + .../XML/XmlWorkflow/xsd/elements.xsd | 69 + .../xsd/extending_complex_types.xsd | 208 + .../XML/XmlWorkflow/xsd/group_all.xsd | 40 + .../XML/XmlWorkflow/xsd/groups.xsd | 235 + .../XML/XmlWorkflow/xsd/include1dir1a.xsd | 31 + .../XML/XmlWorkflow/xsd/include1dir1b.xsd | 27 + .../XML/XmlWorkflow/xsd/include1dir2a.xsd | 19 + .../XML/XmlWorkflow/xsd/include1dir2b.xsd | 21 + .../XML/XmlWorkflow/xsd/includeCircular1a.xsd | 45 + .../XML/XmlWorkflow/xsd/includeCircular1b.xsd | 25 + .../XML/XmlWorkflow/xsd/includeCircular2a.xsd | 23 + .../XML/XmlWorkflow/xsd/includeCircular2b.xsd | 21 + .../XML/XmlWorkflow/xsd/includeCircular3a.xsd | 19 + .../XML/XmlWorkflow/xsd/includeCircular3b.xsd | 21 + .../XML/XmlWorkflow/xsd/includeCircular4a.xsd | 20 + .../XML/XmlWorkflow/xsd/includeCircular4b.xsd | 21 + regression_test/XML/XmlWorkflow/xsd/list.xsd | 83 + .../XML/XmlWorkflow/xsd/list_invalid.xsd | 31 + .../XML/XmlWorkflow/xsd/minBound_maxBound.xsd | 114 + .../XmlWorkflow/xsd/minOccurs_maxOccurs.xsd | 115 + .../xsd/name_clash_element-attribute.xsd | 17 + ...ame_clash_element-attribute_noNsPrefix.xsd | 39 + .../XML/XmlWorkflow/xsd/ranges_float.xsd | 70 + .../XML/XmlWorkflow/xsd/ranges_integer.xsd | 66 + .../xsd/restricting_complex_types.xsd | 80 + .../XML/XmlWorkflow/xsd/schema.xsd | 16 + regression_test/XML/XmlWorkflow/xsd/union.xsd | 47 + regression_test/XML/macros.ttcnin | 169 + .../XML/xsdConverter/Examples/.gitignore | 33 + .../XML/xsdConverter/Examples/Example1.xsd | 49 + .../XML/xsdConverter/Examples/Example2.xsd | 40 + .../XML/xsdConverter/Examples/Example3.xsd | 42 + .../XML/xsdConverter/Examples/Example4.xsd | 26 + .../XML/xsdConverter/Examples/Examples.ttcn | 19 + .../XML/xsdConverter/Examples/Makefile | 54 + .../xsdConverter/Examples/chapter_5_1_1.xsd | 43 + .../xsdConverter/Examples/chapter_5_1_2.xsd | 23 + .../xsdConverter/Examples/chapter_5_1_3.xsd | 17 + .../xsdConverter/Examples/chapter_5_1_4.xsd | 15 + .../xsdConverter/Examples/chapter_5_1_5.xsd | 22 + .../xsdConverter/Examples/chapter_5_1_6.xsd | 22 + .../xsdConverter/Examples/chapter_5_2_1.xsd | 51 + .../xsdConverter/Examples/chapter_5_2_2.xsd | 45 + .../xsdConverter/Examples/chapter_5_2_3.xsd | 13 + .../XML/xsdConverter/Examples/chapter_6.xsd | 158 + .../XML/xsdConverter/Examples/chapter_7_1.xsd | 92 + .../XML/xsdConverter/Examples/chapter_7_3.xsd | 28 + .../XML/xsdConverter/Examples/chapter_7_4.xsd | 17 + .../XML/xsdConverter/Examples/chapter_7_5.xsd | 90 + .../XML/xsdConverter/Examples/chapter_7_6.xsd | 589 + .../XML/xsdConverter/Examples/chapter_7_7.xsd | 79 + .../XML/xsdConverter/Examples/chapter_7_8.xsd | 20 + .../XML/xsdConverter/Examples/chapter_7_9.xsd | 37 + .../XML/xsdConverter/Examples/config.cfg | 9 + .../XML/xsdConverter/HN21072/.gitignore | 14 + .../XML/xsdConverter/HN21072/HN21072Test.ttcn | 85 + .../XML/xsdConverter/HN21072/Makefile | 38 + .../XML/xsdConverter/HN21072/W3-WSDL-chop.xsd | 52 + .../XML/xsdConverter/HN21072/log2xml.pl | 18 + .../XML/xsdConverter/HN65402/.gitignore | 9 + .../XML/xsdConverter/HN65402/Makefile | 22 + .../XML/xsdConverter/HN65402/jellystone.ttcn | 28 + .../XML/xsdConverter/HN65402/jellystone.xsd | 40 + .../XML/xsdConverter/HO12250/.gitignore | 1 + .../XML/xsdConverter/HO12250/HO12250.xsd | 21 + .../XML/xsdConverter/HO12250/Makefile | 24 + .../XML/xsdConverter/HO16426/.gitignore | 11 + .../XML/xsdConverter/HO16426/Makefile | 23 + .../XML/xsdConverter/HO16426/diversion.ttcn | 24 + .../XML/xsdConverter/HO16426/diversion.xsd | 39 + .../XML/xsdConverter/HO18151/.gitignore | 10 + .../XML/xsdConverter/HO18151/HO18151.ttcn | 34 + .../XML/xsdConverter/HO18151/HO18151.xsd | 53 + .../XML/xsdConverter/HO18151/Makefile | 22 + .../XML/xsdConverter/HO21968/.gitignore | 13 + .../XML/xsdConverter/HO21968/HO21968.ttcn | 57 + .../xsdConverter/HO21968/HO21968noprefix.xsd | 22 + .../xsdConverter/HO21968/HO21968prefix.xsd | 22 + .../XML/xsdConverter/HO21968/Makefile | 24 + .../XML/xsdConverter/HQ48576/.gitignore | 12 + .../XML/xsdConverter/HQ48576/HQ48576Test.ttcn | 45 + .../XML/xsdConverter/HQ48576/Makefile | 34 + .../XML/xsdConverter/HQ48576/hlrla_types.xsd | 2014 + regression_test/XML/xsdConverter/Makefile | 32 + .../XML/xsdConverter/Makefile.converter | 71 + .../acceptance_test/Fibonacci/Fibonacci.cfg | 9 + .../acceptance_test/Fibonacci/Fibonacci.ttcn | 33 + .../acceptance_test/Fibonacci/Makefile | 123 + .../acceptance_test/chinese/Makefile | 125 + .../acceptance_test/chinese/chinese.ttcn | 590 + .../acceptance_test/comptest/.gitignore | 5 + .../acceptance_test/comptest/Makefile | 87 + .../acceptance_test/comptest/comptest.ttcn | 326 + .../acceptance_test/testerlanc/Makefile | 125 + .../testerlanc/testerlanc.ttcn | 68 + regression_test/all_from/.gitignore | 10 + regression_test/all_from/Makefile | 147 + regression_test/all_from/all_from.ttcn | 1344 + .../all_from/all_from_complement.ttcn | 519 + .../all_from/all_from_permutation.ttcn | 1772 + regression_test/all_from/all_from_subset.ttcn | 2656 + .../all_from/all_from_superset.ttcn | 989 + regression_test/all_from/all_from_var.ttcn | 303 + .../all_from/all_from_with_functions.ttcn | 128 + regression_test/all_from/everything.ttcn | 312 + regression_test/all_from/f_ext.cc | 16 + regression_test/all_from/f_ext.hh | 19 + regression_test/all_from/functions.ttcn | 229 + .../all_from/imported_templates.ttcn | 28 + regression_test/all_from/sapc.ttcn | 101 + regression_test/all_from/types.ttcn | 83 + regression_test/anytype/.gitignore | 30 + regression_test/anytype/AnyUser.ttcnpp | 76 + regression_test/anytype/AnytypeTest.ttcnpp | 263 + regression_test/anytype/Makefile | 160 + regression_test/anytype/Supplier.asn | 20 + regression_test/anytype/config.cfg | 14 + regression_test/anytype/noany.ttcn | 22 + regression_test/anytype/smallany.ttcn | 157 + regression_test/anytypeOper/.gitignore | 6 + regression_test/anytypeOper/Makefile | 49 + regression_test/anytypeOper/TanytypeOper.ttcn | 734 + .../anytypeOper/TanytypeWrapOper.ttcn | 742 + regression_test/anytypeOper/config.cfg | 16 + regression_test/arrayOper/.gitignore | 7 + regression_test/arrayOper/Makefile | 47 + regression_test/arrayOper/TarrayOper.ttcn | 952 + regression_test/arrayOper/config.cfg | 14 + regression_test/assignmentNotation/.gitignore | 7 + regression_test/assignmentNotation/Makefile | 51 + .../TassignmentNotation.asn | 18 + .../TassignmentNotation.cfg | 28 + .../TassignmentNotation.ttcn | 336 + .../TassignmentNotation_First.cfg | 16 + .../TassignmentNotation_Second.cfg | 12 + .../TassignmentNotation_Third.cfg | 7 + regression_test/basicStatem/.gitignore | 7 + regression_test/basicStatem/Makefile | 47 + regression_test/basicStatem/TbasicStatem.ttcn | 353 + regression_test/basicStatem/config.cfg | 13 + regression_test/bitstrOper/.gitignore | 7 + regression_test/bitstrOper/Makefile | 47 + regression_test/bitstrOper/TbitstrOper.ttcn | 701 + regression_test/bitstrOper/config.cfg | 14 + regression_test/boolOper/.gitignore | 7 + regression_test/boolOper/Makefile | 47 + regression_test/boolOper/TboolOper.ttcn | 322 + regression_test/boolOper/config.cfg | 14 + regression_test/cfgFile/Makefile | 28 + regression_test/cfgFile/define/Makefile | 28 + .../cfgFile/define/macro_reference/.gitignore | 2 + .../cfgFile/define/macro_reference/Makefile | 51 + .../macro_reference/TSTM_macro_test_main.cfg | 185 + .../TSTM_macro_test_testcases.ttcn | 324 + .../cfgFile/define/structured/.gitignore | 2 + .../cfgFile/define/structured/Makefile | 52 + .../cfgFile/define/structured/structured.cfg | 263 + .../cfgFile/define/structured/structured.ttcn | 430 + .../cfgFile/module_parameters/Makefile | 28 + .../module_parameters/assignment/.gitignore | 2 + .../module_parameters/assignment/Makefile | 48 + .../assignment/assignment.cfg | 178 + .../assignment/assignment.ttcn | 564 + .../module_parameters/concat/.gitignore | 2 + .../cfgFile/module_parameters/concat/Makefile | 48 + .../module_parameters/concat/concat.cfg | 54 + .../module_parameters/concat/concat.ttcn | 101 + .../cfgFile/ordered_include/.gitignore | 2 + .../cfgFile/ordered_include/Makefile | 55 + .../ordered_include/config_sub2/oi2_sub.cfg | 13 + .../configs_sub/oi1_subfolder1.cfg | 16 + .../cfgFile/ordered_include/oi.ttcn | 141 + .../cfgFile/ordered_include/oi1.cfg | 16 + .../cfgFile/ordered_include/oi1_after1.cfg | 16 + .../cfgFile/ordered_include/oi1_after2.cfg | 15 + .../cfgFile/ordered_include/oi1_after3.cfg | 15 + .../cfgFile/ordered_include/oi1_before1.cfg | 17 + .../cfgFile/ordered_include/oi1_before2.cfg | 15 + .../ordered_include/oi1_before_include.cfg | 15 + .../cfgFile/ordered_include/oi2.cfg | 13 + .../cfgFile/ordered_include/oi22.cfg | 13 + .../cfgFile/ordered_include/oi23.cfg | 13 + .../cfgFile/ordered_include/oi2_nomacro.cfg | 11 + .../cfgFile/ordered_include/oi_after1.cfg | 27 + .../cfgFile/ordered_include/oi_after2.cfg | 23 + .../ordered_include/oi_after_list1.cfg | 27 + .../ordered_include/oi_after_list2.cfg | 25 + .../cfgFile/ordered_include/oi_before1.cfg | 36 + .../cfgFile/ordered_include/oi_before2.cfg | 26 + .../cfgFile/ordered_include/oi_before3.cfg | 26 + .../cfgFile/ordered_include/oi_before4.cfg | 28 + .../cfgFile/ordered_include/oi_before5.cfg | 23 + .../oi_include_interference.cfg | 29 + .../ordered_include/oi_include_mix.cfg | 23 + .../cfgFile/ordered_include/oi_last1.cfg | 23 + .../cfgFile/ordered_include/oi_last2.cfg | 26 + .../cfgFile/ordered_include/oi_last3.cfg | 75 + .../cfgFile/ordered_include/oi_subfolder1.cfg | 26 + .../cfgFile/testport_parameters/Makefile | 50 + .../cfgFile/testport_parameters/PCOType.cc | 114 + .../cfgFile/testport_parameters/PCOType.hh | 52 + .../testport_parameters/array_index.cfg | 18 + .../testport_parameters/array_index.ttcn | 27 + regression_test/cfg_list_concat/.gitignore | 6 + regression_test/cfg_list_concat/Makefile | 158 + regression_test/cfg_list_concat/concat.prj | 45 + regression_test/cfg_list_concat/concat.ttcn | 46 + .../cfg_list_concat/everything.cfg | 78 + regression_test/cfg_list_concat/sub1.cfg | 10 + regression_test/cfg_list_concat/sub2.cfg | 13 + regression_test/charOper/.gitignore | 7 + regression_test/charOper/Makefile | 47 + regression_test/charOper/TcharOper.ttcn | 95 + regression_test/charOper/config.cfg | 14 + regression_test/charstrOper/.gitignore | 7 + regression_test/charstrOper/Makefile | 47 + regression_test/charstrOper/TcharstrOper.ttcn | 537 + regression_test/charstrOper/config.cfg | 14 + regression_test/commMessage/.gitignore | 15 + regression_test/commMessage/HS41022.ttcn | 69 + .../commMessage/ImplMsgEncData.asn | 22 + regression_test/commMessage/Makefile | 60 + regression_test/commMessage/TcommMessage.ttcn | 1503 + regression_test/commMessage/config.cfg | 16 + .../commMessage/config_parallel.cfg | 15 + regression_test/commProcedure/.gitignore | 18 + regression_test/commProcedure/ExtProcPort.cc | 93 + regression_test/commProcedure/ExtProcPort.hh | 53 + regression_test/commProcedure/Makefile | 76 + regression_test/commProcedure/PortAddress.cc | 113 + regression_test/commProcedure/PortAddress.hh | 61 + regression_test/commProcedure/ProcPort.ttcn | 611 + regression_test/compileonly/.gitignore | 2 + regression_test/compileonly/Makefile | 20 + .../compileonly/assignmentNotation/.gitignore | 7 + .../compileonly/assignmentNotation/Makefile | 41 + .../TassignmentNotation.ttcn | 281 + .../compileonly/attribQualif/.gitignore | 7 + .../compileonly/attribQualif/Makefile | 44 + .../attribQualif/TattribQualif.ttcn | 60 + .../compileonly/centralstorage/.gitignore | 2 + .../compileonly/centralstorage/Makefile | 113 + .../centralstorage/base_asn/.gitignore | 8 + .../centralstorage/base_asn/Base_asn.asn | 13 + .../centralstorage/base_mixed/.gitignore | 19 + .../base_mixed/Base_mixed_asn.asn | 12 + .../base_mixed/base_mixed_PT.cc | 69 + .../base_mixed/base_mixed_PT.hh | 47 + .../base_mixed/base_mixed_ttcn.ttcn | 26 + .../base_mixed/base_mixed_ttcnpp.ttcnpp | 13 + .../centralstorage/base_ttcn/.gitignore | 10 + .../centralstorage/base_ttcn/base_PT.cc | 69 + .../centralstorage/base_ttcn/base_PT.hh | 47 + .../centralstorage/base_ttcn/base_ttcn.ttcnpp | 24 + .../centralstorage/extended_ttcn/.gitignore | 15 + .../extended_ttcn/extended_ttcn.ttcn | 23 + .../extended_ttcn/extended_ttcnpp.ttcnpp | 13 + .../separate_project/.gitignore | 3 + .../centralstorage/separate_user/.gitignore | 10 + .../centralstorage/separate_user/config.cfg | 8 + .../separate_user/separate_user.ttcn | 22 + .../centralstorage/user_all_bases/.gitignore | 9 + .../user_all_bases/user_all_bases.ttcn | 21 + .../centralstorage/user_ttcn/.gitignore | 9 + .../centralstorage/user_ttcn/fake.ttcnpp | 10 + .../centralstorage/user_ttcn/user_ttcn.ttcn | 18 + .../compileonly/circularImport/.gitignore | 13 + .../compileonly/circularImport/A.asn | 18 + .../compileonly/circularImport/B.asn | 19 + .../compileonly/circularImport/Makefile | 45 + .../compileonly/compareImported/.gitignore | 18 + .../compileonly/compareImported/A.ttcn | 31 + .../compileonly/compareImported/B.ttcn | 15 + .../compileonly/compareImported/C.ttcn | 10 + .../compileonly/compareImported/Makefile | 47 + .../compileonly/compoundif/.gitignore | 7 + .../compileonly/compoundif/Makefile | 41 + .../compileonly/compoundif/Tcompoundif.ttcn | 44 + .../compileonly/dynamicTemplate/.gitignore | 8 + .../dynamicTemplate/DynamicTemplate.ttcn | 279 + .../compileonly/dynamicTemplate/Makefile | 55 + .../dynamicTemplate/TD_Dynamic_Templates.doc | Bin 0 -> 150528 bytes .../compileonly/dynamicTemplate/external.cc | 30 + .../compileonly/isbound/.gitignore | 13 + regression_test/compileonly/isbound/Makefile | 142 + .../compileonly/isbound/bad_SE.ttcn | 26 + .../compileonly/isbound/bogus_SY.ttcn | 25 + .../isbound/isbound_component_OK.ttcn | 28 + .../compileonly/isbound/isbound_port_SE.ttcn | 34 + .../isbound/isbound_testcase_SE.ttcn | 26 + .../compileonly/isbound/one_OK.ttcn | 75 + .../compileonly/mfgen-tpd/.gitignore | 3 + .../compileonly/mfgen-tpd/COMMON/.gitignore | 1 + .../COMMON/ProtocolModules_Common.tpd | 31 + .../mfgen-tpd/COMMON/src/General_Types.ttcn | 23 + .../COMMON/src/MobileDomainDefinitions.asn | 37 + .../compileonly/mfgen-tpd/HP79745/.gitignore | 1 + .../mfgen-tpd/HP79745/Hello000/Hello000.tpd | 45 + .../HP79745/Hello000/src/MyExample0.ttcn | 14 + .../mfgen-tpd/HP79745/Hello123/Hello123.tpd | 50 + .../HP79745/Hello123/src/MyExample1.ttcn | 15 + .../mfgen-tpd/HP79745/HelloTpd/.gitignore | 1 + .../mfgen-tpd/HP79745/HelloTpd/.project | 19 + .../mfgen-tpd/HP79745/HelloTpd/HelloTpd.tpd | 56 + .../HP79745/HelloTpd/src/MyExample.ttcn | 14 + .../compileonly/mfgen-tpd/HP79745/Makefile | 39 + .../compileonly/mfgen-tpd/HQ56829/.gitignore | 1 + .../compileonly/mfgen-tpd/HQ56829/Makefile | 16 + .../compileonly/mfgen-tpd/HQ56834/Makefile | 23 + .../mfgen-tpd/HQ56834/bin/.gitignore | 1 + .../mfgen-tpd/HQ56834/bin/emptyfolder | 1 + .../compileonly/mfgen-tpd/HQ56834/counter.tpd | 37 + .../mfgen-tpd/HQ56834/src/counter.ttcn | 17 + .../compileonly/mfgen-tpd/HQ56848/.gitignore | 2 + .../compileonly/mfgen-tpd/HQ56848/Makefile | 22 + .../compileonly/mfgen-tpd/HQ56848/counter.tpd | 37 + .../compileonly/mfgen-tpd/HQ60308/.gitignore | 6 + .../compileonly/mfgen-tpd/HQ60308/counter.tpd | 32 + .../compileonly/mfgen-tpd/HR30356/Makefile | 43 + .../mfgen-tpd/HR30356/client/client.tpd | 36 + .../mfgen-tpd/HR30356/client/src/client.ttcn | 10 + .../HR30356/controller/controller.tpd | 37 + .../HR30356/controller/src/controller.ttcn | 13 + .../mfgen-tpd/HR30356/server/server.tpd | 36 + .../mfgen-tpd/HR30356/server/src/server.ttcn | 10 + .../HR30356/testport/src/testport.ttcn | 9 + .../mfgen-tpd/HR30356/testport/testport.tpd | 33 + .../mfgen-tpd/HR30365/Hello000/Hello000.tpd | 45 + .../HR30365/Hello000/src/MyExample0.ttcn | 14 + .../mfgen-tpd/HR30365/Hello123/Hello123.tpd | 51 + .../HR30365/Hello123/src/MyExample1.ttcn | 15 + .../mfgen-tpd/HR30365/HelloTpd/.gitignore | 1 + .../mfgen-tpd/HR30365/HelloTpd/HelloTpd.tpd | 56 + .../HR30365/HelloTpd/src/MyExample.ttcn | 14 + .../compileonly/mfgen-tpd/HR30365/Makefile | 38 + .../compileonly/mfgen-tpd/Makefile | 97 + .../NAS_EPS_v9.7.0_CNL113729.tpd | 49 + .../src/NAS_EPS_v970.ttcn | 85 + .../test/NAS_EPS_Test.cfg | 9 + .../test/NAS_EPS_Test.ttcn | 58 + .../test/NAS_EPS_v9.7.0_CNL113729_test.tpd | 35 + .../buildconfig_param/HelloTpd/.gitignore | 1 + .../buildconfig_param/HelloTpd/.project | 18 + .../buildconfig_param/HelloTpd/HelloTpd.tpd | 57 + .../HelloTpd/src/MyExample.cfg | 14 + .../HelloTpd/src/MyExample.ttcn | 46 + .../buildconfig_param/HelloTpd/src/PCOType.cc | 96 + .../buildconfig_param/HelloTpd/src/PCOType.hh | 47 + .../mfgen-tpd/buildconfig_param/Makefile | 38 + .../compileonly/mfgen-tpd/consumer/.gitignore | 1 + .../compileonly/mfgen-tpd/consumer/.project | 26 + .../consumer-ref-supplier-Default.tpd | 62 + .../mfgen-tpd/consumer/creator.ttcn | 17 + .../mfgen-tpd/consumer/src/consumer.ttcn | 27 + .../mfgen-tpd/consumer/src/userfun.cc | 8 + .../mfgen-tpd/dependency_check/Makefile | 41 + .../dependency_check/client/client.tpd | 39 + .../dependency_check/client/src/client.ttcn | 10 + .../controller/controller.tpd | 40 + .../controller/src/controller.ttcn | 13 + .../dependency_check/server/server.tpd | 39 + .../dependency_check/server/src/server.ttcn | 10 + .../testport/src/testport.ttcn | 9 + .../dependency_check/testport/testport.tpd | 35 + .../mfgen-tpd/flagTest/Hello000/Hello000.tpd | 45 + .../flagTest/Hello000/src/MyExample0.ttcn | 14 + .../mfgen-tpd/flagTest/Hello123/Hello123.tpd | 50 + .../flagTest/Hello123/src/MyExample1.ttcn | 15 + .../mfgen-tpd/flagTest/HelloTpd/.gitignore | 1 + .../mfgen-tpd/flagTest/HelloTpd/HelloTpd.tpd | 56 + .../flagTest/HelloTpd/src/MyExample.ttcn | 14 + .../flagTest/HelloTpd2/HelloTpd2.tpd | 59 + .../flagTest/HelloTpd2/src/MyExample2.ttcn | 14 + .../compileonly/mfgen-tpd/flagTest/Makefile | 38 + .../compileonly/mfgen-tpd/handmade.ttcn | 16 + .../HelloTpd/.gitignore | 2 + .../HelloTpd/.project | 18 + .../HelloTpd/HelloTpd.tpd | 57 + .../HelloTpd/src/MyExample.cfg | 14 + .../HelloTpd/src/MyExample.ttcn | 46 + .../HelloTpd/src/PCOType.cc | 96 + .../HelloTpd/src/PCOType.hh | 47 + .../invalid_buildconfig_param/Makefile | 40 + .../invalid_buildconfig_tpd/.gitignore | 1 + .../Hello000/Hello000.tpd | 48 + .../Hello000/src/MyExample0.cfg | 14 + .../Hello000/src/MyExample0.ttcn | 46 + .../Hello000/src/PCOType0.cc | 96 + .../Hello000/src/PCOType0.hh | 47 + .../Hello123/Hello123.tpd | 59 + .../Hello123/src/MyExample1.cfg | 14 + .../Hello123/src/MyExample1.ttcn | 73 + .../Hello123/src/PCOType1.cc | 96 + .../Hello123/src/PCOType1.hh | 47 + .../HelloTpd/.gitignore | 1 + .../invalid_buildconfig_tpd/HelloTpd/.project | 19 + .../HelloTpd/HelloTpd.tpd | 58 + .../HelloTpd/src/MyExample.cfg | 14 + .../HelloTpd/src/MyExample.ttcn | 46 + .../HelloTpd/src/PCOType.cc | 96 + .../HelloTpd/src/PCOType.hh | 47 + .../invalid_buildconfig_tpd/Makefile | 40 + .../compileonly/mfgen-tpd/library/.gitignore | 1 + .../mfgen-tpd/library/HelloTpd/.gitignore | 1 + .../mfgen-tpd/library/HelloTpd/.project | 18 + .../mfgen-tpd/library/HelloTpd/HelloTpd.tpd | 40 + .../library/HelloTpd/src/MyExample.cfg | 14 + .../library/HelloTpd/src/MyExample.ttcn | 46 + .../mfgen-tpd/library/HelloTpd/src/PCOType.cc | 96 + .../mfgen-tpd/library/HelloTpd/src/PCOType.hh | 47 + .../mfgen-tpd/library/HelloTpd2/.gitignore | 3 + .../mfgen-tpd/library/HelloTpd2/HelloTpd.tpd | 40 + .../compileonly/mfgen-tpd/library/Makefile | 270 + .../compileonly/mfgen-tpd/library/a.ttcn | 12 + .../compileonly/mfgen-tpd/library/b.ttcn | 15 + .../library/central_storage/.gitignore | 6 + .../library/central_storage/central.ttcn | 14 + .../compileonly/mfgen-tpd/outsider.ttcn | 16 + .../compileonly/mfgen-tpd/runner.pl | 72 + .../compileonly/mfgen-tpd/subplier/.gitignore | 1 + .../compileonly/mfgen-tpd/subplier/.project | 52 + .../mfgen-tpd/subplier/src/subway.ttcn | 14 + .../mfgen-tpd/subplier/subplier.tpd | 52 + .../compileonly/mfgen-tpd/supplier/.gitignore | 1 + .../compileonly/mfgen-tpd/supplier/.project | 19 + .../mfgen-tpd/supplier/src/supplier.ttcn | 17 + .../mfgen-tpd/supplier/src/supplier2.ttcn | 16 + .../mfgen-tpd/supplier/supplier24.tpd | 39 + .../namedActualParameters/.gitignore | 7 + .../namedActualParameters/Makefile | 41 + .../TnamedActualParameters.ttcn | 160 + .../compileonly/openType/.gitignore | 8 + regression_test/compileonly/openType/Makefile | 45 + regression_test/compileonly/openType/X.asn | 44 + .../optionalAssignCompare/.gitignore | 7 + .../optionalAssignCompare/Makefile | 41 + .../ToptionalAssignCompare.ttcn | 108 + .../compileonly/portConstructor/.gitignore | 18 + .../compileonly/portConstructor/Makefile | 51 + .../compileonly/portConstructor/x.ttcn | 34 + .../compileonly/styleGuide/.gitignore | 28 + .../styleGuide/Another_module.ttcn | 36 + .../compileonly/styleGuide/Makefile | 72 + .../compileonly/styleGuide/MyASN1_module.asn | 12 + .../styleGuide/MySample_module.ttcn | 504 + .../compileonly/styleGuide/external.cc | 21 + .../compileonly/topLevelPdu/.gitignore | 13 + regression_test/compileonly/topLevelPdu/A.asn | 26 + regression_test/compileonly/topLevelPdu/B.asn | 14 + .../compileonly/topLevelPdu/Makefile | 46 + .../compileonly/typeInstantiation/.gitignore | 13 + .../compileonly/typeInstantiation/A.asn | 45 + .../compileonly/typeInstantiation/B.asn | 14 + .../compileonly/typeInstantiation/Makefile | 45 + regression_test/configOper/.gitignore | 12 + regression_test/configOper/Makefile | 46 + regression_test/configOper/TconfigOper.ttcn | 1289 + regression_test/controlTimer/.gitignore | 7 + regression_test/controlTimer/Makefile | 47 + .../controlTimer/TcontrolTimer.ttcn | 59 + regression_test/controlTimer/config.cfg | 10 + regression_test/defaultOper/Makefile | 47 + regression_test/defaultOper/TdefaultOper.ttcn | 109 + regression_test/defaultOper/config.cfg | 14 + regression_test/enumOper/.gitignore | 7 + regression_test/enumOper/Makefile | 47 + regression_test/enumOper/TenumOper.ttcn | 286 + regression_test/enumOper/config.cfg | 14 + regression_test/floatOper/.gitignore | 7 + regression_test/floatOper/Makefile | 47 + regression_test/floatOper/TfloatOper.ttcn | 496 + regression_test/floatOper/config.cfg | 14 + regression_test/functionReference/.gitignore | 7 + .../functionReference/FuncRef.ttcn | 466 + regression_test/functionReference/Makefile | 47 + regression_test/functionReference/config.cfg | 14 + regression_test/hexstrOper/.gitignore | 9 + regression_test/hexstrOper/Makefile | 47 + regression_test/hexstrOper/ThexstrOper.ttcn | 96 + regression_test/hexstrOper/config.cfg | 14 + regression_test/iconv/.gitignore | 5 + regression_test/iconv/Makefile | 117 + regression_test/iconv/config.cfg | 14 + regression_test/iconv/converter.ttcn | 56 + regression_test/iconv/convertest.ttcn | 202 + regression_test/iconv/iconver.cc | 108 + .../implicitMsgEncoding/.gitignore | 8 + regression_test/implicitMsgEncoding/Makefile | 55 + .../implicitMsgEncoding/PCOType.cc | 109 + .../implicitMsgEncoding/PCOType.hh | 57 + .../implicitMsgEncoding/TimplicitEnc.ttcn | 229 + .../implicitMsgEncoding/config.cfg | 15 + regression_test/implicitOmit/.gitignore | 6 + regression_test/implicitOmit/Makefile | 141 + regression_test/implicitOmit/config.cfg | 26 + regression_test/implicitOmit/io.ttcn | 593 + regression_test/intOper/.gitignore | 7 + regression_test/intOper/Makefile | 52 + regression_test/intOper/PCOType.cc | 130 + regression_test/intOper/PCOType.hh | 55 + regression_test/intOper/TintOper.ttcn | 1068 + regression_test/intOper/config.cfg | 14 + regression_test/ipv6/.gitignore | 4 + regression_test/ipv6/Makefile | 49 + regression_test/ipv6/host_ipv6_global.cfg | 16 + regression_test/ipv6/host_link_local.cfg | 16 + regression_test/ipv6/invalid_global_ipv6.cfg | 15 + .../ipv6/invalid_global_ipv6_long.cfg | 15 + regression_test/ipv6/ip_create_on_host.cfg | 18 + regression_test/ipv6/ipv6.ttcn | 90 + regression_test/ipv6/ipv6_all_global.cfg | 17 + .../ipv6/ipv6_long_short_global.cfg | 17 + regression_test/ipv6/ipv_hostname_macro.cfg | 16 + regression_test/ipv6/link_local_ipv6.cfg | 15 + .../ipv6/localhost_create_on_host.cfg | 18 + .../ipv6/localhost_ip_create_on_host.cfg | 18 + .../ipv6/long_host_ipv6_global.cfg | 16 + regression_test/ipv6/long_ipv6_global.cfg | 17 + .../ipv6/no_full_syntax_check_link_local.cfg | 16 + .../no_full_syntax_check_link_local_long.cfg | 15 + regression_test/ipv6/platformcheck | 29 + regression_test/ipv6/total_link_local.cfg | 16 + regression_test/ipv6/valid_global_ipv6.cfg | 15 + regression_test/ispresent/IsPresent_Test.cfg | 17 + regression_test/ispresent/IsPresent_Test.ttcn | 941 + regression_test/ispresent/Makefile | 49 + regression_test/json/AttributeTestcases.ttcn | 201 + regression_test/json/Functions.ttcn | 240 + regression_test/json/JSON.cfg | 95 + regression_test/json/JsonData.asn | 117 + regression_test/json/Makefile | 62 + regression_test/json/SemanticCheck.ttcn | 59 + regression_test/json/Testcases.ttcn | 578 + regression_test/json/Types.ttcn | 162 + regression_test/junitlogger/Makefile | 48 + regression_test/junitlogger/main1.cfg | 28 + regression_test/junitlogger/main1.ttcn | 53 + regression_test/junitlogger/test_junitlog.pl | 98 + regression_test/junitlogger/test_junitlog.sh | 14 + regression_test/lazyEval/LazyASNTypes.asn | 47 + regression_test/lazyEval/Makefile | 59 + regression_test/lazyEval/lazy.cfg | 75 + regression_test/lazyEval/lazy_A.ttcn | 48 + regression_test/lazyEval/lazy_B.ttcn | 23 + regression_test/lazyEval/lazy_defs.ttcn | 92 + regression_test/lazyEval/lazy_main.ttcn | 2241 + regression_test/logFiles/.gitignore | 20 + regression_test/logFiles/CommonStuff.ttcn | 732 + regression_test/logFiles/LogFiles.cfg | 28 + regression_test/logFiles/LogFiles.ttcn | 314 + regression_test/logFiles/LogFiles2.cfg | 12 + regression_test/logFiles/LogFilesInc.cfg | 16 + regression_test/logFiles/LogFilesProc.cfg | 16 + regression_test/logFiles/Makefile | 97 + regression_test/logFiles/TitanLogTest.cfg | 23 + regression_test/logFiles/TitanLogTest.ttcn | 266 + regression_test/logFiles/diffLogs | 74 + regression_test/logFiles/extfunc.cc | 121 + regression_test/logFiles/logFiles_doc.script | 181 + regression_test/logger/Makefile | 28 + .../logger/emergency_logging/Console_N.txt | 151 + .../logger/emergency_logging/Console_O.txt | 95 + .../emergency_logging/EL_BufferAll_1.cfg | 31 + .../emergency_logging/EL_BufferAll_10.cfg | 63 + .../EL_BufferAll_10_mtc_expected.log | 145 + .../emergency_logging/EL_BufferAll_11.cfg | 62 + .../EL_BufferAll_11_mtc_expected.log | 927 + .../emergency_logging/EL_BufferAll_12.cfg | 42 + .../EL_BufferAll_12_mtc_expected.log | 14 + .../emergency_logging/EL_BufferAll_13.cfg | 42 + .../EL_BufferAll_13_mtc_expected.log | 15 + .../emergency_logging/EL_BufferAll_1_NOEL.cfg | 31 + .../emergency_logging/EL_BufferAll_2.cfg | 58 + .../emergency_logging/EL_BufferAll_3.cfg | 63 + .../emergency_logging/EL_BufferAll_3_NOEL.cfg | 62 + .../emergency_logging/EL_BufferAll_4.cfg | 58 + .../emergency_logging/EL_BufferAll_5.cfg | 37 + .../emergency_logging/EL_BufferAll_6.cfg | 37 + .../emergency_logging/EL_BufferAll_7.cfg | 38 + .../emergency_logging/EL_BufferAll_7A.cfg | 38 + .../EL_BufferAll_7A_mtc_expected.log | 17 + .../EL_BufferAll_7_mtc_expected.log | 18 + .../emergency_logging/EL_BufferAll_8.cfg | 58 + .../emergency_logging/EL_BufferAll_9.cfg | 63 + .../EL_BufferAll_9_mtc_expected.log | 56 + .../emergency_logging/EL_BufferMasked_1.cfg | 31 + .../emergency_logging/EL_BufferMasked_10.cfg | 59 + .../EL_BufferMasked_10_mtc_expected.log | 14 + ...BufferMasked_10_mtc_expected.log_emergency | 131 + .../emergency_logging/EL_BufferMasked_11.cfg | 62 + .../EL_BufferMasked_11_mtc_expected.log | 74 + ...BufferMasked_11_mtc_expected.log_emergency | 477 + .../emergency_logging/EL_BufferMasked_12.cfg | 45 + .../EL_BufferMasked_12_mtc_expected.log | 10 + ...BufferMasked_12_mtc_expected.log_emergency | 4 + .../emergency_logging/EL_BufferMasked_13.cfg | 42 + .../EL_BufferMasked_13_mtc_expected.log | 10 + ...BufferMasked_13_mtc_expected.log_emergency | 5 + .../emergency_logging/EL_BufferMasked_2.cfg | 58 + .../emergency_logging/EL_BufferMasked_3.cfg | 63 + .../emergency_logging/EL_BufferMasked_4.cfg | 58 + .../emergency_logging/EL_BufferMasked_5.cfg | 38 + .../emergency_logging/EL_BufferMasked_6.cfg | 37 + .../emergency_logging/EL_BufferMasked_7.cfg | 38 + .../EL_BufferMasked_7_mtc_expected.log | 5 + ..._BufferMasked_7_mtc_expected.log_emergency | 15 + .../emergency_logging/EL_BufferMasked_8.cfg | 58 + .../emergency_logging/EL_BufferMasked_9.cfg | 61 + .../EL_BufferMasked_9_mtc_expected.log | 14 + ..._BufferMasked_9_mtc_expected.log_emergency | 60 + .../emergency_logging/EmergencyLogTest.sh | 342 + .../EmergencyLoggingTest.ttcn | 107 + .../EmergencyLoggingTest_BuffMasked.cfg | 59 + .../logger/emergency_logging/Makefile | 180 + .../logger/emergency_logging/PCO_PT.cc | 92 + .../logger/emergency_logging/PCO_PT.hh | 50 + .../emergency_logging/Titan_LogTest.ttcn | 320 + .../Titan_LogTestDefinitions.ttcn | 39 + .../emergency_logging/failed_testcases.txt | 8 + .../logger/emergency_logging/runlog.txt | 5769 ++ regression_test/logger/logcontrol/Makefile | 147 + .../logcontrol/Titan_LogControlTest.cfg | 47 + .../logcontrol/Titan_LogControlTest.ttcn | 552 + .../logtest/Console_original_merged_log.txt | 193 + regression_test/logger/logtest/Makefile | 180 + regression_test/logger/logtest/PCO_PT.cc | 94 + regression_test/logger/logtest/PCO_PT.hh | 50 + .../logger/logtest/Titan_LogTest.cfg | 45 + .../logger/logtest/Titan_LogTest.ttcn | 320 + .../logtest/Titan_LogTestDefinitions.ttcn | 39 + .../logger/logtest/Titan_LogTest_ACTION.cfg | 45 + .../Titan_LogTest_ACTIONplusEXECUTOR_RT.cfg | 45 + .../logger/logtest/Titan_LogTest_DEBUG.cfg | 45 + ...itan_LogTest_DEFAULT_OPplusEXECUTOR_RT.cfg | 45 + .../logtest/Titan_LogTest_ERRORplusRT.cfg | 45 + .../logtest/Titan_LogTest_EXECUTOR_LOGOPT.cfg | 45 + .../Titan_LogTest_EXECUTOR_RTplusCOMP.cfg | 45 + .../Titan_LogTest_EXECUTOR_RTplusLOGOPT.cfg | 45 + .../logger/logtest/Titan_LogTest_EXEC_RT.cfg | 45 + .../logtest/Titan_LogTest_EX_UNQUAL.cfg | 45 + .../Titan_LogTest_E_RTplus_E_CONFIGDATA.cfg | 45 + .../logger/logtest/Titan_LogTest_FUNC.cfg | 45 + .../logger/logtest/Titan_LogTest_MATCH.cfg | 45 + .../logger/logtest/Titan_LogTest_PARALLEL.cfg | 45 + .../logtest/Titan_LogTest_PORTEVENT.cfg | 45 + .../logger/logtest/Titan_LogTest_STAT.cfg | 45 + .../logger/logtest/Titan_LogTest_TC.cfg | 45 + .../logger/logtest/Titan_LogTest_TIMER.cfg | 45 + .../logtest/Titan_LogTest_TTCN_ACTION.cfg | 45 + .../logger/logtest/Titan_LogTest_USER.cfg | 45 + .../logger/logtest/Titan_LogTest_VERDICT.cfg | 45 + .../logger/logtest/Titan_LogTest_WARNING.cfg | 45 + regression_test/logger/logtest/logtest.sh | 232 + .../logger/logtest/original_merged_log.txt | 450 + .../logtest/original_merged_log_modified.txt | 450 + regression_test/logger_control/.gitignore | 9 + regression_test/logger_control/Makefile | 148 + regression_test/logger_control/config.cfg | 31 + .../logger_control/logcontrol.ttcn | 167 + regression_test/logger_control/logfilecheck | 144 + regression_test/loggerplugin/.gitignore | 7 + regression_test/loggerplugin/Makefile | 47 + regression_test/loggerplugin/a.ttcn | 15 + regression_test/loggerplugin/config.cfg | 17 + regression_test/lostTimer/.gitignore | 7 + regression_test/lostTimer/Makefile | 47 + regression_test/lostTimer/TlostTimer.ttcn | 49 + regression_test/lostTimer/config.cfg | 10 + regression_test/macros/.gitignore | 6 + regression_test/macros/Macros.ttcn | 178 + regression_test/macros/Makefile | 47 + regression_test/macros/config.cfg | 14 + regression_test/modifiedTemplate/.gitignore | 7 + regression_test/modifiedTemplate/Makefile | 47 + .../modifiedTemplate/TmodifiedTemplate.ttcn | 263 + regression_test/modifiedTemplate/config.cfg | 10 + .../namedActualParameters/.gitignore | 18 + .../namedActualParameters/Makefile | 47 + .../namedActualParameters/config.cfg | 15 + .../namedActualParameters/inlinetemplate.ttcn | 34 + .../namedActualParameters/namedparam.ttcn | 122 + .../namedActualParameters/small.ttcn | 53 + .../namedActualParameters/templates.ttcn | 45 + regression_test/negativeTest/.gitignore | 7 + regression_test/negativeTest/Makefile | 107 + regression_test/negativeTest/NegTest.cfg | 19 + .../negativeTest/NegTestTestcases.ttcn | 3485 + regression_test/negativeTest/NegTestTypes.asn | 338 + regression_test/negativeTest/NegTest_RAW.cfg | 21 + .../negativeTest/NegTest_RAW_Testcases.ttcn | 3377 + .../negativeTest/NegTest_RAW_Types.ttcn | 968 + regression_test/negativeTest/NegTest_TEXT.cfg | 20 + .../negativeTest/NegTest_TEXT_Testcases.ttcn | 2866 + .../negativeTest/NegTest_TEXT_Types.ttcn | 220 + regression_test/negativeTest/NegTest_XML.cfg | 20 + .../negativeTest/NegTest_XML_Testcases.ttcn | 2733 + .../negativeTest/NegTest_XML_Types.xsd | 756 + regression_test/negativeTest/NegTest_all.cfg | 22 + regression_test/negativeTest/Types.asn | 85 + .../negativeTest/UsefulTtcn3Types.ttcn | 82 + regression_test/negativeTest/XSD.ttcn | 322 + regression_test/negativeTest/config.cfg | 15 + regression_test/negativeTest/negtest.ttcn | 1794 + ...ww_XmlTest_org_negativeTest_XML_Types.ttcn | 1179 + regression_test/nonMandatoryPar/.gitignore | 12 + regression_test/nonMandatoryPar/Makefile | 54 + .../nonMandatoryPar/TnonMandatory.ttcn | 395 + regression_test/nonMandatoryPar/config.cfg | 14 + regression_test/objidOper/.gitignore | 10 + regression_test/objidOper/Makefile | 51 + regression_test/objidOper/TobjidOper.ttcn | 265 + regression_test/objidOper/config.cfg | 14 + regression_test/objidOper/indexer.cc | 23 + regression_test/octetstrOper/.gitignore | 7 + regression_test/octetstrOper/Makefile | 47 + .../octetstrOper/ToctetstrOper.ttcn | 561 + regression_test/octetstrOper/config.cfg | 14 + regression_test/omitdef/.gitignore | 13 + regression_test/omitdef/Datatypes.asn | 25 + regression_test/omitdef/Dumping.hh | 23 + regression_test/omitdef/Makefile | 62 + regression_test/omitdef/PT_DefOpt.cc | 97 + regression_test/omitdef/PT_DefOpt.hh | 55 + regression_test/omitdef/Tsenderos.ttcn | 170 + regression_test/omitdef/config.cfg | 16 + regression_test/pattern_quadruples/.gitignore | 6 + regression_test/pattern_quadruples/Makefile | 47 + regression_test/pattern_quadruples/config.cfg | 14 + .../pattern_quadruples.ttcn | 97 + regression_test/post_commit_test | 1 + regression_test/preCompilerFlags/.gitignore | 9 + regression_test/preCompilerFlags/Makefile | 56 + .../preCompilerFlags/TpreCompilerFlags.ttcnpp | 107 + regression_test/preCompilerFlags/config.cfg | 15 + .../preCompilerFlags/test_include.inc | 5 + .../preCompilerFlags/test_macro.inc | 5 + regression_test/predefFunction/.gitignore | 7 + regression_test/predefFunction/Makefile | 162 + regression_test/predefFunction/PreDef.cfg | 52 + regression_test/predefFunction/bit_to_OK.ttcn | 284 + regression_test/predefFunction/bit_to_SW.ttcn | 306 + .../predefFunction/char_to_OK.ttcn | 151 + .../predefFunction/char_to_SW.ttcn | 155 + regression_test/predefFunction/encdec_OK.ttcn | 191 + .../predefFunction/enum_to_OK.ttcn | 92 + .../predefFunction/enum_to_SW.ttcn | 101 + .../predefFunction/float_to_OK.ttcn | 123 + .../predefFunction/float_to_SW.ttcn | 120 + regression_test/predefFunction/hex_to_OK.ttcn | 274 + regression_test/predefFunction/hex_to_SW.ttcn | 293 + regression_test/predefFunction/int_to_OK.ttcn | 463 + regression_test/predefFunction/int_to_SW.ttcn | 444 + .../predefFunction/isprecho_OK.ttcn | 383 + .../predefFunction/length_of_OK.ttcn | 362 + .../predefFunction/length_of_SW.ttcn | 252 + regression_test/predefFunction/oct_to_OK.ttcn | 279 + regression_test/predefFunction/oct_to_SW.ttcn | 318 + regression_test/predefFunction/regex_OK.ttcn | 155 + .../predefFunction/replacer_OK.ttcn | 133 + .../predefFunction/replacer_SW.ttcn | 153 + regression_test/predefFunction/rotter_OK.ttcn | 548 + regression_test/predefFunction/rotter_SW.ttcn | 430 + regression_test/predefFunction/shifty_OK.ttcn | 262 + regression_test/predefFunction/shifty_SW.ttcn | 241 + .../predefFunction/size_of_OK.ttcn | 180 + .../predefFunction/size_of_SW.ttcn | 210 + regression_test/predefFunction/str_to_OK.ttcn | 593 + regression_test/predefFunction/str_to_SW.ttcn | 453 + .../predefFunction/sub_str_OK.ttcn | 279 + .../predefFunction/sub_str_SW.ttcn | 252 + regression_test/predefFunction/tcname_OK.ttcn | 53 + regression_test/predefFunction/tcname_SW.ttcn | 52 + regression_test/prereq.pl | 40 + regression_test/recofOper/.gitignore | 7 + regression_test/recofOper/BerType.asn | 21 + regression_test/recofOper/Makefile | 48 + regression_test/recofOper/TrecofOper.ttcn | 1384 + regression_test/recofOper/TrecofParamRef.ttcn | 689 + regression_test/recofOper/config.cfg | 15 + regression_test/recordOper/.gitignore | 7 + regression_test/recordOper/Makefile | 47 + regression_test/recordOper/TrecordOper.ttcn | 1634 + regression_test/recordOper/config.cfg | 14 + regression_test/setOper/.gitignore | 7 + regression_test/setOper/Makefile | 47 + regression_test/setOper/TsetOper.ttcn | 1185 + regression_test/setOper/config.cfg | 14 + regression_test/setofMatch/.gitignore | 7 + regression_test/setofMatch/Makefile | 47 + regression_test/setofMatch/TsetofMatch.ttcn | 616 + regression_test/setofMatch/config.cfg | 14 + regression_test/setofOper/.gitignore | 7 + regression_test/setofOper/Makefile | 47 + regression_test/setofOper/TsetofOper.ttcn | 1085 + regression_test/setofOper/config.cfg | 14 + regression_test/singlecontrol/.gitignore | 5 + regression_test/singlecontrol/Makefile | 72 + .../singlecontrol/alsohascontrolpart.ttcn | 28 + regression_test/singlecontrol/config.cfg | 14 + regression_test/singlecontrol/config1.cfg | 14 + regression_test/singlecontrol/config2.cfg | 15 + .../singlecontrol/config_noexec.cfg | 11 + .../singlecontrol/hascontrolpart.ttcn | 29 + .../singlecontrol/nocontrolpart.ttcn | 19 + regression_test/singlecontrol/ouch.cfg | 12 + regression_test/slider/.gitignore | 9 + regression_test/slider/Makefile | 153 + regression_test/slider/PT1.cc | 152 + regression_test/slider/PT1.hh | 70 + regression_test/slider/UNDER.cc | 87 + regression_test/slider/UNDER.hh | 59 + regression_test/slider/dual.ttcn | 323 + regression_test/slider/dual2.ttcn | 228 + regression_test/slider/dualnegtest.ttcn | 72 + regression_test/slider/run.cfg | 17 + regression_test/slider/slider.ttcn | 134 + regression_test/templateAnytype/.gitignore | 8 + regression_test/templateAnytype/Makefile | 47 + .../templateAnytype/TtemplateAnytype.ttcn | 179 + regression_test/templateAnytype/config.cfg | 14 + regression_test/templateBitstr/.gitignore | 7 + regression_test/templateBitstr/Makefile | 47 + .../templateBitstr/TtemplateBitstr.ttcn | 328 + regression_test/templateBitstr/config.cfg | 14 + regression_test/templateBool/.gitignore | 7 + regression_test/templateBool/Makefile | 47 + .../templateBool/TtemplateBool.ttcn | 165 + regression_test/templateBool/config.cfg | 14 + regression_test/templateChar/.gitignore | 7 + regression_test/templateChar/Makefile | 47 + .../templateChar/TtemplateChar.ttcn | 248 + regression_test/templateChar/config.cfg | 14 + regression_test/templateCharstr/.gitignore | 7 + regression_test/templateCharstr/Makefile | 47 + .../templateCharstr/TtemplateCharstr.ttcn | 707 + regression_test/templateCharstr/config.cfg | 14 + regression_test/templateEnum/.gitignore | 7 + regression_test/templateEnum/Makefile | 47 + .../templateEnum/TtemplateEnum.ttcn | 165 + regression_test/templateEnum/config.cfg | 14 + regression_test/templateFloat/.gitignore | 7 + regression_test/templateFloat/Makefile | 47 + .../templateFloat/TtemplateFloat.ttcn | 248 + regression_test/templateFloat/config.cfg | 14 + regression_test/templateInt/.gitignore | 7 + regression_test/templateInt/Makefile | 47 + regression_test/templateInt/TtemplateInt.ttcn | 275 + regression_test/templateInt/config.cfg | 14 + regression_test/templateOctetstr/.gitignore | 7 + regression_test/templateOctetstr/Makefile | 47 + .../templateOctetstr/TtemplateOctetstr.ttcn | 326 + regression_test/templateOctetstr/config.cfg | 14 + regression_test/templateRec/.gitignore | 8 + regression_test/templateRec/Makefile | 51 + regression_test/templateRec/TtemplateRec.ttcn | 685 + .../templateRec/TtemplateRecAsn.asn | 17 + regression_test/templateRec/config.cfg | 14 + regression_test/templateRecof/.gitignore | 7 + regression_test/templateRecof/Makefile | 44 + .../templateRecof/TmultiplePermutations.ttcn | 136 + .../templateRecof/TtemplateRecof.ttcn | 660 + regression_test/templateRecof/config.cfg | 16 + regression_test/templateSet/.gitignore | 7 + regression_test/templateSet/Makefile | 47 + regression_test/templateSet/TtemplateSet.ttcn | 176 + regression_test/templateSet/config.cfg | 14 + regression_test/templateSetof/.gitignore | 7 + regression_test/templateSetof/Makefile | 47 + .../templateSetof/TtemplateSetof.ttcn | 431 + regression_test/templateSetof/config.cfg | 14 + regression_test/templateUnion/.gitignore | 7 + regression_test/templateUnion/Makefile | 47 + .../templateUnion/TtemplateUnion.ttcn | 205 + regression_test/templateUnion/config.cfg | 14 + regression_test/testcase_defparam/.gitignore | 6 + regression_test/testcase_defparam/Makefile | 141 + regression_test/testcase_defparam/config.cfg | 32 + .../testcase_defparam/tcdefparam.ttcn | 89 + regression_test/text2ttcn/Makefile | 62 + regression_test/text2ttcn/array_test.ttcn | 1005 + regression_test/text2ttcn/bitstring_test.ttcn | 482 + regression_test/text2ttcn/boolean_test.ttcn | 367 + .../text2ttcn/charstring_test.ttcn | 1405 + regression_test/text2ttcn/component_test.ttcn | 41 + regression_test/text2ttcn/enum_test.ttcn | 234 + regression_test/text2ttcn/float_test.ttcn | 365 + regression_test/text2ttcn/functions.ttcn | 571 + regression_test/text2ttcn/hexstring_test.ttcn | 253 + regression_test/text2ttcn/integer_test.ttcn | 367 + regression_test/text2ttcn/objid_test.ttcn | 33 + .../text2ttcn/octetstring_test.ttcn | 243 + regression_test/text2ttcn/record_test.ttcn | 1266 + regression_test/text2ttcn/recordof_test.ttcn | 768 + regression_test/text2ttcn/set_test.ttcn | 321 + regression_test/text2ttcn/setof_test.ttcn | 310 + regression_test/text2ttcn/text2ttcn_1.cfg | 503 + regression_test/text2ttcn/text2ttcn_2.cfg | 4 + regression_test/text2ttcn/types.ttcn | 250 + .../text2ttcn/ucharstring_test.ttcn | 561 + regression_test/text2ttcn/union_test.ttcn | 293 + regression_test/transparent/.gitignore | 5 + regression_test/transparent/Makefile | 150 + regression_test/transparent/run.cfg | 14 + regression_test/transparent/transparent.ttcn | 38 + regression_test/tryCatch/.gitignore | 9 + regression_test/tryCatch/Makefile | 60 + regression_test/tryCatch/PCOType.cc | 95 + regression_test/tryCatch/PCOType.hh | 46 + regression_test/tryCatch/external_function.cc | 16 + regression_test/tryCatch/tryCatch.cfg | 21 + .../tryCatch/tryCatch_Functions.ttcn | 15 + .../tryCatch/tryCatch_Testcases.ttcn | 728 + regression_test/ttcn2json/General_Types.ttcn | 316 + .../ttcn2json/General_Types_e.json | 770 + regression_test/ttcn2json/Makefile | 57 + regression_test/ttcn2json/PIPEasp_PT.cc | 738 + regression_test/ttcn2json/PIPEasp_PT.hh | 106 + .../ttcn2json/PIPEasp_PortType.ttcn | 46 + .../ttcn2json/PIPEasp_Templates.ttcn | 93 + regression_test/ttcn2json/PIPEasp_Types.ttcn | 180 + regression_test/ttcn2json/Shell.ttcn | 244 + regression_test/ttcn2json/Testcases.ttcn | 64 + regression_test/ttcn2json/one.ttcn | 51 + regression_test/ttcn2json/one_e.json | 827 + regression_test/ttcn2json/three.ttcn | 56 + regression_test/ttcn2json/two.ttcn | 37 + regression_test/ttcn2json/zero.asn | 83 + regression_test/typeCompat/.gitignore | 8 + regression_test/typeCompat/ASN_Ext.asn | 27 + regression_test/typeCompat/Compat.ttcn | 477 + regression_test/typeCompat/Ext.ttcn | 92 + regression_test/typeCompat/Ext2.ttcn | 15 + regression_test/typeCompat/Makefile | 62 + regression_test/typeCompat/Std.ttcn | 217 + regression_test/typeCompat/config.cfg | 14 + regression_test/ucharstrOper/.gitignore | 14 + .../ucharstrOper/Base64Testcases.ttcn | 293 + regression_test/ucharstrOper/Common.ttcn | 245 + regression_test/ucharstrOper/Makefile | 60 + .../ucharstrOper/TucharstrOper.ttcn | 105 + .../ucharstrOper/UTF16Testcases.ttcn | 691 + .../ucharstrOper/UTF32Testcases.ttcn | 576 + .../ucharstrOper/UTF8Testcases.ttcn | 592 + regression_test/ucharstrOper/config.cfg | 26 + .../ucharstrOper/cstr_content.ttcn | 383 + regression_test/ucharstrOper/external.cc | 260 + regression_test/unionOper/.gitignore | 7 + regression_test/unionOper/Makefile | 47 + regression_test/unionOper/TunionOper.ttcn | 1066 + regression_test/unionOper/config.cfg | 14 + regression_test/vcheck.pl | 59 + regression_test/verdictOper/.gitignore | 7 + regression_test/verdictOper/Makefile | 51 + regression_test/verdictOper/TverdictOper.ttcn | 341 + regression_test/verdictOper/config.cfg | 18 + regression_test/visibility/.gitignore | 9 + regression_test/visibility/Makefile | 49 + regression_test/visibility/Visibility.ttcn | 28 + regression_test/visibility/config.cfg | 14 + regression_test/visibility/module1.ttcn | 85 + regression_test/visibility/module2.ttcn | 34 + regression_test/visibility/module3.ttcn | 20 + regression_test/visibility/module4.ttcn | 41 + repgen/.gitignore | 12 + repgen/Makefile | 80 + repgen/logfilter.c | 369 + repgen/logformat.l | 483 + repgen/logmerge.c | 703 + repgen/parser.l | 316 + repgen/repgen.c | 716 + repgen/repgen.h | 27 + repgen/ttcn3_logfilter.1 | 89 + repgen/ttcn3_logformat.1 | 113 + repgen/ttcn3_logmerge.1 | 73 + titan_executor_api/.gitignore | 10 + .../TITAN_Executor_API/.classpath | 6 + .../TITAN_Executor_API/.gitignore | 7 + .../TITAN_Executor_API/.project | 17 + .../TITAN_Executor_API/build.xml | 54 + .../javadoc-overview/javadoc-overview.html | 26 + .../uml/TITAN_Executor_API_class_diagram.png | Bin 0 -> 152597 bytes .../uml/TITAN_Executor_API_class_diagram.uxf | 722 + .../TITAN_Executor_API_sequence_diagram.uxf | 4957 ++ .../uml/TITAN_Executor_API_state_diagram.uxf | 598 + ...ITAN_Executor_API_state_diagram_simple.png | Bin 0 -> 24970 bytes ...ITAN_Executor_API_state_diagram_simple.uxf | 295 + .../TITAN_Executor_API_test_class_diagram.uxf | 552 + .../TITAN_Executor_API/javadoc.xml | 6 + .../TITAN_Executor_API/nb-build.xml | 73 + .../nbproject/build-impl.xml | 1422 + .../nbproject/genfiles.properties | 8 + .../nbproject/project.properties | 78 + .../TITAN_Executor_API/nbproject/project.xml | 14 + .../TITAN_Executor_API/readme.txt | 32 + .../titan/executor/jni/ComponentStruct.java | 97 + .../titan/executor/jni/HcStateEnum.java | 35 + .../titan/executor/jni/HostStruct.java | 106 + .../titan/executor/jni/IJNICallback.java | 45 + .../titan/executor/jni/JNIMiddleWare.java | 691 + .../titan/executor/jni/McStateEnum.java | 33 + .../titan/executor/jni/QualifiedName.java | 28 + .../titan/executor/jni/TcStateEnum.java | 58 + .../eclipse/titan/executor/jni/Timeval.java | 83 + .../titan/executor/jni/TransportTypeEnum.java | 31 + .../titan/executor/jni/VerdictTypeEnum.java | 42 + .../titan/executorapi/HostController.java | 143 + .../executorapi/IJniExecutorObserver.java | 59 + .../titan/executorapi/JniExecutor.java | 1377 + .../exception/JniExecutorException.java | 32 + .../JniExecutorIllegalArgumentException.java | 27 + .../JniExecutorJniLoadException.java | 39 + .../JniExecutorStartSessionException.java | 27 + .../JniExecutorWrongStateException.java | 27 + .../titan/executorapi/package-info.java | 11 + .../eclipse/titan/executorapi/util/Log.java | 361 + .../titan/executorapi/util/StringUtil.java | 162 + .../TITAN_Executor_API_Demo/.classpath | 7 + .../TITAN_Executor_API_Demo/.gitignore | 3 + .../TITAN_Executor_API_Demo/.project | 17 + .../TITAN_Executor_API_Demo/build.xml | 69 + .../TITAN_Executor_API_Demo/manifest.mf | 3 + .../TITAN_Executor_API_Demo/nb-build.xml | 73 + .../nbproject/build-impl.xml | 1436 + .../nbproject/genfiles.properties | 8 + .../nbproject/project.properties | 83 + .../nbproject/project.xml | 24 + .../titan/executorapi/demo/CommonData.java | 42 + .../titan/executorapi/demo/DemoFrame.java | 1021 + .../executorapi/demo/ExecuteCfgDialog.java | 95 + .../demo/ExecuteControlDialog.java | 86 + .../demo/ExecuteTestcaseDialog.java | 92 + .../eclipse/titan/executorapi/demo/Main.java | 16 + .../TITAN_Executor_API_test/.classpath | 8 + .../TITAN_Executor_API_test/.gitignore | 4 + .../TITAN_Executor_API_test/.project | 18 + .../TITAN_Executor_API_test/build.xml | 147 + .../TITAN_Executor_API_test/nb-build.xml | 73 + .../nbproject/build-impl.xml | 1436 + .../nbproject/genfiles.properties | 8 + .../nbproject/project.properties | 83 + .../nbproject/project.xml | 24 + .../TITAN_Executor_API_test/readme.txt | 20 + .../HostControllerErrorIllegalArgTest.java | 81 + .../JniExecutorAsyncErrorIllegalArgTest.java | 263 + .../test/JniExecutorAsyncErrorTest.java | 335 + .../JniExecutorAsyncErrorWrongStateTest.java | 979 + .../test/JniExecutorAsyncHappySimpleTest.java | 91 + .../test/JniExecutorAsyncHappyTest.java | 169 + .../test/JniExecutorAsyncTest.java | 79 + .../executorapi/test/JniExecutorSync.java | 277 + .../executorapi/test/JniExecutorSyncTest.java | 223 + .../executorapi/test/JniExecutorTest.java | 22 + .../executorapi/test/NormalTestObserver.java | 110 + .../executorapi/test/StringUtilTest.java | 50 + .../titan/executorapi/test/Test1Observer.java | 61 + .../titan/executorapi/test/Test2Observer.java | 61 + .../titan/executorapi/test/TestConstants.java | 55 + .../executorapi/test/TestObserverBase.java | 159 + .../titan/executorapi/test/TestUtil.java | 33 + .../doc/Titan_Executor_API_User_Guide.doc | Bin 0 -> 64512 bytes usrguide/.gitignore | 15 + usrguide/Makefile | 47 + usrguide/apiguide.doc | Bin 0 -> 566784 bytes usrguide/installationguide.doc | Bin 0 -> 117760 bytes usrguide/pdfgen.sh | 10 + usrguide/referenceguide.doc | Bin 0 -> 1503744 bytes usrguide/releasenotes.doc | Bin 0 -> 564736 bytes usrguide/userguide.doc | Bin 0 -> 850432 bytes xsdconvert/.gitignore | 3 + xsdconvert/Annotation.cc | 41 + xsdconvert/Annotation.hh | 43 + xsdconvert/ComplexType.cc | 1288 + xsdconvert/ComplexType.hh | 176 + xsdconvert/FieldType.cc | 587 + xsdconvert/FieldType.hh | 98 + xsdconvert/GeneralFunctions.cc | 642 + xsdconvert/GeneralFunctions.hh | 69 + xsdconvert/GeneralTypes.hh | 92 + xsdconvert/ImportStatement.cc | 162 + xsdconvert/ImportStatement.hh | 54 + xsdconvert/List.hh | 369 + xsdconvert/Makefile | 81 + xsdconvert/Mstring.cc | 381 + xsdconvert/Mstring.hh | 240 + xsdconvert/PredefinedModules.cc | 417 + xsdconvert/RootType.cc | 220 + xsdconvert/RootType.hh | 174 + xsdconvert/SimpleType.cc | 1305 + xsdconvert/SimpleType.hh | 249 + xsdconvert/TTCN3Module.cc | 438 + xsdconvert/TTCN3Module.hh | 135 + xsdconvert/TTCN3ModuleInventory.cc | 364 + xsdconvert/TTCN3ModuleInventory.hh | 103 + xsdconvert/XMLParser.cc | 761 + xsdconvert/XMLParser.hh | 294 + xsdconvert/converter.cc | 411 + 2700 files changed, 879407 insertions(+) create mode 100644 .gitignore create mode 100644 JNI/.gitignore create mode 100644 JNI/Makefile create mode 100644 JNI/jnimw.cc create mode 100644 JNI/jnimw.h create mode 100644 JNI/jninativelib.cc create mode 100644 JNI/org_eclipse_titan_executor_jni_JNIMiddleWare.h create mode 100644 Makefile create mode 100644 Makefile.cfg create mode 100644 Makefile.genrules create mode 100644 README.cygwin create mode 100644 README.linux create mode 100644 common/.gitignore create mode 100644 common/CharCoding.hh create mode 100644 common/JSON_Tokenizer.cc create mode 100644 common/JSON_Tokenizer.hh create mode 100644 common/Makefile create mode 100644 common/ModuleVersion.cc create mode 100644 common/ModuleVersion.hh create mode 100644 common/NetworkHandler.cc create mode 100644 common/NetworkHandler.hh create mode 100644 common/Path2.cc create mode 100644 common/Path2.hh create mode 100644 common/Quadruple.cc create mode 100644 common/Quadruple.hh create mode 100644 common/cfg_process_utils.hh create mode 100644 common/config_preproc.cc create mode 100644 common/config_preproc.h create mode 100644 common/config_preproc_la.l create mode 100644 common/config_preproc_p.y create mode 100644 common/dbgnew.hh create mode 100644 common/hostid.c create mode 100644 common/license.c create mode 100644 common/license.h create mode 100644 common/memory.c create mode 100644 common/memory.h create mode 100644 common/new.cc create mode 100644 common/path.c create mode 100644 common/path.h create mode 100644 common/pattern.hh create mode 100644 common/pattern_la.l create mode 100644 common/pattern_p.y create mode 100644 common/pattern_uni.y create mode 100644 common/platform.h create mode 100644 common/static_check.h create mode 100644 common/ttcn3float.hh create mode 100644 common/usage_stats.cc create mode 100644 common/usage_stats.hh create mode 100644 common/userinfo.c create mode 100644 common/userinfo.h create mode 100644 common/version.h create mode 100644 common/version.py create mode 100644 common/version_internal.h create mode 100644 compiler2/.gitignore create mode 100644 compiler2/AST.cc create mode 100644 compiler2/AST.hh create mode 100644 compiler2/Code.cc create mode 100644 compiler2/Code.hh create mode 100644 compiler2/CodeGenHelper.cc create mode 100644 compiler2/CodeGenHelper.hh create mode 100644 compiler2/CompField.cc create mode 100644 compiler2/CompField.hh create mode 100644 compiler2/CompType.cc create mode 100644 compiler2/CompType.hh create mode 100644 compiler2/CompilerError.cc create mode 100644 compiler2/CompilerError.hh create mode 100644 compiler2/Constraint.cc create mode 100644 compiler2/Constraint.hh create mode 100644 compiler2/EnumItem.cc create mode 100644 compiler2/EnumItem.hh create mode 100644 compiler2/Identifier.cc create mode 100644 compiler2/Identifier.hh create mode 100644 compiler2/Int.cc create mode 100644 compiler2/Int.hh create mode 100644 compiler2/Makefile create mode 100644 compiler2/PredefFunc.cc create mode 100644 compiler2/PredefFunc.hh create mode 100644 compiler2/Real.cc create mode 100644 compiler2/Real.hh create mode 100644 compiler2/Setting.cc create mode 100644 compiler2/Setting.hh create mode 100644 compiler2/SigParam.cc create mode 100644 compiler2/SigParam.hh create mode 100644 compiler2/Stopwatch.cc create mode 100644 compiler2/Stopwatch.hh create mode 100644 compiler2/Type.cc create mode 100644 compiler2/Type.hh create mode 100644 compiler2/TypeCompat.cc create mode 100644 compiler2/TypeCompat.hh create mode 100644 compiler2/Type_chk.cc create mode 100644 compiler2/Type_codegen.cc create mode 100644 compiler2/Typestuff.cc create mode 100644 compiler2/Typestuff.hh create mode 100644 compiler2/Value.cc create mode 100644 compiler2/Value.hh create mode 100644 compiler2/Valuestuff.cc create mode 100644 compiler2/Valuestuff.hh create mode 100644 compiler2/XerAttributes.cc create mode 100644 compiler2/XerAttributes.hh create mode 100644 compiler2/asn1/.gitignore create mode 100644 compiler2/asn1/AST_asn1.cc create mode 100644 compiler2/asn1/AST_asn1.hh create mode 100644 compiler2/asn1/Block.cc create mode 100644 compiler2/asn1/Block.hh create mode 100644 compiler2/asn1/Makefile create mode 100644 compiler2/asn1/OCSV.cc create mode 100644 compiler2/asn1/OCSV.hh create mode 100644 compiler2/asn1/Object.cc create mode 100644 compiler2/asn1/Object.hh create mode 100644 compiler2/asn1/Object0.hh create mode 100644 compiler2/asn1/Ref.cc create mode 100644 compiler2/asn1/Ref.hh create mode 100644 compiler2/asn1/TableConstraint.cc create mode 100644 compiler2/asn1/TableConstraint.hh create mode 100644 compiler2/asn1/Tag.cc create mode 100644 compiler2/asn1/Tag.hh create mode 100644 compiler2/asn1/TokenBuf.cc create mode 100644 compiler2/asn1/TokenBuf.hh create mode 100644 compiler2/asn1/Type_parse.cc create mode 100644 compiler2/asn1/asn1.hh create mode 100644 compiler2/asn1/asn1_preparser.h create mode 100644 compiler2/asn1/asn1_preparser.l create mode 100644 compiler2/asn1/asn1la.l create mode 100644 compiler2/asn1/asn1p.y create mode 100644 compiler2/asn1/asn1p_old.h create mode 100644 compiler2/compiler.1 create mode 100644 compiler2/datatypes.h create mode 100644 compiler2/encdec.c create mode 100644 compiler2/encdec.h create mode 100644 compiler2/enum.c create mode 100644 compiler2/enum.h create mode 100644 compiler2/error.h create mode 100644 compiler2/functionref.c create mode 100644 compiler2/functionref.h create mode 100644 compiler2/main.cc create mode 100644 compiler2/main.hh create mode 100644 compiler2/makefile.c create mode 100644 compiler2/map.hh create mode 100644 compiler2/record.c create mode 100644 compiler2/record.h create mode 100644 compiler2/record_of.c create mode 100644 compiler2/record_of.h create mode 100644 compiler2/stack.hh create mode 100644 compiler2/string.cc create mode 100644 compiler2/string.hh create mode 100644 compiler2/subtype.cc create mode 100644 compiler2/subtype.hh create mode 100644 compiler2/subtypestuff.cc create mode 100644 compiler2/subtypestuff.hh create mode 100644 compiler2/tcov.xsd create mode 100644 compiler2/tcov.xsl create mode 100644 compiler2/tcov2lcov.cc create mode 100644 compiler2/tcov2lcov.hh create mode 100644 compiler2/titanver create mode 100644 compiler2/ttcn3/.gitignore create mode 100644 compiler2/ttcn3/AST_ttcn3.cc create mode 100644 compiler2/ttcn3/AST_ttcn3.hh create mode 100644 compiler2/ttcn3/ArrayDimensions.cc create mode 100644 compiler2/ttcn3/ArrayDimensions.hh create mode 100644 compiler2/ttcn3/Attributes.cc create mode 100644 compiler2/ttcn3/Attributes.hh create mode 100644 compiler2/ttcn3/BerAST.cc create mode 100644 compiler2/ttcn3/BerAST.hh create mode 100644 compiler2/ttcn3/ILT.cc create mode 100644 compiler2/ttcn3/ILT.hh create mode 100644 compiler2/ttcn3/JsonAST.cc create mode 100644 compiler2/ttcn3/JsonAST.hh create mode 100644 compiler2/ttcn3/Makefile create mode 100644 compiler2/ttcn3/PatternString.cc create mode 100644 compiler2/ttcn3/PatternString.hh create mode 100644 compiler2/ttcn3/RawAST.cc create mode 100644 compiler2/ttcn3/RawAST.hh create mode 100644 compiler2/ttcn3/Statement.cc create mode 100644 compiler2/ttcn3/Statement.hh create mode 100644 compiler2/ttcn3/Templatestuff.cc create mode 100644 compiler2/ttcn3/Templatestuff.hh create mode 100644 compiler2/ttcn3/TextAST.cc create mode 100644 compiler2/ttcn3/TextAST.hh create mode 100644 compiler2/ttcn3/Ttcn2Json.cc create mode 100644 compiler2/ttcn3/Ttcn2Json.hh create mode 100644 compiler2/ttcn3/TtcnTemplate.cc create mode 100644 compiler2/ttcn3/TtcnTemplate.hh create mode 100644 compiler2/ttcn3/Ttcnstuff.cc create mode 100644 compiler2/ttcn3/Ttcnstuff.hh create mode 100644 compiler2/ttcn3/charstring_la.l create mode 100644 compiler2/ttcn3/coding_attrib_la.l create mode 100644 compiler2/ttcn3/coding_attrib_p.y create mode 100644 compiler2/ttcn3/compiler.c create mode 100644 compiler2/ttcn3/compiler.h create mode 100644 compiler2/ttcn3/compiler.l create mode 100644 compiler2/ttcn3/compiler.y create mode 100644 compiler2/ttcn3/comptype_attrib_la.l create mode 100644 compiler2/ttcn3/port.c create mode 100644 compiler2/ttcn3/port.h create mode 100644 compiler2/ttcn3/pstring_la.l create mode 100644 compiler2/ttcn3/rawAST.l create mode 100644 compiler2/ttcn3/rawAST.y create mode 100644 compiler2/ttcn3/rawASTspec.h create mode 100644 compiler2/ttcn3/signature.c create mode 100644 compiler2/ttcn3/signature.h create mode 100644 compiler2/ttcn3/ttcn3_preparser.h create mode 100644 compiler2/ttcn3/ttcn3_preparser.l create mode 100644 compiler2/ttcn3_makefilegen.1 create mode 100644 compiler2/union.c create mode 100644 compiler2/union.h create mode 100644 compiler2/ustring.cc create mode 100644 compiler2/ustring.hh create mode 100644 compiler2/vector.hh create mode 100644 compiler2/xpather.cc create mode 100644 compiler2/xpather.h create mode 100644 core/.gitignore create mode 100644 core/ASN_Any.cc create mode 100644 core/ASN_Any.hh create mode 100644 core/ASN_CharacterString.cc create mode 100644 core/ASN_CharacterString.hh create mode 100644 core/ASN_EmbeddedPDV.cc create mode 100644 core/ASN_EmbeddedPDV.hh create mode 100644 core/ASN_External.cc create mode 100644 core/ASN_External.hh create mode 100644 core/ASN_Null.cc create mode 100644 core/ASN_Null.hh create mode 100644 core/Addfunc.cc create mode 100644 core/Addfunc.hh create mode 100644 core/Array.cc create mode 100644 core/Array.hh create mode 100644 core/BER.cc create mode 100644 core/BER.hh create mode 100644 core/Basetype.cc create mode 100644 core/Basetype.hh create mode 100644 core/Bitstring.cc create mode 100644 core/Bitstring.hh create mode 100644 core/Boolean.cc create mode 100644 core/Boolean.hh create mode 100644 core/Charstring.cc create mode 100644 core/Charstring.hh create mode 100644 core/Communication.cc create mode 100644 core/Communication.hh create mode 100644 core/Component.cc create mode 100644 core/Component.hh create mode 100644 core/Default.cc create mode 100644 core/Default.hh create mode 100644 core/Encdec.cc create mode 100644 core/Encdec.hh create mode 100644 core/Error.cc create mode 100644 core/Error.hh create mode 100644 core/Event_Handler.hh create mode 100644 core/Fd_And_Timeout_User.hh create mode 100644 core/Float.cc create mode 100644 core/Float.hh create mode 100644 core/Hexstring.cc create mode 100644 core/Hexstring.hh create mode 100644 core/ILoggerPlugin.hh create mode 100644 core/Integer.cc create mode 100644 core/Integer.hh create mode 100644 core/JSON.cc create mode 100644 core/JSON.hh create mode 100644 core/LegacyLogger.cc create mode 100644 core/LegacyLogger.hh create mode 100644 core/Logger.cc create mode 100644 core/Logger.hh create mode 100644 core/LoggerPlugin.cc create mode 100644 core/LoggerPlugin.hh create mode 100644 core/LoggerPluginManager.cc create mode 100644 core/LoggerPluginManager.hh create mode 100644 core/LoggerPlugin_dynamic.cc create mode 100644 core/LoggerPlugin_static.cc create mode 100644 core/LoggingBits.cc create mode 100644 core/LoggingBits.hh create mode 100644 core/LoggingParam.hh create mode 100644 core/Makefile create mode 100644 core/Message_types.hh create mode 100644 core/Module_list.cc create mode 100644 core/Module_list.hh create mode 100644 core/Objid.cc create mode 100644 core/Objid.hh create mode 100644 core/Octetstring.cc create mode 100644 core/Octetstring.hh create mode 100644 core/Optional.hh create mode 100644 core/Parallel_main.cc create mode 100644 core/Param_Types.cc create mode 100644 core/Param_Types.hh create mode 100644 core/Parameters.h create mode 100644 core/Port.cc create mode 100644 core/Port.hh create mode 100644 core/RAW.cc create mode 100644 core/RAW.hh create mode 100644 core/RInt.cc create mode 100644 core/RInt.hh create mode 100644 core/Runtime.cc create mode 100644 core/Runtime.hh create mode 100644 core/Single_main.cc create mode 100644 core/Snapshot.cc create mode 100644 core/Snapshot.hh create mode 100644 core/String_struct.hh create mode 100644 core/Struct_of.cc create mode 100644 core/Struct_of.hh create mode 100644 core/TCov.cc create mode 100644 core/TCov.hh create mode 100644 core/TEXT.cc create mode 100644 core/TEXT.hh create mode 100644 core/TTCN3.hh create mode 100644 core/Template.cc create mode 100644 core/Template.hh create mode 100644 core/Textbuf.cc create mode 100644 core/Textbuf.hh create mode 100644 core/Timer.cc create mode 100644 core/Timer.hh create mode 100644 core/TitanLoggerApi.xsd create mode 100644 core/TitanLoggerControl.ttcn create mode 100644 core/TitanLoggerControlImpl.cc create mode 100644 core/Types.h create mode 100644 core/Universal_charstring.cc create mode 100644 core/Universal_charstring.hh create mode 100644 core/VIRAG.asn create mode 100644 core/Vector.hh create mode 100644 core/Verdicttype.cc create mode 100644 core/Verdicttype.hh create mode 100644 core/XER.cc create mode 100644 core/XER.hh create mode 100644 core/XmlReader.cc create mode 100644 core/XmlReader.hh create mode 100644 core/config_process.l create mode 100644 core/config_process.y create mode 100644 core/gccversion.c create mode 100644 core/license_gen.c create mode 100644 core/simplify.pl create mode 100644 core2/.gitignore create mode 100644 core2/Basetype2.cc create mode 100644 core2/Makefile create mode 100644 doc/License_handling_in_TITAN.doc create mode 100644 doc/asn1parser/asn1_jackson.vsd create mode 100644 doc/asn1parser/asn1p.vsd create mode 100644 doc/parallelarch/.gitignore create mode 100644 doc/parallelarch/Makefile create mode 100644 doc/parallelarch/connect_op.eps create mode 100644 doc/parallelarch/connect_op.msc create mode 100644 doc/parallelarch/connect_op_local.eps create mode 100644 doc/parallelarch/connect_op_local.msc create mode 100644 doc/parallelarch/create_op.eps create mode 100644 doc/parallelarch/create_op.msc create mode 100644 doc/parallelarch/creating_MTC.eps create mode 100644 doc/parallelarch/creating_MTC.msc create mode 100644 doc/parallelarch/disconnect_op.eps create mode 100644 doc/parallelarch/disconnect_op.msc create mode 100644 doc/parallelarch/disconnect_op_local.eps create mode 100644 doc/parallelarch/disconnect_op_local.msc create mode 100644 doc/parallelarch/done_op.eps create mode 100644 doc/parallelarch/done_op.msc create mode 100644 doc/parallelarch/erilogo_black_on_white.eps create mode 100644 doc/parallelarch/eripage.sty create mode 100644 doc/parallelarch/executing_control.eps create mode 100644 doc/parallelarch/executing_control.msc create mode 100644 doc/parallelarch/executing_testcase.eps create mode 100644 doc/parallelarch/executing_testcase.msc create mode 100644 doc/parallelarch/killing_TC.eps create mode 100644 doc/parallelarch/killing_TC.msc create mode 100644 doc/parallelarch/log.eps create mode 100644 doc/parallelarch/log.msc create mode 100644 doc/parallelarch/map_op.eps create mode 100644 doc/parallelarch/map_op.msc create mode 100644 doc/parallelarch/parallel.tex create mode 100644 doc/parallelarch/parallel_ttcn3.sdt create mode 100644 doc/parallelarch/parallelarch.eps create mode 100644 doc/parallelarch/parallelarch.fig create mode 100644 doc/parallelarch/running_op.eps create mode 100644 doc/parallelarch/running_op.msc create mode 100644 doc/parallelarch/send_to_op.eps create mode 100644 doc/parallelarch/start_op.eps create mode 100644 doc/parallelarch/start_op.msc create mode 100644 doc/parallelarch/starting_HC.eps create mode 100644 doc/parallelarch/starting_HC.msc create mode 100644 doc/parallelarch/state_mach_conn_endpoint.dot create mode 100644 doc/parallelarch/state_mach_conn_endpoint.eps create mode 100644 doc/parallelarch/state_mach_conn_mc.dot create mode 100644 doc/parallelarch/state_mach_conn_mc.eps create mode 100644 doc/parallelarch/state_mach_hc.eps create mode 100644 doc/parallelarch/state_mach_hc.fig create mode 100644 doc/parallelarch/state_mach_hc_mc.dot create mode 100644 doc/parallelarch/state_mach_hc_mc.eps create mode 100644 doc/parallelarch/state_mach_mapping_mc.dot create mode 100644 doc/parallelarch/state_mach_mapping_mc.eps create mode 100644 doc/parallelarch/state_mach_mc.dot create mode 100644 doc/parallelarch/state_mach_mc.eps create mode 100644 doc/parallelarch/state_mach_mtc.eps create mode 100644 doc/parallelarch/state_mach_mtc.fig create mode 100644 doc/parallelarch/state_mach_ptc_mc.dot create mode 100644 doc/parallelarch/state_mach_ptc_mc.eps create mode 100644 doc/parallelarch/stop_op.eps create mode 100644 doc/parallelarch/stop_op.msc create mode 100644 doc/parallelarch/stop_op1.eps create mode 100644 doc/parallelarch/unmap_op.eps create mode 100644 doc/parallelarch/unmap_op.msc create mode 100644 doc/pri/PRI_1_10_A.doc create mode 100644 doc/pri/PRI_1_9_B.doc create mode 100644 doc/pri/PRI_2_1_A.doc create mode 100644 doc/pri/PRI_2_2_A.doc create mode 100644 doc/pri/PRI_3_1_A.doc create mode 100644 doc/pri/PRI_3_2_A.doc create mode 100755 doc/pri/PRI_4_1_A.doc create mode 100755 doc/pri/PRI_4_2_A.doc create mode 100755 doc/pri/PRI_5_1_A.doc create mode 100644 doc/pri/PRI_8_G.doc create mode 100644 doc/pri/PRI_8_H.doc create mode 100644 etc/Makefile create mode 100644 etc/TXDSample.xml create mode 100644 etc/autotest/.titan_builder-esekilxxen1843 create mode 100644 etc/autotest/.titan_builder-esekits1064 create mode 100644 etc/autotest/.titan_builder-esekits3013 create mode 100644 etc/autotest/.titan_builder-esekits5013 create mode 100644 etc/autotest/.titan_builder-rhea create mode 100644 etc/autotest/.titan_builder-tcclab1 create mode 100644 etc/autotest/README create mode 100755 etc/autotest/freshbuild.sh create mode 100755 etc/autotest/mountall.sh create mode 100755 etc/autotest/product_handler.py create mode 100755 etc/autotest/titan_builder.py create mode 100755 etc/autotest/titan_builder.sh create mode 100755 etc/autotest/titan_builder_cfg.py create mode 100755 etc/autotest/titan_publisher.py create mode 100644 etc/autotest/web/titan_builder.css create mode 100644 etc/autotest/web/titan_builder.php create mode 100644 etc/download_stats/README create mode 100755 etc/download_stats/addDownloadStats.sh create mode 100644 etc/download_stats/addDownloadStats.xsl create mode 100644 etc/download_stats/eclipsestats-old.php create mode 100644 etc/download_stats/eclipsestats.php create mode 100755 etc/howto/pqb_stats_howto.txt create mode 100755 etc/howto/titan_release_howto.txt create mode 100644 etc/scripts/cfg_msg_maker.py create mode 100644 etc/scripts/stacklogger.pl create mode 100644 etc/scripts/tpd_graph_xml2dot.py create mode 100644 etc/skeleton/altstep.skeleton create mode 100644 etc/skeleton/asn1_module.skeleton create mode 100644 etc/skeleton/component_type.skeleton create mode 100644 etc/skeleton/constant.skeleton create mode 100644 etc/skeleton/control_part.skeleton create mode 100644 etc/skeleton/data_type.skeleton create mode 100644 etc/skeleton/function.skeleton create mode 100644 etc/skeleton/import_part.skeleton create mode 100644 etc/skeleton/module_param.skeleton create mode 100644 etc/skeleton/port_type.skeleton create mode 100644 etc/skeleton/signature.skeleton create mode 100644 etc/skeleton/template.skeleton create mode 100644 etc/skeleton/testcase.skeleton create mode 100644 etc/skeleton/ttcn3_module.skeleton create mode 100644 etc/solaris/README create mode 100755 etc/solaris/build.sh create mode 100755 etc/solaris/get.sh create mode 100755 etc/solaris/path.sh create mode 100755 etc/solaris/titan.sh create mode 100644 etc/xsd/Junit.xsd create mode 100644 etc/xsd/TPD.xsd create mode 100644 etc/xsd/TXD.xsd create mode 100644 function_test/BER_EncDec/.gitignore create mode 100644 function_test/BER_EncDec/BER_EncDec_TD.fast_script create mode 100644 function_test/BER_EncDec/BER_EncDec_TD.script create mode 100644 function_test/BER_EncDec/Makefile create mode 100644 function_test/BER_EncDec/Temp.cfg create mode 100755 function_test/BER_EncDec/run_test create mode 100644 function_test/Config_Parser/.gitignore create mode 100755 function_test/Config_Parser/Logging_1_TD.script create mode 100644 function_test/Config_Parser/OrderedInclude.script create mode 100644 function_test/Config_Parser/PreprocessingCfgFiles_TD.script create mode 100755 function_test/Config_Parser/begin_script.sh create mode 100755 function_test/Config_Parser/end_script.sh create mode 100755 function_test/Config_Parser/extfunc.cc create mode 100755 function_test/Config_Parser/run_test create mode 100755 function_test/Config_Parser/run_test_all create mode 100644 function_test/Makefile create mode 100644 function_test/RAW_EncDec/.gitignore create mode 100644 function_test/RAW_EncDec/Makefile create mode 100644 function_test/RAW_EncDec/RAW_EncDec_TD.fast_script create mode 100644 function_test/RAW_EncDec/RAW_EncDec_TD.script create mode 100644 function_test/RAW_EncDec/Temp.cfg create mode 100755 function_test/RAW_EncDec/run_test create mode 100755 function_test/README.txt create mode 100644 function_test/Semantic_Analyser/.gitignore create mode 100644 function_test/Semantic_Analyser/ASN_SA_1_TD.script create mode 100644 function_test/Semantic_Analyser/ASN_SA_asn1adhoc_TD.script create mode 100644 function_test/Semantic_Analyser/Makefile.semantic create mode 100644 function_test/Semantic_Analyser/SA_6_TD.script create mode 100644 function_test/Semantic_Analyser/TTCN3_SA_10_TD.script create mode 100644 function_test/Semantic_Analyser/TTCN3_SA_11_TD.script create mode 100644 function_test/Semantic_Analyser/TTCN3_SA_12_TD.script_not_running create mode 100644 function_test/Semantic_Analyser/TTCN3_SA_13_TD.script create mode 100644 function_test/Semantic_Analyser/TTCN3_SA_1_TD.script create mode 100644 function_test/Semantic_Analyser/TTCN3_SA_3_TD.script create mode 100644 function_test/Semantic_Analyser/TTCN3_SA_4_TD.script create mode 100644 function_test/Semantic_Analyser/TTCN3_SA_5_TD.script create mode 100644 function_test/Semantic_Analyser/TTCN3_SA_6_TD.script create mode 100644 function_test/Semantic_Analyser/TTCN3_SA_7_TD.script create mode 100644 function_test/Semantic_Analyser/TTCN3_SA_9_TD.script create mode 100644 function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script create mode 100644 function_test/Semantic_Analyser/common.mk create mode 100755 function_test/Semantic_Analyser/cw.pl create mode 100755 function_test/Semantic_Analyser/defpars/t create mode 100755 function_test/Semantic_Analyser/encode/t create mode 100755 function_test/Semantic_Analyser/float/run_test_all create mode 100755 function_test/Semantic_Analyser/float/t create mode 100755 function_test/Semantic_Analyser/harness.pl create mode 100755 function_test/Semantic_Analyser/import_of_iports/run_test_all create mode 100755 function_test/Semantic_Analyser/import_of_iports/t create mode 100644 function_test/Semantic_Analyser/options/.gitignore create mode 100755 function_test/Semantic_Analyser/options/run_test_all create mode 100755 function_test/Semantic_Analyser/param/t create mode 100755 function_test/Semantic_Analyser/run_test create mode 100755 function_test/Semantic_Analyser/run_test_all create mode 100755 function_test/Semantic_Analyser/ver/.gitignore create mode 100755 function_test/Semantic_Analyser/ver/run_test_all create mode 100755 function_test/Semantic_Analyser/ver/t create mode 100755 function_test/Semantic_Analyser/xer/.gitignore create mode 100755 function_test/Semantic_Analyser/xer/run_test_all create mode 100755 function_test/Semantic_Analyser/xer/t create mode 100644 function_test/Text_EncDec/.gitignore create mode 100644 function_test/Text_EncDec/Makefile create mode 100644 function_test/Text_EncDec/TEXT_1_TD.fast_script create mode 100644 function_test/Text_EncDec/TEXT_1_TD.script create mode 100644 function_test/Text_EncDec/Temp.cfg create mode 100755 function_test/Text_EncDec/run_test create mode 100755 function_test/Tools/SAtester create mode 100755 function_test/Tools/SAtester.pl create mode 100644 function_test/XER_EncDec/Makefile create mode 100644 function_test/XER_EncDec/Temp.cfg create mode 100644 function_test/XER_EncDec/XER_EncDec_TD.script create mode 100755 function_test/XER_EncDec/run_test create mode 100644 function_test/doc/TTCN3_Executor_TestReport.doc create mode 100644 hello/Makefile create mode 100644 hello/MyExample.cfg create mode 100644 hello/MyExample.ttcn create mode 100644 hello/PCOType.cc create mode 100644 hello/PCOType.hh create mode 100644 help/.gitignore create mode 100644 help/Makefile create mode 100755 help/chm_refact.sh create mode 100755 help/docs/TTCN-3_Naming_convention.doc create mode 100644 help/images/ao.jpg create mode 100644 help/images/left.jpg create mode 100644 help/images/right.jpg create mode 100755 help/images/titan.gif create mode 100644 help/images/titan_511x511.png create mode 100755 help/images/titan_icon.gif create mode 100755 help/images/titan_icon_transparent.gif create mode 100644 help/images/titan_old.gif create mode 100644 help/images/titan_selected.gif create mode 100755 help/images/titan_text.gif create mode 100755 help/images/titan_text_transparent.gif create mode 100755 help/images/titan_transparent.gif create mode 100644 help/images/up.jpg create mode 100644 help/info/BNF.html create mode 100644 help/info/action.html create mode 100644 help/info/activate.html create mode 100644 help/info/address.html create mode 100644 help/info/alive.html create mode 100644 help/info/all.html create mode 100644 help/info/alt.html create mode 100644 help/info/altstep.html create mode 100644 help/info/and.html create mode 100644 help/info/and4b.html create mode 100644 help/info/any.html create mode 100644 help/info/anytype.html create mode 100644 help/info/bit2hex.html create mode 100644 help/info/bit2int.html create mode 100644 help/info/bit2oct.html create mode 100644 help/info/bit2str.html create mode 100644 help/info/bitstring.html create mode 100644 help/info/boolean.html create mode 100644 help/info/break.html create mode 100644 help/info/call.html create mode 100644 help/info/case.html create mode 100644 help/info/catch.html create mode 100644 help/info/char.html create mode 100644 help/info/char2int.html create mode 100644 help/info/char2oct.html create mode 100644 help/info/charstring.html create mode 100644 help/info/check.html create mode 100644 help/info/clear.html create mode 100644 help/info/complement.html create mode 100644 help/info/component.html create mode 100644 help/info/connect.html create mode 100644 help/info/const.html create mode 100644 help/info/continue.html create mode 100644 help/info/control.html create mode 100644 help/info/create.html create mode 100644 help/info/deactivate.html create mode 100644 help/info/decode_base64.html create mode 100644 help/info/decvalue.html create mode 100644 help/info/default.html create mode 100644 help/info/disconnect.html create mode 100644 help/info/display.html create mode 100644 help/info/do.html create mode 100644 help/info/done.html create mode 100644 help/info/else.html create mode 100644 help/info/encode.html create mode 100644 help/info/encode_base64.html create mode 100644 help/info/encvalue.html create mode 100644 help/info/enumerated.html create mode 100644 help/info/error.html create mode 100644 help/info/except.html create mode 100644 help/info/exception.html create mode 100644 help/info/execute.html create mode 100644 help/info/extension.html create mode 100644 help/info/external.html create mode 100644 help/info/fail.html create mode 100644 help/info/false.html create mode 100644 help/info/float.html create mode 100644 help/info/float2int.html create mode 100644 help/info/float2str.html create mode 100644 help/info/for.html create mode 100644 help/info/friend.html create mode 100644 help/info/from.html create mode 100644 help/info/function.html create mode 100644 help/info/get_stringencoding.html create mode 100644 help/info/getcall.html create mode 100644 help/info/getreply.html create mode 100644 help/info/getverdict.html create mode 100644 help/info/goto.html create mode 100644 help/info/group.html create mode 100644 help/info/hex2bit.html create mode 100644 help/info/hex2int.html create mode 100644 help/info/hex2oct.html create mode 100644 help/info/hex2str.html create mode 100644 help/info/hexstring.html create mode 100644 help/info/if.html create mode 100644 help/info/ifpresent.html create mode 100644 help/info/import.html create mode 100644 help/info/in.html create mode 100644 help/info/inconc.html create mode 100644 help/info/infinity.html create mode 100644 help/info/inout.html create mode 100644 help/info/int2bit.html create mode 100644 help/info/int2char.html create mode 100644 help/info/int2float.html create mode 100644 help/info/int2hex.html create mode 100644 help/info/int2oct.html create mode 100644 help/info/int2str.html create mode 100644 help/info/int2unichar.html create mode 100644 help/info/integer.html create mode 100644 help/info/interleave.html create mode 100644 help/info/isbound.html create mode 100644 help/info/ischosen.html create mode 100644 help/info/ispresent.html create mode 100644 help/info/isvalue.html create mode 100644 help/info/kill.html create mode 100644 help/info/killed.html create mode 100644 help/info/label.html create mode 100644 help/info/language.html create mode 100644 help/info/length.html create mode 100644 help/info/lengthof.html create mode 100644 help/info/log.html create mode 100644 help/info/map.html create mode 100644 help/info/match.html create mode 100644 help/info/message.html create mode 100644 help/info/mixed.html create mode 100644 help/info/mod.html create mode 100644 help/info/modifies.html create mode 100644 help/info/module.html create mode 100644 help/info/modulepar.html create mode 100644 help/info/mtc.html create mode 100644 help/info/noblock.html create mode 100644 help/info/none.html create mode 100644 help/info/not.html create mode 100644 help/info/not4b.html create mode 100644 help/info/nowait.html create mode 100644 help/info/null.html create mode 100644 help/info/objid.html create mode 100644 help/info/oct2bit.html create mode 100644 help/info/oct2char.html create mode 100644 help/info/oct2hex.html create mode 100644 help/info/oct2int.html create mode 100644 help/info/oct2str.html create mode 100644 help/info/oct2unichar.html create mode 100644 help/info/octetstring.html create mode 100644 help/info/of.html create mode 100644 help/info/omit.html create mode 100644 help/info/on.html create mode 100644 help/info/operators.html create mode 100644 help/info/optional.html create mode 100644 help/info/or.html create mode 100644 help/info/or4b.html create mode 100644 help/info/out.html create mode 100644 help/info/override.html create mode 100644 help/info/param.html create mode 100644 help/info/pass.html create mode 100644 help/info/pattern.html create mode 100644 help/info/permutation.html create mode 100644 help/info/port.html create mode 100644 help/info/private.html create mode 100644 help/info/procedure.html create mode 100644 help/info/public.html create mode 100644 help/info/raise.html create mode 100644 help/info/read.html create mode 100644 help/info/receive.html create mode 100644 help/info/record.html create mode 100644 help/info/recursive.html create mode 100644 help/info/regexp.html create mode 100644 help/info/rem.html create mode 100644 help/info/remove_bom.html create mode 100644 help/info/repeat.html create mode 100644 help/info/replace.html create mode 100644 help/info/reply.html create mode 100644 help/info/return.html create mode 100644 help/info/rnd.html create mode 100644 help/info/running.html create mode 100644 help/info/runs.html create mode 100644 help/info/select.html create mode 100644 help/info/self.html create mode 100644 help/info/send.html create mode 100644 help/info/sender.html create mode 100644 help/info/set.html create mode 100644 help/info/setverdict.html create mode 100644 help/info/signature.html create mode 100644 help/info/sizeof.html create mode 100644 help/info/start.html create mode 100644 help/info/stop.html create mode 100644 help/info/str2bit.html create mode 100644 help/info/str2float.html create mode 100644 help/info/str2hex.html create mode 100644 help/info/str2int.html create mode 100644 help/info/str2oct.html create mode 100644 help/info/subset.html create mode 100644 help/info/substr.html create mode 100644 help/info/superset.html create mode 100644 help/info/system.html create mode 100644 help/info/template.html create mode 100644 help/info/testcase.html create mode 100644 help/info/testcasename.html create mode 100644 help/info/timeout.html create mode 100644 help/info/timer.html create mode 100644 help/info/to.html create mode 100644 help/info/trigger.html create mode 100644 help/info/true.html create mode 100644 help/info/type.html create mode 100644 help/info/unichar2char.html create mode 100644 help/info/unichar2int.html create mode 100644 help/info/unichar2oct.html create mode 100644 help/info/union.html create mode 100644 help/info/universal.html create mode 100644 help/info/unmap.html create mode 100644 help/info/value.html create mode 100644 help/info/valueof.html create mode 100644 help/info/var.html create mode 100644 help/info/variant.html create mode 100644 help/info/verdicttype.html create mode 100644 help/info/while.html create mode 100644 help/info/with.html create mode 100644 help/info/xor.html create mode 100644 help/info/xor4b.html create mode 100644 help/titan.chm create mode 100644 help/titan.hhc create mode 100644 help/titan.hhp create mode 100644 help/titan_index.html create mode 100644 help/titan_main.html create mode 100644 help/ttcn3_help create mode 100644 langviz/.gitignore create mode 100644 langviz/Grammar.cc create mode 100644 langviz/Grammar.hh create mode 100644 langviz/Graph.cc create mode 100644 langviz/Graph.hh create mode 100644 langviz/Iterator.cc create mode 100644 langviz/Iterator.hh create mode 100644 langviz/Makefile create mode 100644 langviz/Node.cc create mode 100644 langviz/Node.hh create mode 100644 langviz/Rule.cc create mode 100644 langviz/Rule.hh create mode 100644 langviz/Symbol.cc create mode 100644 langviz/Symbol.hh create mode 100644 langviz/bison_la.l create mode 100644 langviz/bison_p.y create mode 100644 langviz/error.c create mode 100644 langviz/error.h create mode 100644 langviz/main.cc create mode 100644 license/.gitignore create mode 100644 license/Makefile create mode 100644 license/Makefile_renew_license create mode 100644 license/license.dat create mode 100644 license/license_gen.c create mode 100644 license/renew_license.c create mode 100644 license/renew_license.html create mode 100644 loggerplugins/JUnitLogger/.gitignore create mode 100644 loggerplugins/JUnitLogger/JUnitLogger.cc create mode 100644 loggerplugins/JUnitLogger/JUnitLogger.hh create mode 100644 loggerplugins/JUnitLogger/Makefile create mode 100644 loggerplugins/Makefile create mode 100644 loggerplugins/TSTLogger/.gitignore create mode 100644 loggerplugins/TSTLogger/Makefile create mode 100644 loggerplugins/TSTLogger/TSTLogger.cc create mode 100644 loggerplugins/TSTLogger/TSTLogger.hh create mode 100644 makefiles/Makefile.personal.MinGW create mode 100644 makefiles/Makefile.personal.bangjohansen create mode 100644 makefiles/Makefile.personal.cygwin15 create mode 100644 makefiles/Makefile.personal.ehubuux110 create mode 100644 makefiles/Makefile.personal.esekilxxen1843.rnd.ericsson.se create mode 100644 makefiles/Makefile.personal.esekits1024 create mode 100644 makefiles/Makefile.personal.esekits1080 create mode 100644 makefiles/Makefile.personal.esekits3013 create mode 100644 makefiles/Makefile.personal.tcclab1 create mode 100644 makefiles/Makefile.personal.tcclab2 create mode 100644 makefiles/Makefile.personal.tcclab3 create mode 100644 makefiles/Makefile.personal.tcclab4 create mode 100644 makefiles/Makefile.personal.tcclab5 create mode 100644 makefiles/Makefile.personal.tcclab6 create mode 100644 mctr2/Makefile create mode 100644 mctr2/cli/.gitignore create mode 100644 mctr2/cli/Cli.cc create mode 100644 mctr2/cli/Cli.h create mode 100644 mctr2/cli/Makefile create mode 100644 mctr2/cli/config_read.l create mode 100644 mctr2/cli/config_read.y create mode 100644 mctr2/editline/.gitignore create mode 100644 mctr2/editline/Makefile create mode 100644 mctr2/editline/libedit/.gitignore create mode 100644 mctr2/editline/libedit/COPYING create mode 100644 mctr2/editline/libedit/ChangeLog create mode 100644 mctr2/editline/libedit/INSTALL create mode 100644 mctr2/editline/libedit/Makefile.am create mode 100644 mctr2/editline/libedit/Makefile.in create mode 100644 mctr2/editline/libedit/THANKS create mode 100644 mctr2/editline/libedit/acinclude.m4 create mode 100644 mctr2/editline/libedit/aclocal.m4 create mode 100755 mctr2/editline/libedit/config.guess create mode 100644 mctr2/editline/libedit/config.h.in create mode 100755 mctr2/editline/libedit/config.sub create mode 100755 mctr2/editline/libedit/configure create mode 100644 mctr2/editline/libedit/configure.ac create mode 100755 mctr2/editline/libedit/depcomp create mode 100644 mctr2/editline/libedit/doc/.gitignore create mode 100644 mctr2/editline/libedit/doc/Makefile.am create mode 100644 mctr2/editline/libedit/doc/Makefile.in create mode 100644 mctr2/editline/libedit/examples/.gitignore create mode 100644 mctr2/editline/libedit/examples/Makefile.am create mode 100644 mctr2/editline/libedit/examples/Makefile.in create mode 100755 mctr2/editline/libedit/install-sh create mode 100644 mctr2/editline/libedit/libedit.pc.in create mode 100755 mctr2/editline/libedit/ltmain.sh create mode 100755 mctr2/editline/libedit/missing create mode 100644 mctr2/editline/libedit/src/.gitignore create mode 100644 mctr2/editline/libedit/src/Makefile.am create mode 100644 mctr2/editline/libedit/src/Makefile.in create mode 100644 mctr2/editline/libedit/src/chared.c create mode 100644 mctr2/editline/libedit/src/chared.h create mode 100644 mctr2/editline/libedit/src/chartype.c create mode 100644 mctr2/editline/libedit/src/chartype.h create mode 100644 mctr2/editline/libedit/src/common.c create mode 100644 mctr2/editline/libedit/src/editline/readline.h create mode 100644 mctr2/editline/libedit/src/el.c create mode 100644 mctr2/editline/libedit/src/el.h create mode 100644 mctr2/editline/libedit/src/el_term.h create mode 100644 mctr2/editline/libedit/src/eln.c create mode 100644 mctr2/editline/libedit/src/emacs.c create mode 100644 mctr2/editline/libedit/src/fgetln.c create mode 100644 mctr2/editline/libedit/src/filecomplete.c create mode 100644 mctr2/editline/libedit/src/filecomplete.h create mode 100644 mctr2/editline/libedit/src/hist.c create mode 100644 mctr2/editline/libedit/src/hist.h create mode 100644 mctr2/editline/libedit/src/histedit.h create mode 100644 mctr2/editline/libedit/src/history.c create mode 100644 mctr2/editline/libedit/src/key.c create mode 100644 mctr2/editline/libedit/src/key.h create mode 100644 mctr2/editline/libedit/src/makelist create mode 100644 mctr2/editline/libedit/src/map.c create mode 100644 mctr2/editline/libedit/src/map.h create mode 100644 mctr2/editline/libedit/src/parse.c create mode 100644 mctr2/editline/libedit/src/parse.h create mode 100644 mctr2/editline/libedit/src/prompt.c create mode 100644 mctr2/editline/libedit/src/prompt.h create mode 100644 mctr2/editline/libedit/src/read.c create mode 100644 mctr2/editline/libedit/src/read.h create mode 100644 mctr2/editline/libedit/src/readline.c create mode 100644 mctr2/editline/libedit/src/refresh.c create mode 100644 mctr2/editline/libedit/src/refresh.h create mode 100644 mctr2/editline/libedit/src/search.c create mode 100644 mctr2/editline/libedit/src/search.h create mode 100644 mctr2/editline/libedit/src/shlib_version create mode 100644 mctr2/editline/libedit/src/sig.c create mode 100644 mctr2/editline/libedit/src/sig.h create mode 100644 mctr2/editline/libedit/src/strlcat.c create mode 100644 mctr2/editline/libedit/src/strlcpy.c create mode 100644 mctr2/editline/libedit/src/sys.h create mode 100644 mctr2/editline/libedit/src/term.c create mode 100644 mctr2/editline/libedit/src/tokenizer.c create mode 100644 mctr2/editline/libedit/src/tty.c create mode 100644 mctr2/editline/libedit/src/tty.h create mode 100644 mctr2/editline/libedit/src/unvis.c create mode 100644 mctr2/editline/libedit/src/vi.c create mode 100644 mctr2/editline/libedit/src/vis.c create mode 100644 mctr2/editline/libedit/src/vis.h create mode 100644 mctr2/editline/libedit/src/wcsdup.c create mode 100644 mctr2/mctr/.gitignore create mode 100644 mctr2/mctr/MainController.cc create mode 100644 mctr2/mctr/MainController.h create mode 100644 mctr2/mctr/Makefile create mode 100644 mctr2/mctr/MctrError.cc create mode 100644 mctr2/mctr/UserInterface.cc create mode 100644 mctr2/mctr/UserInterface.h create mode 100644 mctr2/mctr/config_data.cc create mode 100644 mctr2/mctr/config_data.h create mode 100644 mctr2/mctr/main.cc create mode 100755 mctr2/mctr/ttcn3_start create mode 100644 parser/.gitignore create mode 100644 parser/Makefile create mode 100644 parser/parser.l create mode 100644 parser/parser.y create mode 100644 regression_test/.gitignore create mode 100644 regression_test/ASN1/Makefile create mode 100644 regression_test/ASN1/Test303/.gitignore create mode 100644 regression_test/ASN1/Test303/Makefile create mode 100644 regression_test/ASN1/Test303/Test303A.asn create mode 100644 regression_test/ASN1/Test303/Test303T.ttcn create mode 100644 regression_test/ASN1/Test303/config.cfg create mode 100644 regression_test/ASN1/Test307/.gitignore create mode 100644 regression_test/ASN1/Test307/Makefile create mode 100644 regression_test/ASN1/Test307/Test307A.asn create mode 100644 regression_test/ASN1/Test307/Test307T.ttcn create mode 100644 regression_test/ASN1/Test308/.gitignore create mode 100644 regression_test/ASN1/Test308/Makefile create mode 100644 regression_test/ASN1/Test308/Test308A.asn create mode 100644 regression_test/ASN1/Test308/Test308T.ttcn create mode 100644 regression_test/ASN1/Test309/.gitignore create mode 100644 regression_test/ASN1/Test309/Makefile create mode 100644 regression_test/ASN1/Test309/Test309A.asn create mode 100644 regression_test/ASN1/Test309/Test309T.ttcn create mode 100644 regression_test/ASN1/Test310/.gitignore create mode 100644 regression_test/ASN1/Test310/Makefile create mode 100644 regression_test/ASN1/Test310/Test310A.asn create mode 100644 regression_test/ASN1/Test310/Test310T.ttcn create mode 100644 regression_test/ASN1/Test330/Makefile create mode 100644 regression_test/ASN1/Test330/Test330A.asn create mode 100644 regression_test/ASN1/Test330/Test330T.ttcn create mode 100644 regression_test/ASN1/Test332/Makefile create mode 100644 regression_test/ASN1/Test332/Test332A.asn create mode 100644 regression_test/ASN1/Test332/Test332T.ttcn create mode 100644 regression_test/ASN1/Test338/.gitignore create mode 100644 regression_test/ASN1/Test338/Makefile create mode 100644 regression_test/ASN1/Test338/Test338A.asn create mode 100644 regression_test/ASN1/Test338/Test338T.ttcn create mode 100644 regression_test/ASN1/Test340/.gitignore create mode 100644 regression_test/ASN1/Test340/Makefile create mode 100644 regression_test/ASN1/Test340/Test340A.asn create mode 100644 regression_test/ASN1/Test340/Test340T.ttcn create mode 100644 regression_test/ASN1/Test342/.gitignore create mode 100644 regression_test/ASN1/Test342/Makefile create mode 100644 regression_test/ASN1/Test342/Test342A.asn create mode 100644 regression_test/ASN1/Test342/Test342T.ttcn create mode 100644 regression_test/ASN1/Test344/.gitignore create mode 100644 regression_test/ASN1/Test344/Makefile create mode 100644 regression_test/ASN1/Test344/Test344A.asn create mode 100644 regression_test/ASN1/Test344/Test344T.ttcn create mode 100644 regression_test/ASN1/Test346/.gitignore create mode 100644 regression_test/ASN1/Test346/Makefile create mode 100644 regression_test/ASN1/Test346/Test346A.asn create mode 100644 regression_test/ASN1/Test346/Test346T.ttcn create mode 100644 regression_test/ASN1/Test348/.gitignore create mode 100644 regression_test/ASN1/Test348/Makefile create mode 100644 regression_test/ASN1/Test348/Test348A.asn create mode 100644 regression_test/ASN1/Test348/Test348T.ttcn create mode 100644 regression_test/ASN1/Test350/.gitignore create mode 100644 regression_test/ASN1/Test350/Makefile create mode 100644 regression_test/ASN1/Test350/Test350A.asn create mode 100644 regression_test/ASN1/Test350/Test350T.ttcn create mode 100644 regression_test/ASN1/Test350/config.cfg create mode 100644 regression_test/ASN1/Test352/.gitignore create mode 100644 regression_test/ASN1/Test352/Makefile create mode 100644 regression_test/ASN1/Test352/Test352A.asn create mode 100644 regression_test/ASN1/Test352/Test352T.ttcn create mode 100644 regression_test/ASN1/Test352/config.cfg create mode 100644 regression_test/ASN1/Test354/.gitignore create mode 100644 regression_test/ASN1/Test354/Makefile create mode 100644 regression_test/ASN1/Test354/Test354A.asn create mode 100644 regression_test/ASN1/Test354/Test354T.ttcn create mode 100644 regression_test/ASN1/Test354/config.cfg create mode 100644 regression_test/ASN1/Test356/.gitignore create mode 100644 regression_test/ASN1/Test356/Makefile create mode 100644 regression_test/ASN1/Test356/Test356A.asn create mode 100644 regression_test/ASN1/Test356/Test356T.ttcn create mode 100644 regression_test/ASN1/Test356/config.cfg create mode 100644 regression_test/ASN1/Test358/.gitignore create mode 100644 regression_test/ASN1/Test358/Makefile create mode 100644 regression_test/ASN1/Test358/Test358A.asn create mode 100644 regression_test/ASN1/Test358/Test358T.ttcn create mode 100644 regression_test/ASN1/Test358/config.cfg create mode 100644 regression_test/ASN1/Test360/.gitignore create mode 100644 regression_test/ASN1/Test360/Makefile create mode 100644 regression_test/ASN1/Test360/Test360A.asn create mode 100644 regression_test/ASN1/Test360/Test360T.ttcn create mode 100644 regression_test/ASN1/Test360/config.cfg create mode 100644 regression_test/ASN1/Test38/.gitignore create mode 100644 regression_test/ASN1/Test38/Makefile create mode 100644 regression_test/ASN1/Test38/Test38A.asn create mode 100644 regression_test/ASN1/Test38/Test38B.asn create mode 100755 regression_test/ASN1/Test38/Test38compare create mode 100644 regression_test/ASN1/codeGeneration2/.gitignore create mode 100644 regression_test/ASN1/codeGeneration2/Makefile create mode 100644 regression_test/ASN1/codeGeneration2/Test46.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test48.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test49.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test51.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test52.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test53.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test54.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test55.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test56.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test57.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test60.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test61.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test62.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test63.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test64.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test65.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test66.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test68.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test71.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test74.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test75.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test76.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test77.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test78.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test80.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test81.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test83.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test86.asn create mode 100644 regression_test/ASN1/codeGeneration2/Test87.asn create mode 100755 regression_test/ASN1/codeGeneration2/codeGeneration2 create mode 100644 regression_test/ASN1/enum1/.gitignore create mode 100644 regression_test/ASN1/enum1/Makefile create mode 100644 regression_test/ASN1/enum1/Test23.asn create mode 100755 regression_test/ASN1/enum1/enum1 create mode 100644 regression_test/ASN1/enum2/.gitignore create mode 100644 regression_test/ASN1/enum2/Makefile create mode 100644 regression_test/ASN1/enum2/Test25.asn create mode 100755 regression_test/ASN1/enum2/enum2 create mode 100644 regression_test/ASN1/errorMessages/Makefile create mode 100644 regression_test/ASN1/errorMessages/Test11.asn create mode 100644 regression_test/ASN1/errorMessages/Test12.asn create mode 100644 regression_test/ASN1/errorMessages/Test13.asn create mode 100644 regression_test/ASN1/errorMessages/Test14.asn create mode 100644 regression_test/ASN1/errorMessages/Test15.asn create mode 100644 regression_test/ASN1/errorMessages/Test16.asn create mode 100644 regression_test/ASN1/errorMessages/Test17.asn create mode 100644 regression_test/ASN1/errorMessages/Test18.asn create mode 100644 regression_test/ASN1/errorMessages/Test19_1.asn create mode 100644 regression_test/ASN1/errorMessages/Test19_2.asn create mode 100644 regression_test/ASN1/errorMessages/Test20.asn create mode 100644 regression_test/ASN1/errorMessages/Test21.asn create mode 100644 regression_test/ASN1/errorMessages/Test22.asn create mode 100644 regression_test/ASN1/errorMessages/Test24.asn create mode 100644 regression_test/ASN1/errorMessages/Test26.asn create mode 100644 regression_test/ASN1/errorMessages/Test28.asn create mode 100644 regression_test/ASN1/errorMessages/Test32.asn create mode 100644 regression_test/ASN1/errorMessages/Test33.asn create mode 100644 regression_test/ASN1/errorMessages/Test34.asn create mode 100644 regression_test/ASN1/errorMessages/Test39.asn create mode 100644 regression_test/ASN1/errorMessages/Test40.asn create mode 100644 regression_test/ASN1/errorMessages/Test41.asn create mode 100644 regression_test/ASN1/errorMessages/Test42.asn create mode 100644 regression_test/ASN1/errorMessages/Test43.asn create mode 100644 regression_test/ASN1/errorMessages/Test44.asn create mode 100644 regression_test/ASN1/errorMessages/Test45.asn create mode 100644 regression_test/ASN1/errorMessages/Test47.asn create mode 100644 regression_test/ASN1/errorMessages/Test50.asn create mode 100644 regression_test/ASN1/errorMessages/Test67.asn create mode 100644 regression_test/ASN1/errorMessages/Test69.asn create mode 100644 regression_test/ASN1/errorMessages/Test70.asn create mode 100644 regression_test/ASN1/errorMessages/Test72.asn create mode 100644 regression_test/ASN1/errorMessages/Test73.asn create mode 100644 regression_test/ASN1/errorMessages/Test79.asn create mode 100644 regression_test/ASN1/errorMessages/Test82.asn create mode 100644 regression_test/ASN1/errorMessages/Test84.asn create mode 100644 regression_test/ASN1/errorMessages/Test85.asn create mode 100755 regression_test/ASN1/errorMessages/error create mode 100644 regression_test/ASN1/errorMessages2/Makefile create mode 100644 regression_test/ASN1/errorMessages2/Test10.asn create mode 100755 regression_test/ASN1/errorMessages2/error2 create mode 100644 regression_test/ASN1/hyphen/.gitignore create mode 100644 regression_test/ASN1/hyphen/Makefile create mode 100644 regression_test/ASN1/hyphen/Test284.asn create mode 100755 regression_test/ASN1/hyphen/hyphen create mode 100644 regression_test/ASN1/keyword/.gitignore create mode 100644 regression_test/ASN1/keyword/Makefile create mode 100644 regression_test/ASN1/keyword/Test283.asn create mode 100644 regression_test/ASN1/keyword/Test283T.ttcn create mode 100755 regression_test/ASN1/keyword/keyword create mode 100644 regression_test/ASN1/parse/Makefile create mode 100644 regression_test/ASN1/parse/Test1.asn create mode 100644 regression_test/ASN1/parse/Test1_known_errors.asn create mode 100644 regression_test/ASN1/parse/Test2.asn create mode 100644 regression_test/ASN1/parse/Test2_known_errors.asn create mode 100644 regression_test/ASN1/parse/Test3.asn create mode 100644 regression_test/ASN1/parse/Test3_known_errors.asn create mode 100644 regression_test/ASN1/parse/Test4.asn create mode 100644 regression_test/ASN1/parse/Test4_known_errors.asn create mode 100755 regression_test/ASN1/parse/parse create mode 100644 regression_test/ASN1/transformations/.gitignore create mode 100644 regression_test/ASN1/transformations/Makefile create mode 100644 regression_test/ASN1/transformations/Test289A.asn create mode 100644 regression_test/ASN1/transformations/Test289B.asn create mode 100644 regression_test/ASN1/transformations/Test5A.asn create mode 100644 regression_test/ASN1/transformations/Test5B.asn create mode 100644 regression_test/ASN1/transformations/Test6A.asn create mode 100644 regression_test/ASN1/transformations/Test6B.asn create mode 100644 regression_test/ASN1/transformations/Test7A.asn create mode 100644 regression_test/ASN1/transformations/Test7B.asn create mode 100644 regression_test/ASN1/transformations/Test8A.asn create mode 100644 regression_test/ASN1/transformations/Test8B.asn create mode 100644 regression_test/ASN1/transformations/Test9A.asn create mode 100644 regression_test/ASN1/transformations/Test9B.asn create mode 100755 regression_test/ASN1/transformations/compare3 create mode 100644 regression_test/BER/.gitignore create mode 100644 regression_test/BER/Makefile create mode 100644 regression_test/BER/MyPort1.cc create mode 100644 regression_test/BER/MyPort1.hh create mode 100644 regression_test/BER/MyPort2.cc create mode 100644 regression_test/BER/MyPort2.hh create mode 100644 regression_test/BER/Regr.cfg create mode 100644 regression_test/BER/Regr.ttcn create mode 100644 regression_test/BER/Regr1.asn create mode 100644 regression_test/BER/Regr2.asn create mode 100644 regression_test/BER_x682/.gitignore create mode 100644 regression_test/BER_x682/Makefile create mode 100644 regression_test/BER_x682/MyPort1.cc create mode 100644 regression_test/BER_x682/MyPort1.hh create mode 100644 regression_test/BER_x682/MyPort2.cc create mode 100644 regression_test/BER_x682/MyPort2.hh create mode 100644 regression_test/BER_x682/X.cfg create mode 100644 regression_test/BER_x682/X.ttcn create mode 100644 regression_test/BER_x682/X682.asn create mode 100644 regression_test/BER_x682_wa/Makefile create mode 100644 regression_test/BER_x682_wa/MyPort1.cc create mode 100644 regression_test/BER_x682_wa/MyPort1.hh create mode 100644 regression_test/BER_x682_wa/MyPort2.cc create mode 100644 regression_test/BER_x682_wa/MyPort2.hh create mode 100644 regression_test/BER_x682_wa/X.cfg create mode 100644 regression_test/BER_x682_wa/X.ttcn create mode 100644 regression_test/BER_x682_wa/x682.asn create mode 100644 regression_test/CRTR00015758/.gitignore create mode 100644 regression_test/CRTR00015758/Makefile create mode 100644 regression_test/CRTR00015758/config.cfg create mode 100755 regression_test/CRTR00015758/logfilecheck create mode 100644 regression_test/CRTR00015758/no.ttcn create mode 100644 regression_test/CRTR00015758/run.cfg create mode 100644 regression_test/CRTR00015758/trouble.cfg create mode 100644 regression_test/ERC/.gitignore create mode 100644 regression_test/ERC/Makefile create mode 100644 regression_test/ERC/base.cfg create mode 100644 regression_test/ERC/config.cfg create mode 100644 regression_test/ERC/erc.ttcn create mode 100644 regression_test/ERC/included1.cfg create mode 100644 regression_test/ERC/included2.cfg create mode 100644 regression_test/ERC/subdir/subdir_config.cfg create mode 100644 regression_test/HP17080/.gitignore create mode 100644 regression_test/HQ16404/.gitignore create mode 100644 regression_test/HQ16404/HQ16404.ttcn create mode 100644 regression_test/HQ16404/Makefile create mode 100644 regression_test/HQ16404/config.cfg create mode 100644 regression_test/Makefile create mode 100644 regression_test/Makefile.regression create mode 100644 regression_test/RAW/Examples/.gitignore create mode 100644 regression_test/RAW/Examples/DTAP_RAW_Samples.ttcn create mode 100644 regression_test/RAW/Examples/DTAP_typedefs.ttcn create mode 100644 regression_test/RAW/Examples/Makefile create mode 100644 regression_test/RAW/Examples/RAW_Test.ttcn create mode 100644 regression_test/RAW/Examples/RAWtest.cfg create mode 100644 regression_test/RAW/Examples/SCCP_RAW_Samples.ttcn create mode 100644 regression_test/RAW/Examples/SCCP_typedefs.ttcn create mode 100644 regression_test/RAW/Examples/general_typedefs.ttcn create mode 100644 regression_test/RAW/HN25015/.gitignore create mode 100644 regression_test/RAW/HN25015/General_Types.ttcn create mode 100644 regression_test/RAW/HN25015/HN25015.ttcn create mode 100644 regression_test/RAW/HN25015/Makefile create mode 100644 regression_test/RAW/HN25015/SGsAP_Types.ttcn create mode 100644 regression_test/RAW/HN25015/config.cfg create mode 100644 regression_test/RAW/HQ26535/.gitignore create mode 100644 regression_test/RAW/HQ26535/GTPv2_Types.ttcn create mode 100644 regression_test/RAW/HQ26535/General_Types.ttcn create mode 100644 regression_test/RAW/HQ26535/Makefile create mode 100644 regression_test/RAW/HQ26535/gtpctest.ttcn create mode 100644 regression_test/RAW/HQ49956/Makefile create mode 100644 regression_test/RAW/HQ49956/Module.ttcn create mode 100644 regression_test/RAW/HQ49956/Test.ttcn create mode 100644 regression_test/RAW/HS16977/HS16977_Constants.ttcn create mode 100644 regression_test/RAW/HS16977/HS16977_Test.ttcn create mode 100644 regression_test/RAW/HS16977/HS16977_Types.ttcn create mode 100644 regression_test/RAW/HS16977/Makefile create mode 100644 regression_test/RAW/HS16977/config.cfg create mode 100644 regression_test/RAW/Makefile create mode 100644 regression_test/XML/EXER-whitepaper/.gitignore create mode 100644 regression_test/XML/EXER-whitepaper/AnyAttributes.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/AnyElement.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/AnyElementOptional.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/AnyElementOptional2.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/Attribute.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/DefaultForEmpty.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/EmbedValues.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/List.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/Makefile create mode 100644 regression_test/XML/EXER-whitepaper/Name.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/Namespaces.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/NamespacesDup.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/Order.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/Qname.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/Text.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/Untagged.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/Untagged1.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/UseNil.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/UseNilSimple.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/UseNumber.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/UseOrder.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/UseType.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/UseUnion.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/Whitespace.ttcnpp create mode 100644 regression_test/XML/EXER-whitepaper/config.cfg create mode 100644 regression_test/XML/HM60295/.gitignore create mode 100644 regression_test/XML/HM60295/Importer.xsd create mode 100644 regression_test/XML/HM60295/Makefile create mode 100644 regression_test/XML/HM60295/Schema1.xsd create mode 100644 regression_test/XML/HM60295/Schema2.xsd create mode 100644 regression_test/XML/HM60295/config.cfg create mode 100644 regression_test/XML/HM60295/tester.ttcn create mode 100644 regression_test/XML/HN15589/.gitignore create mode 100644 regression_test/XML/HN15589/A.xsd create mode 100644 regression_test/XML/HN15589/B.xsd create mode 100644 regression_test/XML/HN15589/HN15589.ttcnpp create mode 100644 regression_test/XML/HN15589/Makefile create mode 100644 regression_test/XML/HN15589/config.cfg create mode 100644 regression_test/XML/HN15589/flipflop-check.xsd create mode 100644 regression_test/XML/HN15589/log2xml.pl create mode 100644 regression_test/XML/HN15589/xsd/XTDL.xsd create mode 100644 regression_test/XML/HN15589/xsd/XTDP-Message.xsd create mode 100644 regression_test/XML/HN15589/xtdl.ttcn create mode 100644 regression_test/XML/HN15589/xtdp.cfg create mode 100644 regression_test/XML/HN15589/xtdp.ttcn create mode 100644 regression_test/XML/HN34094/.gitignore create mode 100644 regression_test/XML/HQ30408/.gitignore create mode 100644 regression_test/XML/HQ30408/HQ30408.ttcn create mode 100644 regression_test/XML/HQ30408/Makefile create mode 100644 regression_test/XML/HR49727/.gitignore create mode 100644 regression_test/XML/HR49727/HR49727.ttcn create mode 100644 regression_test/XML/HR49727/Makefile create mode 100644 regression_test/XML/HR49727/UsefulTtcn3Types.ttcn create mode 100644 regression_test/XML/HR49727/XSD.ttcn create mode 100644 regression_test/XML/HR49727/config.cfg create mode 100644 regression_test/XML/HR49727/http_jabber_org_protocol_pubsub.ttcn create mode 100644 regression_test/XML/HR49727/http_jabber_org_protocol_pubsub_event.ttcn create mode 100644 regression_test/XML/HR49727/jabber_x_data.ttcn create mode 100644 regression_test/XML/Makefile create mode 100644 regression_test/XML/NegativeTest/.gitignore create mode 100644 regression_test/XML/NegativeTest/Makefile create mode 100644 regression_test/XML/NegativeTest/ReadXml.ttcn create mode 100644 regression_test/XML/NegativeTest/ReadXmlImpl.cc create mode 100644 regression_test/XML/NegativeTest/exer_rec.ttcn create mode 100644 regression_test/XML/NegativeTest/exer_rec_of.ttcn create mode 100644 regression_test/XML/NegativeTest/exer_uni.ttcn create mode 100755 regression_test/XML/NegativeTest/indent.pl create mode 100644 regression_test/XML/NegativeTest/rec.ttcn create mode 100644 regression_test/XML/NegativeTest/rec_of.ttcn create mode 100644 regression_test/XML/NegativeTest/run.cfg create mode 100644 regression_test/XML/NegativeTest/runner.ttcn create mode 100644 regression_test/XML/NegativeTest/uni.ttcn create mode 100644 regression_test/XML/TTCNandXML/.gitignore create mode 100644 regression_test/XML/TTCNandXML/AnnexB1.ttcn create mode 100644 regression_test/XML/TTCNandXML/AnnexB1Template.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/AnnexB2.ttcn create mode 100644 regression_test/XML/TTCNandXML/AnnexB2Template.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/AnnexB3.ttcn create mode 100644 regression_test/XML/TTCNandXML/AnnexB3Template.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/AnnexB4.ttcn create mode 100644 regression_test/XML/TTCNandXML/AnnexB4Template.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/AnyStuff.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/AttribPath.ttcn create mode 100644 regression_test/XML/TTCNandXML/AttribPathTest.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/AttributesTest.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/Base64Test.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/DFEAttribTest.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/DFETest.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/E0.ttcn create mode 100644 regression_test/XML/TTCNandXML/EmbedValues.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/EnumTest.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/Flattener.ttcn create mode 100644 regression_test/XML/TTCNandXML/Makefile create mode 100644 regression_test/XML/TTCNandXML/Marx.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/NamespaceDef.ttcn create mode 100644 regression_test/XML/TTCNandXML/NamespaceTest.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/Regressions.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/UTF8.ttcn create mode 100644 regression_test/XML/TTCNandXML/WhitespaceTest.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/X693amd1.ttcn create mode 100644 regression_test/XML/TTCNandXML/X693amd1Test.ttcnpp create mode 100644 regression_test/XML/TTCNandXML/XSDAttributes.ttcn create mode 100644 regression_test/XML/TTCNandXML/config.cfg create mode 100644 regression_test/XML/XER/.gitignore create mode 100644 regression_test/XML/XER/AsnValues.asn create mode 100644 regression_test/XML/XER/Asntypes.asn create mode 100644 regression_test/XML/XER/EmptyUnion.asn create mode 100644 regression_test/XML/XER/Flatten.cc create mode 100644 regression_test/XML/XER/Makefile create mode 100644 regression_test/XML/XER/ObjectClass.asn create mode 100644 regression_test/XML/XER/ObjectClassWithSyntax.asn create mode 100644 regression_test/XML/XER/SetValues.asn create mode 100644 regression_test/XML/XER/Sets.asn create mode 100644 regression_test/XML/XER/Txerasntypes.ttcnpp create mode 100644 regression_test/XML/XER/Txerbinstr.ttcnpp create mode 100644 regression_test/XML/XER/Txerboolean.ttcnpp create mode 100644 regression_test/XML/XER/Txerenum.ttcnpp create mode 100644 regression_test/XML/XER/Txerfloat.ttcnpp create mode 100644 regression_test/XML/XER/Txerint.ttcnpp create mode 100644 regression_test/XML/XER/Txernested.ttcnpp create mode 100644 regression_test/XML/XER/Txerobjclass.ttcnpp create mode 100644 regression_test/XML/XER/Txersets.ttcnpp create mode 100644 regression_test/XML/XER/Txerstring.ttcnpp create mode 100755 regression_test/XML/XER/checkit.pl create mode 100644 regression_test/XML/XER/config.cfg create mode 100644 regression_test/XML/XER/junk.ttcn3 create mode 100644 regression_test/XML/XMLqualif/.gitignore create mode 100644 regression_test/XML/XMLqualif/Makefile create mode 100644 regression_test/XML/XMLqualif/POtest.ttcnpp create mode 100644 regression_test/XML/XMLqualif/config.cfg create mode 100644 regression_test/XML/XMLqualif/globall.xsd create mode 100644 regression_test/XML/XMLqualif/po_qual.xsd create mode 100644 regression_test/XML/XMLqualif/po_qual_atr.xsd create mode 100644 regression_test/XML/XMLqualif/po_qual_both.xsd create mode 100644 regression_test/XML/XMLqualif/po_qual_default.xml create mode 100644 regression_test/XML/XMLqualif/po_qual_explicit.xml create mode 100644 regression_test/XML/XMLqualif/po_unqual.xml create mode 100644 regression_test/XML/XMLqualif/po_unqual.xsd create mode 100644 regression_test/XML/XmlWorkflow/Makefile create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/demo/PIPE.cfg create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/demo/PIPEasp_Templates.ttcn create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/demo/PipeTest.prj create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/demo/PipeTest.ttcn create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/demo/ShellNotice.sh create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/demo/ShellQuestionString.sh create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/demo/ShellQuestionYesNo.sh create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/src/PIPEasp_PT.cc create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/src/PIPEasp_PT.hh create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/src/PIPEasp_PortType.ttcn create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/src/PIPEasp_Types.ttcn create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/test/Makefile create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/test/PIPEasp_PT.cc create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/test/PIPEasp_PT.hh create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/test/PIPEasp_PortType.ttcn create mode 100644 regression_test/XML/XmlWorkflow/PIPEasp_CNL113334/test/PIPEasp_Types.ttcn create mode 100644 regression_test/XML/XmlWorkflow/Tgc/IsTypes.xsd create mode 100644 regression_test/XML/XmlWorkflow/Tgc/Tgc.ttcn create mode 100644 regression_test/XML/XmlWorkflow/Tgc/Tgc.xsd create mode 100644 regression_test/XML/XmlWorkflow/Tgc/UsefulTtcn3Types.ttcn create mode 100644 regression_test/XML/XmlWorkflow/Tgc/XMLSchema.xsd create mode 100644 regression_test/XML/XmlWorkflow/Tgc/XSD.ttcn create mode 100644 regression_test/XML/XmlWorkflow/Tgc/confd.xsd create mode 100644 regression_test/XML/XmlWorkflow/Tgc/tail_f_com_ns_confd_1_0.ttcn create mode 100644 regression_test/XML/XmlWorkflow/Tgc/www_ericsson_com_is_isco_IsTypes_R4L06_R4AF11.ttcn create mode 100644 regression_test/XML/XmlWorkflow/Tgc/www_ericsson_com_is_isco_Tgc_R6A48_R6H01.ttcn create mode 100644 regression_test/XML/XmlWorkflow/Tgc/www_w3_org_XML_1998_namespace.ttcn create mode 100644 regression_test/XML/XmlWorkflow/Tgc/xml.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/ETSI_CR5852_union_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/NoTargetNamespace_CCAPI_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/NoTargetNamespace_JMdict_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/NoTargetNamespace_PAP_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/NoTargetNamespace_RLP_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/NoTargetNamespace_XML_RPC_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/NoTargetNamespace_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/XmlTest_imsike_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/http_www_XmlTest_org_po_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/http_www_example_org_ttcn_wildcards_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/ietf_params_xml_ns_pidf_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/ietf_params_xml_ns_pidf_status_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/ietf_params_xml_ns_resource_lists_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/ietf_params_xml_ns_rlmi_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/schemas_ericsson_com_cai3g1_1_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/schemas_ericsson_com_cai3g1_2_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/schemas_ericsson_com_ma_HSS_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/schemas_ericsson_com_upg_bulkprovisioning_1_0_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/schemas_ericsson_com_upg_dm_hss_sh_4_1_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/schemas_ericsson_com_upg_provisioning_1_0_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/tail_f_com_ns_confd_1_0_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/uri_etsi_org_ngn_params_xml_simservs_sci_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/urn_ietf_params_xml_ns_conference_info_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_annotation_c_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_annotation_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_annotation_e_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_annotation_t_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_boolean_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex1_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex2_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_all_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_any_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_choice_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_extension_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_import_AB_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_import_A_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_import_B_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_import_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_include1_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_include2_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_include_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_minOccursMaxOccurs_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_mixed_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_restriction_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_complex_simpleContent_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_decimal_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_decimal_withEnum_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_decimal_withLength_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_decimal_withMinMaxExclusive_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_decimal_withMinMaxInclusive_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_element_anyType_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_element_nameInheritance_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_element_recordOfElements3_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_element_recordOfElements4_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_element_recordOfElements5_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_element_recordOfElements_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_empty_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_integer_MaxExcl_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_integer_MaxIncl_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_integer_MinExcl_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_integer_MinIncl_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_integer_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_integer_withEnum_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_integer_withMaxExcl_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_integer_withMaxIncl_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_integer_withMinExcl_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_integer_withMinIncl_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_list_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_list_integer_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_simple_enum_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withEmptyLength_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withEmptyMax_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withEmptyMin_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withEnum_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withFaultyMinMax_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withFixedLength_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withFloatLength_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withMinLength_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withNegativeLength_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withNegativeMin_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withOverDefinition_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withPosLength_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withPosMax_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withTypeAndBase_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_string_withWhitespace_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_time_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_time_withEnum_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_XmlTest_org_union_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_csapi_org_schema_parlayx_common_v2_0_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_csapi_org_schema_parlayx_payment_amount_charging_v2_0_local_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_csapi_org_schema_parlayx_payment_reserve_amount_charging_v2_0_local_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_csapi_org_schema_parlayx_payment_reserve_volume_charging_v2_0_local_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_csapi_org_schema_parlayx_payment_v2_0_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_csapi_org_schema_parlayx_payment_volume_charging_v2_0_local_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_ericsson_com_is_isco_IntegratedSite_R4L06_R4AB_1_02_HK84933_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_ericsson_com_is_isco_IntegratedSite_R4L06_R4AB_1_02_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_ericsson_com_is_isco_IsTypes_R4L06_R4AB_1_02_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_ericsson_com_is_isco_IsTypes_R4L06_R4AF11_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_ericsson_com_is_isco_MainSwitch_R4L06_R4AB_1_02_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_ericsson_com_is_isco_Mgw_R9B27_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_ericsson_com_is_isco_Misc_R4L06_R4AB_1_02_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_ericsson_com_is_isco_Tgc_R6A48_R6H01_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_example_org_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_w3_org_XML_1998_namespace_PIDF_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_expectedTtcns/www_w3_org_XML_1998_namespace_e.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/CAI3G/Bulk.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/CAI3G/GenericCai3gType.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/CAI3G/Provisioning.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/CCAPI/CCAPI.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/HSS/avg.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/HSS/cai3g1.2_provisioning.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/HSS/eps.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/HSS/hssla_types.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/JMdict/jmdict-good.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/MGW/IntegratedSite.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/MGW/IntegratedSite_HK84933.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/MGW/IsTypes.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/MGW/MainSwitch.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/MGW/Mgw_R9B27.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/MGW/Misc.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/MGW/XMLSchema.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/MGW/confd.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/MGW/xml.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/PAP/PAP.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/PIDF/pidf.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/PIDF/rlmi.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/PIDF/testschema.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/PIDF/xml_PIDF.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/ParlayX/parlayx_common_types_2_0.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/ParlayX/parlayx_payment_amount_charging_interface_2_0.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/ParlayX/parlayx_payment_reserve_amount_charging_interface_2_0.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/ParlayX/parlayx_payment_reserve_volume_charging_interface_2_0.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/ParlayX/parlayx_payment_types_2_0.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/ParlayX/parlayx_payment_volume_charging_interface_2_0.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/RLP/RLP_SVC.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/RLXML/RLXML_small.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/RLXML/rlxml.xml create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/SIP/SIP.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/ShData/ShDataType.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_protocolXSDs/XML_RPC/XML_RPC.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/ETSI_CR5852_union.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/UsefulTtcn3Types.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XSD.ttcn create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_annotation.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_annotation1.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_annotation2.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_boolean.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_boolean_withTypeAndBase.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex1.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex2.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_all.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_any.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_choice.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_extension.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_import_A.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_import_AB.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_import_B.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_import_neg1.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_import_pos.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_import_withSchemaLocation.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_include.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_include1.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_include2.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_minOccursMaxOccurs.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_mixed.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_restriction.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_restriction_neg1.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_restriction_neg2.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_simpleContent.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_complex_unique.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_decimal.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_decimal_withEnum.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_decimal_withLength.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_decimal_withMinMaxExclusive.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_decimal_withMinMaxInclusive.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_element_abstract.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_element_anyType.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_element_nameInheritance.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_element_recordOfElements.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_element_recordOfElements3.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_element_recordOfElements4.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_element_recordOfElements5.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_files1.txt create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_imsike.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_integer.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_integer_empty1.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_integer_withEnum.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_integer_withLength.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_integer_withMaxExcl.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_integer_withMaxIncl.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_integer_withMinExcl.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_integer_withMinIncl.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_list.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_list_integer.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_simple_enum.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withEmptyLength.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withEmptyMax.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withEmptyMin.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withEnum.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withFaultyMinMax.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withFixedLength.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withFloatLength.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withMinLength.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withNegativeLength.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withNegativeMax.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withNegativeMin.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withOverDefinition.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withPosLength.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withPosMax.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withTypeAndBase.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_string_withWhitespace.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_time.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_time_withEnum.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_union.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_union2.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/XmlTest_version.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/empty.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/noTargetNamespace.xsd create mode 100644 regression_test/XML/XmlWorkflow/XmlTest_xsds/po.xsd create mode 100644 regression_test/XML/XmlWorkflow/bin/.gitignore create mode 100644 regression_test/XML/XmlWorkflow/bin/prj2mk.pl create mode 100644 regression_test/XML/XmlWorkflow/bin2/.gitignore create mode 100755 regression_test/XML/XmlWorkflow/bin2/prj2mk.pl create mode 100644 regression_test/XML/XmlWorkflow/src/UsefulTtcn3Types.ttcn create mode 100644 regression_test/XML/XmlWorkflow/src/XSD.ttcn create mode 100644 regression_test/XML/XmlWorkflow/src/XmlTest.cfg create mode 100644 regression_test/XML/XmlWorkflow/src/XmlTest_protocolXsds.cfg create mode 100644 regression_test/XML/XmlWorkflow/src/my_xml_test_script create mode 100644 regression_test/XML/XmlWorkflow/src/xmlTest.prj create mode 100644 regression_test/XML/XmlWorkflow/src/xmlTest_Functions_complex.ttcn create mode 100644 regression_test/XML/XmlWorkflow/src/xmlTest_Functions_complex1.ttcn create mode 100644 regression_test/XML/XmlWorkflow/src/xmlTest_Functions_complex2.ttcn create mode 100644 regression_test/XML/XmlWorkflow/src/xmlTest_Functions_element.ttcn create mode 100644 regression_test/XML/XmlWorkflow/src/xmlTest_Functions_list.ttcn create mode 100644 regression_test/XML/XmlWorkflow/src/xmlTest_Functions_string.ttcn create mode 100644 regression_test/XML/XmlWorkflow/src/xmlTest_Shell.ttcn create mode 100644 regression_test/XML/XmlWorkflow/src/xmlTest_Testcases.ttcn create mode 100644 regression_test/XML/XmlWorkflow/src/xmlTest_encDec.ttcn create mode 100644 regression_test/XML/XmlWorkflow/src/xmlTest_protocolXsd_Testcases.ttcn create mode 100644 regression_test/XML/XmlWorkflow/src/xmlTest_protocolXsds.prj create mode 100644 regression_test/XML/XmlWorkflow/xsd/HQ73011.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/PDUexample.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/all.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/any_anyAttribute.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/attributeGroup.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/attribute_use.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/attribute_use_noTNS.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/complexTypes.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/elements.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/extending_complex_types.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/group_all.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/groups.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/include1dir1a.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/include1dir1b.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/include1dir2a.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/include1dir2b.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/includeCircular1a.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/includeCircular1b.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/includeCircular2a.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/includeCircular2b.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/includeCircular3a.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/includeCircular3b.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/includeCircular4a.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/includeCircular4b.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/list.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/list_invalid.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/minBound_maxBound.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/minOccurs_maxOccurs.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/name_clash_element-attribute.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/name_clash_element-attribute_noNsPrefix.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/ranges_float.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/ranges_integer.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/restricting_complex_types.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/schema.xsd create mode 100644 regression_test/XML/XmlWorkflow/xsd/union.xsd create mode 100644 regression_test/XML/macros.ttcnin create mode 100644 regression_test/XML/xsdConverter/Examples/.gitignore create mode 100644 regression_test/XML/xsdConverter/Examples/Example1.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/Example2.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/Example3.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/Example4.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/Examples.ttcn create mode 100644 regression_test/XML/xsdConverter/Examples/Makefile create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_5_1_1.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_5_1_2.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_5_1_3.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_5_1_4.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_5_1_5.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_5_1_6.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_5_2_1.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_5_2_2.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_5_2_3.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_6.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_7_1.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_7_3.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_7_4.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_7_5.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_7_6.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_7_7.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_7_8.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/chapter_7_9.xsd create mode 100644 regression_test/XML/xsdConverter/Examples/config.cfg create mode 100644 regression_test/XML/xsdConverter/HN21072/.gitignore create mode 100644 regression_test/XML/xsdConverter/HN21072/HN21072Test.ttcn create mode 100644 regression_test/XML/xsdConverter/HN21072/Makefile create mode 100644 regression_test/XML/xsdConverter/HN21072/W3-WSDL-chop.xsd create mode 100644 regression_test/XML/xsdConverter/HN21072/log2xml.pl create mode 100644 regression_test/XML/xsdConverter/HN65402/.gitignore create mode 100644 regression_test/XML/xsdConverter/HN65402/Makefile create mode 100644 regression_test/XML/xsdConverter/HN65402/jellystone.ttcn create mode 100644 regression_test/XML/xsdConverter/HN65402/jellystone.xsd create mode 100644 regression_test/XML/xsdConverter/HO12250/.gitignore create mode 100644 regression_test/XML/xsdConverter/HO12250/HO12250.xsd create mode 100644 regression_test/XML/xsdConverter/HO12250/Makefile create mode 100644 regression_test/XML/xsdConverter/HO16426/.gitignore create mode 100644 regression_test/XML/xsdConverter/HO16426/Makefile create mode 100644 regression_test/XML/xsdConverter/HO16426/diversion.ttcn create mode 100644 regression_test/XML/xsdConverter/HO16426/diversion.xsd create mode 100644 regression_test/XML/xsdConverter/HO18151/.gitignore create mode 100644 regression_test/XML/xsdConverter/HO18151/HO18151.ttcn create mode 100644 regression_test/XML/xsdConverter/HO18151/HO18151.xsd create mode 100644 regression_test/XML/xsdConverter/HO18151/Makefile create mode 100644 regression_test/XML/xsdConverter/HO21968/.gitignore create mode 100644 regression_test/XML/xsdConverter/HO21968/HO21968.ttcn create mode 100644 regression_test/XML/xsdConverter/HO21968/HO21968noprefix.xsd create mode 100644 regression_test/XML/xsdConverter/HO21968/HO21968prefix.xsd create mode 100644 regression_test/XML/xsdConverter/HO21968/Makefile create mode 100644 regression_test/XML/xsdConverter/HQ48576/.gitignore create mode 100644 regression_test/XML/xsdConverter/HQ48576/HQ48576Test.ttcn create mode 100644 regression_test/XML/xsdConverter/HQ48576/Makefile create mode 100644 regression_test/XML/xsdConverter/HQ48576/hlrla_types.xsd create mode 100644 regression_test/XML/xsdConverter/Makefile create mode 100644 regression_test/XML/xsdConverter/Makefile.converter create mode 100644 regression_test/acceptance_test/Fibonacci/Fibonacci.cfg create mode 100644 regression_test/acceptance_test/Fibonacci/Fibonacci.ttcn create mode 100644 regression_test/acceptance_test/Fibonacci/Makefile create mode 100644 regression_test/acceptance_test/chinese/Makefile create mode 100644 regression_test/acceptance_test/chinese/chinese.ttcn create mode 100644 regression_test/acceptance_test/comptest/.gitignore create mode 100644 regression_test/acceptance_test/comptest/Makefile create mode 100644 regression_test/acceptance_test/comptest/comptest.ttcn create mode 100644 regression_test/acceptance_test/testerlanc/Makefile create mode 100644 regression_test/acceptance_test/testerlanc/testerlanc.ttcn create mode 100644 regression_test/all_from/.gitignore create mode 100644 regression_test/all_from/Makefile create mode 100644 regression_test/all_from/all_from.ttcn create mode 100644 regression_test/all_from/all_from_complement.ttcn create mode 100644 regression_test/all_from/all_from_permutation.ttcn create mode 100644 regression_test/all_from/all_from_subset.ttcn create mode 100644 regression_test/all_from/all_from_superset.ttcn create mode 100644 regression_test/all_from/all_from_var.ttcn create mode 100644 regression_test/all_from/all_from_with_functions.ttcn create mode 100644 regression_test/all_from/everything.ttcn create mode 100644 regression_test/all_from/f_ext.cc create mode 100644 regression_test/all_from/f_ext.hh create mode 100644 regression_test/all_from/functions.ttcn create mode 100644 regression_test/all_from/imported_templates.ttcn create mode 100644 regression_test/all_from/sapc.ttcn create mode 100644 regression_test/all_from/types.ttcn create mode 100644 regression_test/anytype/.gitignore create mode 100644 regression_test/anytype/AnyUser.ttcnpp create mode 100644 regression_test/anytype/AnytypeTest.ttcnpp create mode 100644 regression_test/anytype/Makefile create mode 100644 regression_test/anytype/Supplier.asn create mode 100644 regression_test/anytype/config.cfg create mode 100644 regression_test/anytype/noany.ttcn create mode 100644 regression_test/anytype/smallany.ttcn create mode 100644 regression_test/anytypeOper/.gitignore create mode 100644 regression_test/anytypeOper/Makefile create mode 100644 regression_test/anytypeOper/TanytypeOper.ttcn create mode 100644 regression_test/anytypeOper/TanytypeWrapOper.ttcn create mode 100644 regression_test/anytypeOper/config.cfg create mode 100644 regression_test/arrayOper/.gitignore create mode 100644 regression_test/arrayOper/Makefile create mode 100644 regression_test/arrayOper/TarrayOper.ttcn create mode 100644 regression_test/arrayOper/config.cfg create mode 100644 regression_test/assignmentNotation/.gitignore create mode 100644 regression_test/assignmentNotation/Makefile create mode 100644 regression_test/assignmentNotation/TassignmentNotation.asn create mode 100755 regression_test/assignmentNotation/TassignmentNotation.cfg create mode 100644 regression_test/assignmentNotation/TassignmentNotation.ttcn create mode 100755 regression_test/assignmentNotation/TassignmentNotation_First.cfg create mode 100755 regression_test/assignmentNotation/TassignmentNotation_Second.cfg create mode 100755 regression_test/assignmentNotation/TassignmentNotation_Third.cfg create mode 100644 regression_test/basicStatem/.gitignore create mode 100644 regression_test/basicStatem/Makefile create mode 100644 regression_test/basicStatem/TbasicStatem.ttcn create mode 100644 regression_test/basicStatem/config.cfg create mode 100644 regression_test/bitstrOper/.gitignore create mode 100644 regression_test/bitstrOper/Makefile create mode 100644 regression_test/bitstrOper/TbitstrOper.ttcn create mode 100644 regression_test/bitstrOper/config.cfg create mode 100644 regression_test/boolOper/.gitignore create mode 100644 regression_test/boolOper/Makefile create mode 100644 regression_test/boolOper/TboolOper.ttcn create mode 100644 regression_test/boolOper/config.cfg create mode 100644 regression_test/cfgFile/Makefile create mode 100644 regression_test/cfgFile/define/Makefile create mode 100644 regression_test/cfgFile/define/macro_reference/.gitignore create mode 100644 regression_test/cfgFile/define/macro_reference/Makefile create mode 100644 regression_test/cfgFile/define/macro_reference/TSTM_macro_test_main.cfg create mode 100644 regression_test/cfgFile/define/macro_reference/TSTM_macro_test_testcases.ttcn create mode 100644 regression_test/cfgFile/define/structured/.gitignore create mode 100644 regression_test/cfgFile/define/structured/Makefile create mode 100644 regression_test/cfgFile/define/structured/structured.cfg create mode 100644 regression_test/cfgFile/define/structured/structured.ttcn create mode 100644 regression_test/cfgFile/module_parameters/Makefile create mode 100644 regression_test/cfgFile/module_parameters/assignment/.gitignore create mode 100644 regression_test/cfgFile/module_parameters/assignment/Makefile create mode 100644 regression_test/cfgFile/module_parameters/assignment/assignment.cfg create mode 100644 regression_test/cfgFile/module_parameters/assignment/assignment.ttcn create mode 100644 regression_test/cfgFile/module_parameters/concat/.gitignore create mode 100644 regression_test/cfgFile/module_parameters/concat/Makefile create mode 100644 regression_test/cfgFile/module_parameters/concat/concat.cfg create mode 100644 regression_test/cfgFile/module_parameters/concat/concat.ttcn create mode 100644 regression_test/cfgFile/ordered_include/.gitignore create mode 100644 regression_test/cfgFile/ordered_include/Makefile create mode 100644 regression_test/cfgFile/ordered_include/config_sub2/oi2_sub.cfg create mode 100644 regression_test/cfgFile/ordered_include/configs_sub/oi1_subfolder1.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi.ttcn create mode 100644 regression_test/cfgFile/ordered_include/oi1.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi1_after1.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi1_after2.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi1_after3.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi1_before1.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi1_before2.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi1_before_include.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi2.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi22.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi23.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi2_nomacro.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_after1.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_after2.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_after_list1.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_after_list2.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_before1.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_before2.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_before3.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_before4.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_before5.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_include_interference.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_include_mix.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_last1.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_last2.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_last3.cfg create mode 100644 regression_test/cfgFile/ordered_include/oi_subfolder1.cfg create mode 100644 regression_test/cfgFile/testport_parameters/Makefile create mode 100644 regression_test/cfgFile/testport_parameters/PCOType.cc create mode 100644 regression_test/cfgFile/testport_parameters/PCOType.hh create mode 100644 regression_test/cfgFile/testport_parameters/array_index.cfg create mode 100644 regression_test/cfgFile/testport_parameters/array_index.ttcn create mode 100644 regression_test/cfg_list_concat/.gitignore create mode 100644 regression_test/cfg_list_concat/Makefile create mode 100644 regression_test/cfg_list_concat/concat.prj create mode 100644 regression_test/cfg_list_concat/concat.ttcn create mode 100644 regression_test/cfg_list_concat/everything.cfg create mode 100644 regression_test/cfg_list_concat/sub1.cfg create mode 100644 regression_test/cfg_list_concat/sub2.cfg create mode 100644 regression_test/charOper/.gitignore create mode 100644 regression_test/charOper/Makefile create mode 100644 regression_test/charOper/TcharOper.ttcn create mode 100644 regression_test/charOper/config.cfg create mode 100644 regression_test/charstrOper/.gitignore create mode 100644 regression_test/charstrOper/Makefile create mode 100644 regression_test/charstrOper/TcharstrOper.ttcn create mode 100644 regression_test/charstrOper/config.cfg create mode 100644 regression_test/commMessage/.gitignore create mode 100644 regression_test/commMessage/HS41022.ttcn create mode 100644 regression_test/commMessage/ImplMsgEncData.asn create mode 100644 regression_test/commMessage/Makefile create mode 100644 regression_test/commMessage/TcommMessage.ttcn create mode 100644 regression_test/commMessage/config.cfg create mode 100644 regression_test/commMessage/config_parallel.cfg create mode 100644 regression_test/commProcedure/.gitignore create mode 100644 regression_test/commProcedure/ExtProcPort.cc create mode 100644 regression_test/commProcedure/ExtProcPort.hh create mode 100644 regression_test/commProcedure/Makefile create mode 100644 regression_test/commProcedure/PortAddress.cc create mode 100644 regression_test/commProcedure/PortAddress.hh create mode 100644 regression_test/commProcedure/ProcPort.ttcn create mode 100644 regression_test/compileonly/.gitignore create mode 100644 regression_test/compileonly/Makefile create mode 100644 regression_test/compileonly/assignmentNotation/.gitignore create mode 100644 regression_test/compileonly/assignmentNotation/Makefile create mode 100644 regression_test/compileonly/assignmentNotation/TassignmentNotation.ttcn create mode 100644 regression_test/compileonly/attribQualif/.gitignore create mode 100644 regression_test/compileonly/attribQualif/Makefile create mode 100644 regression_test/compileonly/attribQualif/TattribQualif.ttcn create mode 100644 regression_test/compileonly/centralstorage/.gitignore create mode 100644 regression_test/compileonly/centralstorage/Makefile create mode 100644 regression_test/compileonly/centralstorage/base_asn/.gitignore create mode 100644 regression_test/compileonly/centralstorage/base_asn/Base_asn.asn create mode 100644 regression_test/compileonly/centralstorage/base_mixed/.gitignore create mode 100644 regression_test/compileonly/centralstorage/base_mixed/Base_mixed_asn.asn create mode 100644 regression_test/compileonly/centralstorage/base_mixed/base_mixed_PT.cc create mode 100644 regression_test/compileonly/centralstorage/base_mixed/base_mixed_PT.hh create mode 100644 regression_test/compileonly/centralstorage/base_mixed/base_mixed_ttcn.ttcn create mode 100644 regression_test/compileonly/centralstorage/base_mixed/base_mixed_ttcnpp.ttcnpp create mode 100644 regression_test/compileonly/centralstorage/base_ttcn/.gitignore create mode 100644 regression_test/compileonly/centralstorage/base_ttcn/base_PT.cc create mode 100644 regression_test/compileonly/centralstorage/base_ttcn/base_PT.hh create mode 100644 regression_test/compileonly/centralstorage/base_ttcn/base_ttcn.ttcnpp create mode 100644 regression_test/compileonly/centralstorage/extended_ttcn/.gitignore create mode 100644 regression_test/compileonly/centralstorage/extended_ttcn/extended_ttcn.ttcn create mode 100644 regression_test/compileonly/centralstorage/extended_ttcn/extended_ttcnpp.ttcnpp create mode 100644 regression_test/compileonly/centralstorage/separate_project/.gitignore create mode 100644 regression_test/compileonly/centralstorage/separate_user/.gitignore create mode 100644 regression_test/compileonly/centralstorage/separate_user/config.cfg create mode 100644 regression_test/compileonly/centralstorage/separate_user/separate_user.ttcn create mode 100644 regression_test/compileonly/centralstorage/user_all_bases/.gitignore create mode 100644 regression_test/compileonly/centralstorage/user_all_bases/user_all_bases.ttcn create mode 100644 regression_test/compileonly/centralstorage/user_ttcn/.gitignore create mode 100644 regression_test/compileonly/centralstorage/user_ttcn/fake.ttcnpp create mode 100644 regression_test/compileonly/centralstorage/user_ttcn/user_ttcn.ttcn create mode 100644 regression_test/compileonly/circularImport/.gitignore create mode 100644 regression_test/compileonly/circularImport/A.asn create mode 100644 regression_test/compileonly/circularImport/B.asn create mode 100644 regression_test/compileonly/circularImport/Makefile create mode 100644 regression_test/compileonly/compareImported/.gitignore create mode 100644 regression_test/compileonly/compareImported/A.ttcn create mode 100644 regression_test/compileonly/compareImported/B.ttcn create mode 100644 regression_test/compileonly/compareImported/C.ttcn create mode 100644 regression_test/compileonly/compareImported/Makefile create mode 100644 regression_test/compileonly/compoundif/.gitignore create mode 100644 regression_test/compileonly/compoundif/Makefile create mode 100644 regression_test/compileonly/compoundif/Tcompoundif.ttcn create mode 100644 regression_test/compileonly/dynamicTemplate/.gitignore create mode 100644 regression_test/compileonly/dynamicTemplate/DynamicTemplate.ttcn create mode 100644 regression_test/compileonly/dynamicTemplate/Makefile create mode 100644 regression_test/compileonly/dynamicTemplate/TD_Dynamic_Templates.doc create mode 100644 regression_test/compileonly/dynamicTemplate/external.cc create mode 100644 regression_test/compileonly/isbound/.gitignore create mode 100644 regression_test/compileonly/isbound/Makefile create mode 100644 regression_test/compileonly/isbound/bad_SE.ttcn create mode 100644 regression_test/compileonly/isbound/bogus_SY.ttcn create mode 100644 regression_test/compileonly/isbound/isbound_component_OK.ttcn create mode 100644 regression_test/compileonly/isbound/isbound_port_SE.ttcn create mode 100644 regression_test/compileonly/isbound/isbound_testcase_SE.ttcn create mode 100644 regression_test/compileonly/isbound/one_OK.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/COMMON/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/COMMON/ProtocolModules_Common.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/COMMON/src/General_Types.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/COMMON/src/MobileDomainDefinitions.asn create mode 100644 regression_test/compileonly/mfgen-tpd/HP79745/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/HP79745/Hello000/Hello000.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/HP79745/Hello000/src/MyExample0.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/HP79745/Hello123/Hello123.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/HP79745/Hello123/src/MyExample1.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/HP79745/HelloTpd/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/HP79745/HelloTpd/.project create mode 100644 regression_test/compileonly/mfgen-tpd/HP79745/HelloTpd/HelloTpd.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/HP79745/HelloTpd/src/MyExample.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/HP79745/Makefile create mode 100644 regression_test/compileonly/mfgen-tpd/HQ56829/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/HQ56829/Makefile create mode 100644 regression_test/compileonly/mfgen-tpd/HQ56834/Makefile create mode 100644 regression_test/compileonly/mfgen-tpd/HQ56834/bin/.gitignore create mode 100755 regression_test/compileonly/mfgen-tpd/HQ56834/bin/emptyfolder create mode 100644 regression_test/compileonly/mfgen-tpd/HQ56834/counter.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/HQ56834/src/counter.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/HQ56848/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/HQ56848/Makefile create mode 100644 regression_test/compileonly/mfgen-tpd/HQ56848/counter.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/HQ60308/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/HQ60308/counter.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/HR30356/Makefile create mode 100755 regression_test/compileonly/mfgen-tpd/HR30356/client/client.tpd create mode 100755 regression_test/compileonly/mfgen-tpd/HR30356/client/src/client.ttcn create mode 100755 regression_test/compileonly/mfgen-tpd/HR30356/controller/controller.tpd create mode 100755 regression_test/compileonly/mfgen-tpd/HR30356/controller/src/controller.ttcn create mode 100755 regression_test/compileonly/mfgen-tpd/HR30356/server/server.tpd create mode 100755 regression_test/compileonly/mfgen-tpd/HR30356/server/src/server.ttcn create mode 100755 regression_test/compileonly/mfgen-tpd/HR30356/testport/src/testport.ttcn create mode 100755 regression_test/compileonly/mfgen-tpd/HR30356/testport/testport.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/HR30365/Hello000/Hello000.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/HR30365/Hello000/src/MyExample0.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/HR30365/Hello123/Hello123.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/HR30365/Hello123/src/MyExample1.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/HR30365/HelloTpd/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/HR30365/HelloTpd/HelloTpd.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/HR30365/HelloTpd/src/MyExample.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/HR30365/Makefile create mode 100644 regression_test/compileonly/mfgen-tpd/Makefile create mode 100644 regression_test/compileonly/mfgen-tpd/NAS_EPS_v9.7.0_CNL113729/NAS_EPS_v9.7.0_CNL113729.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/NAS_EPS_v9.7.0_CNL113729/src/NAS_EPS_v970.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/NAS_EPS_v9.7.0_CNL113729/test/NAS_EPS_Test.cfg create mode 100644 regression_test/compileonly/mfgen-tpd/NAS_EPS_v9.7.0_CNL113729/test/NAS_EPS_Test.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/NAS_EPS_v9.7.0_CNL113729/test/NAS_EPS_v9.7.0_CNL113729_test.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/buildconfig_param/HelloTpd/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/buildconfig_param/HelloTpd/.project create mode 100644 regression_test/compileonly/mfgen-tpd/buildconfig_param/HelloTpd/HelloTpd.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/buildconfig_param/HelloTpd/src/MyExample.cfg create mode 100644 regression_test/compileonly/mfgen-tpd/buildconfig_param/HelloTpd/src/MyExample.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/buildconfig_param/HelloTpd/src/PCOType.cc create mode 100644 regression_test/compileonly/mfgen-tpd/buildconfig_param/HelloTpd/src/PCOType.hh create mode 100644 regression_test/compileonly/mfgen-tpd/buildconfig_param/Makefile create mode 100644 regression_test/compileonly/mfgen-tpd/consumer/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/consumer/.project create mode 100644 regression_test/compileonly/mfgen-tpd/consumer/consumer-ref-supplier-Default.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/consumer/creator.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/consumer/src/consumer.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/consumer/src/userfun.cc create mode 100644 regression_test/compileonly/mfgen-tpd/dependency_check/Makefile create mode 100755 regression_test/compileonly/mfgen-tpd/dependency_check/client/client.tpd create mode 100755 regression_test/compileonly/mfgen-tpd/dependency_check/client/src/client.ttcn create mode 100755 regression_test/compileonly/mfgen-tpd/dependency_check/controller/controller.tpd create mode 100755 regression_test/compileonly/mfgen-tpd/dependency_check/controller/src/controller.ttcn create mode 100755 regression_test/compileonly/mfgen-tpd/dependency_check/server/server.tpd create mode 100755 regression_test/compileonly/mfgen-tpd/dependency_check/server/src/server.ttcn create mode 100755 regression_test/compileonly/mfgen-tpd/dependency_check/testport/src/testport.ttcn create mode 100755 regression_test/compileonly/mfgen-tpd/dependency_check/testport/testport.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/flagTest/Hello000/Hello000.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/flagTest/Hello000/src/MyExample0.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/flagTest/Hello123/Hello123.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/flagTest/Hello123/src/MyExample1.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/flagTest/HelloTpd/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/flagTest/HelloTpd/HelloTpd.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/flagTest/HelloTpd/src/MyExample.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/flagTest/HelloTpd2/HelloTpd2.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/flagTest/HelloTpd2/src/MyExample2.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/flagTest/Makefile create mode 100644 regression_test/compileonly/mfgen-tpd/handmade.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/HelloTpd/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/HelloTpd/.project create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/HelloTpd/HelloTpd.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/HelloTpd/src/MyExample.cfg create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/HelloTpd/src/MyExample.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/HelloTpd/src/PCOType.cc create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/HelloTpd/src/PCOType.hh create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_param/Makefile create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/Hello000/Hello000.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/Hello000/src/MyExample0.cfg create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/Hello000/src/MyExample0.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/Hello000/src/PCOType0.cc create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/Hello000/src/PCOType0.hh create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/Hello123/Hello123.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/Hello123/src/MyExample1.cfg create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/Hello123/src/MyExample1.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/Hello123/src/PCOType1.cc create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/Hello123/src/PCOType1.hh create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/HelloTpd/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/HelloTpd/.project create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/HelloTpd/HelloTpd.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/HelloTpd/src/MyExample.cfg create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/HelloTpd/src/MyExample.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/HelloTpd/src/PCOType.cc create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/HelloTpd/src/PCOType.hh create mode 100644 regression_test/compileonly/mfgen-tpd/invalid_buildconfig_tpd/Makefile create mode 100644 regression_test/compileonly/mfgen-tpd/library/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/library/HelloTpd/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/library/HelloTpd/.project create mode 100644 regression_test/compileonly/mfgen-tpd/library/HelloTpd/HelloTpd.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/library/HelloTpd/src/MyExample.cfg create mode 100644 regression_test/compileonly/mfgen-tpd/library/HelloTpd/src/MyExample.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/library/HelloTpd/src/PCOType.cc create mode 100644 regression_test/compileonly/mfgen-tpd/library/HelloTpd/src/PCOType.hh create mode 100644 regression_test/compileonly/mfgen-tpd/library/HelloTpd2/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/library/HelloTpd2/HelloTpd.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/library/Makefile create mode 100644 regression_test/compileonly/mfgen-tpd/library/a.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/library/b.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/library/central_storage/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/library/central_storage/central.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/outsider.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/runner.pl create mode 100644 regression_test/compileonly/mfgen-tpd/subplier/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/subplier/.project create mode 100644 regression_test/compileonly/mfgen-tpd/subplier/src/subway.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/subplier/subplier.tpd create mode 100644 regression_test/compileonly/mfgen-tpd/supplier/.gitignore create mode 100644 regression_test/compileonly/mfgen-tpd/supplier/.project create mode 100644 regression_test/compileonly/mfgen-tpd/supplier/src/supplier.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/supplier/src/supplier2.ttcn create mode 100644 regression_test/compileonly/mfgen-tpd/supplier/supplier24.tpd create mode 100644 regression_test/compileonly/namedActualParameters/.gitignore create mode 100644 regression_test/compileonly/namedActualParameters/Makefile create mode 100644 regression_test/compileonly/namedActualParameters/TnamedActualParameters.ttcn create mode 100644 regression_test/compileonly/openType/.gitignore create mode 100644 regression_test/compileonly/openType/Makefile create mode 100644 regression_test/compileonly/openType/X.asn create mode 100644 regression_test/compileonly/optionalAssignCompare/.gitignore create mode 100644 regression_test/compileonly/optionalAssignCompare/Makefile create mode 100644 regression_test/compileonly/optionalAssignCompare/ToptionalAssignCompare.ttcn create mode 100644 regression_test/compileonly/portConstructor/.gitignore create mode 100644 regression_test/compileonly/portConstructor/Makefile create mode 100644 regression_test/compileonly/portConstructor/x.ttcn create mode 100644 regression_test/compileonly/styleGuide/.gitignore create mode 100644 regression_test/compileonly/styleGuide/Another_module.ttcn create mode 100644 regression_test/compileonly/styleGuide/Makefile create mode 100644 regression_test/compileonly/styleGuide/MyASN1_module.asn create mode 100644 regression_test/compileonly/styleGuide/MySample_module.ttcn create mode 100644 regression_test/compileonly/styleGuide/external.cc create mode 100644 regression_test/compileonly/topLevelPdu/.gitignore create mode 100644 regression_test/compileonly/topLevelPdu/A.asn create mode 100644 regression_test/compileonly/topLevelPdu/B.asn create mode 100644 regression_test/compileonly/topLevelPdu/Makefile create mode 100644 regression_test/compileonly/typeInstantiation/.gitignore create mode 100644 regression_test/compileonly/typeInstantiation/A.asn create mode 100644 regression_test/compileonly/typeInstantiation/B.asn create mode 100644 regression_test/compileonly/typeInstantiation/Makefile create mode 100644 regression_test/configOper/.gitignore create mode 100644 regression_test/configOper/Makefile create mode 100644 regression_test/configOper/TconfigOper.ttcn create mode 100644 regression_test/controlTimer/.gitignore create mode 100644 regression_test/controlTimer/Makefile create mode 100644 regression_test/controlTimer/TcontrolTimer.ttcn create mode 100644 regression_test/controlTimer/config.cfg create mode 100644 regression_test/defaultOper/Makefile create mode 100644 regression_test/defaultOper/TdefaultOper.ttcn create mode 100644 regression_test/defaultOper/config.cfg create mode 100644 regression_test/enumOper/.gitignore create mode 100644 regression_test/enumOper/Makefile create mode 100644 regression_test/enumOper/TenumOper.ttcn create mode 100644 regression_test/enumOper/config.cfg create mode 100644 regression_test/floatOper/.gitignore create mode 100644 regression_test/floatOper/Makefile create mode 100644 regression_test/floatOper/TfloatOper.ttcn create mode 100644 regression_test/floatOper/config.cfg create mode 100644 regression_test/functionReference/.gitignore create mode 100644 regression_test/functionReference/FuncRef.ttcn create mode 100644 regression_test/functionReference/Makefile create mode 100644 regression_test/functionReference/config.cfg create mode 100644 regression_test/hexstrOper/.gitignore create mode 100644 regression_test/hexstrOper/Makefile create mode 100644 regression_test/hexstrOper/ThexstrOper.ttcn create mode 100644 regression_test/hexstrOper/config.cfg create mode 100644 regression_test/iconv/.gitignore create mode 100644 regression_test/iconv/Makefile create mode 100644 regression_test/iconv/config.cfg create mode 100644 regression_test/iconv/converter.ttcn create mode 100644 regression_test/iconv/convertest.ttcn create mode 100644 regression_test/iconv/iconver.cc create mode 100644 regression_test/implicitMsgEncoding/.gitignore create mode 100644 regression_test/implicitMsgEncoding/Makefile create mode 100644 regression_test/implicitMsgEncoding/PCOType.cc create mode 100644 regression_test/implicitMsgEncoding/PCOType.hh create mode 100644 regression_test/implicitMsgEncoding/TimplicitEnc.ttcn create mode 100644 regression_test/implicitMsgEncoding/config.cfg create mode 100644 regression_test/implicitOmit/.gitignore create mode 100644 regression_test/implicitOmit/Makefile create mode 100644 regression_test/implicitOmit/config.cfg create mode 100644 regression_test/implicitOmit/io.ttcn create mode 100644 regression_test/intOper/.gitignore create mode 100644 regression_test/intOper/Makefile create mode 100644 regression_test/intOper/PCOType.cc create mode 100644 regression_test/intOper/PCOType.hh create mode 100644 regression_test/intOper/TintOper.ttcn create mode 100644 regression_test/intOper/config.cfg create mode 100644 regression_test/ipv6/.gitignore create mode 100644 regression_test/ipv6/Makefile create mode 100644 regression_test/ipv6/host_ipv6_global.cfg create mode 100644 regression_test/ipv6/host_link_local.cfg create mode 100644 regression_test/ipv6/invalid_global_ipv6.cfg create mode 100644 regression_test/ipv6/invalid_global_ipv6_long.cfg create mode 100644 regression_test/ipv6/ip_create_on_host.cfg create mode 100644 regression_test/ipv6/ipv6.ttcn create mode 100644 regression_test/ipv6/ipv6_all_global.cfg create mode 100644 regression_test/ipv6/ipv6_long_short_global.cfg create mode 100644 regression_test/ipv6/ipv_hostname_macro.cfg create mode 100644 regression_test/ipv6/link_local_ipv6.cfg create mode 100644 regression_test/ipv6/localhost_create_on_host.cfg create mode 100644 regression_test/ipv6/localhost_ip_create_on_host.cfg create mode 100644 regression_test/ipv6/long_host_ipv6_global.cfg create mode 100644 regression_test/ipv6/long_ipv6_global.cfg create mode 100644 regression_test/ipv6/no_full_syntax_check_link_local.cfg create mode 100644 regression_test/ipv6/no_full_syntax_check_link_local_long.cfg create mode 100755 regression_test/ipv6/platformcheck create mode 100644 regression_test/ipv6/total_link_local.cfg create mode 100644 regression_test/ipv6/valid_global_ipv6.cfg create mode 100644 regression_test/ispresent/IsPresent_Test.cfg create mode 100644 regression_test/ispresent/IsPresent_Test.ttcn create mode 100644 regression_test/ispresent/Makefile create mode 100755 regression_test/json/AttributeTestcases.ttcn create mode 100755 regression_test/json/Functions.ttcn create mode 100755 regression_test/json/JSON.cfg create mode 100644 regression_test/json/JsonData.asn create mode 100755 regression_test/json/Makefile create mode 100644 regression_test/json/SemanticCheck.ttcn create mode 100755 regression_test/json/Testcases.ttcn create mode 100755 regression_test/json/Types.ttcn create mode 100644 regression_test/junitlogger/Makefile create mode 100644 regression_test/junitlogger/main1.cfg create mode 100644 regression_test/junitlogger/main1.ttcn create mode 100755 regression_test/junitlogger/test_junitlog.pl create mode 100755 regression_test/junitlogger/test_junitlog.sh create mode 100644 regression_test/lazyEval/LazyASNTypes.asn create mode 100644 regression_test/lazyEval/Makefile create mode 100644 regression_test/lazyEval/lazy.cfg create mode 100644 regression_test/lazyEval/lazy_A.ttcn create mode 100644 regression_test/lazyEval/lazy_B.ttcn create mode 100644 regression_test/lazyEval/lazy_defs.ttcn create mode 100644 regression_test/lazyEval/lazy_main.ttcn create mode 100755 regression_test/logFiles/.gitignore create mode 100644 regression_test/logFiles/CommonStuff.ttcn create mode 100755 regression_test/logFiles/LogFiles.cfg create mode 100755 regression_test/logFiles/LogFiles.ttcn create mode 100755 regression_test/logFiles/LogFiles2.cfg create mode 100755 regression_test/logFiles/LogFilesInc.cfg create mode 100755 regression_test/logFiles/LogFilesProc.cfg create mode 100755 regression_test/logFiles/Makefile create mode 100644 regression_test/logFiles/TitanLogTest.cfg create mode 100644 regression_test/logFiles/TitanLogTest.ttcn create mode 100755 regression_test/logFiles/diffLogs create mode 100755 regression_test/logFiles/extfunc.cc create mode 100755 regression_test/logFiles/logFiles_doc.script create mode 100644 regression_test/logger/Makefile create mode 100644 regression_test/logger/emergency_logging/Console_N.txt create mode 100644 regression_test/logger/emergency_logging/Console_O.txt create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_1.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_10.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_10_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_11.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_11_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_12.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_12_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_13.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_13_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_1_NOEL.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_2.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_3.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_3_NOEL.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_4.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_5.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_6.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_7.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_7A.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_7A_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_7_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_8.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_9.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferAll_9_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_1.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_10.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_10_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_10_mtc_expected.log_emergency create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_11.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_11_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_11_mtc_expected.log_emergency create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_12.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_12_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_12_mtc_expected.log_emergency create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_13.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_13_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_13_mtc_expected.log_emergency create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_2.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_3.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_4.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_5.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_6.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_7.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_7_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_7_mtc_expected.log_emergency create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_8.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_9.cfg create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_9_mtc_expected.log create mode 100644 regression_test/logger/emergency_logging/EL_BufferMasked_9_mtc_expected.log_emergency create mode 100755 regression_test/logger/emergency_logging/EmergencyLogTest.sh create mode 100644 regression_test/logger/emergency_logging/EmergencyLoggingTest.ttcn create mode 100644 regression_test/logger/emergency_logging/EmergencyLoggingTest_BuffMasked.cfg create mode 100644 regression_test/logger/emergency_logging/Makefile create mode 100644 regression_test/logger/emergency_logging/PCO_PT.cc create mode 100644 regression_test/logger/emergency_logging/PCO_PT.hh create mode 100644 regression_test/logger/emergency_logging/Titan_LogTest.ttcn create mode 100644 regression_test/logger/emergency_logging/Titan_LogTestDefinitions.ttcn create mode 100644 regression_test/logger/emergency_logging/failed_testcases.txt create mode 100644 regression_test/logger/emergency_logging/runlog.txt create mode 100644 regression_test/logger/logcontrol/Makefile create mode 100644 regression_test/logger/logcontrol/Titan_LogControlTest.cfg create mode 100644 regression_test/logger/logcontrol/Titan_LogControlTest.ttcn create mode 100644 regression_test/logger/logtest/Console_original_merged_log.txt create mode 100644 regression_test/logger/logtest/Makefile create mode 100644 regression_test/logger/logtest/PCO_PT.cc create mode 100644 regression_test/logger/logtest/PCO_PT.hh create mode 100644 regression_test/logger/logtest/Titan_LogTest.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest.ttcn create mode 100644 regression_test/logger/logtest/Titan_LogTestDefinitions.ttcn create mode 100644 regression_test/logger/logtest/Titan_LogTest_ACTION.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_ACTIONplusEXECUTOR_RT.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_DEBUG.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_DEFAULT_OPplusEXECUTOR_RT.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_ERRORplusRT.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_EXECUTOR_LOGOPT.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_EXECUTOR_RTplusCOMP.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_EXECUTOR_RTplusLOGOPT.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_EXEC_RT.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_EX_UNQUAL.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_E_RTplus_E_CONFIGDATA.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_FUNC.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_MATCH.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_PARALLEL.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_PORTEVENT.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_STAT.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_TC.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_TIMER.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_TTCN_ACTION.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_USER.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_VERDICT.cfg create mode 100644 regression_test/logger/logtest/Titan_LogTest_WARNING.cfg create mode 100755 regression_test/logger/logtest/logtest.sh create mode 100644 regression_test/logger/logtest/original_merged_log.txt create mode 100644 regression_test/logger/logtest/original_merged_log_modified.txt create mode 100644 regression_test/logger_control/.gitignore create mode 100644 regression_test/logger_control/Makefile create mode 100644 regression_test/logger_control/config.cfg create mode 100644 regression_test/logger_control/logcontrol.ttcn create mode 100755 regression_test/logger_control/logfilecheck create mode 100644 regression_test/loggerplugin/.gitignore create mode 100644 regression_test/loggerplugin/Makefile create mode 100644 regression_test/loggerplugin/a.ttcn create mode 100644 regression_test/loggerplugin/config.cfg create mode 100644 regression_test/lostTimer/.gitignore create mode 100644 regression_test/lostTimer/Makefile create mode 100644 regression_test/lostTimer/TlostTimer.ttcn create mode 100644 regression_test/lostTimer/config.cfg create mode 100644 regression_test/macros/.gitignore create mode 100644 regression_test/macros/Macros.ttcn create mode 100644 regression_test/macros/Makefile create mode 100644 regression_test/macros/config.cfg create mode 100644 regression_test/modifiedTemplate/.gitignore create mode 100644 regression_test/modifiedTemplate/Makefile create mode 100644 regression_test/modifiedTemplate/TmodifiedTemplate.ttcn create mode 100644 regression_test/modifiedTemplate/config.cfg create mode 100644 regression_test/namedActualParameters/.gitignore create mode 100644 regression_test/namedActualParameters/Makefile create mode 100644 regression_test/namedActualParameters/config.cfg create mode 100644 regression_test/namedActualParameters/inlinetemplate.ttcn create mode 100644 regression_test/namedActualParameters/namedparam.ttcn create mode 100644 regression_test/namedActualParameters/small.ttcn create mode 100644 regression_test/namedActualParameters/templates.ttcn create mode 100755 regression_test/negativeTest/.gitignore create mode 100755 regression_test/negativeTest/Makefile create mode 100644 regression_test/negativeTest/NegTest.cfg create mode 100644 regression_test/negativeTest/NegTestTestcases.ttcn create mode 100644 regression_test/negativeTest/NegTestTypes.asn create mode 100644 regression_test/negativeTest/NegTest_RAW.cfg create mode 100644 regression_test/negativeTest/NegTest_RAW_Testcases.ttcn create mode 100644 regression_test/negativeTest/NegTest_RAW_Types.ttcn create mode 100644 regression_test/negativeTest/NegTest_TEXT.cfg create mode 100644 regression_test/negativeTest/NegTest_TEXT_Testcases.ttcn create mode 100644 regression_test/negativeTest/NegTest_TEXT_Types.ttcn create mode 100644 regression_test/negativeTest/NegTest_XML.cfg create mode 100644 regression_test/negativeTest/NegTest_XML_Testcases.ttcn create mode 100644 regression_test/negativeTest/NegTest_XML_Types.xsd create mode 100644 regression_test/negativeTest/NegTest_all.cfg create mode 100755 regression_test/negativeTest/Types.asn create mode 100644 regression_test/negativeTest/UsefulTtcn3Types.ttcn create mode 100644 regression_test/negativeTest/XSD.ttcn create mode 100755 regression_test/negativeTest/config.cfg create mode 100755 regression_test/negativeTest/negtest.ttcn create mode 100644 regression_test/negativeTest/www_XmlTest_org_negativeTest_XML_Types.ttcn create mode 100644 regression_test/nonMandatoryPar/.gitignore create mode 100644 regression_test/nonMandatoryPar/Makefile create mode 100644 regression_test/nonMandatoryPar/TnonMandatory.ttcn create mode 100644 regression_test/nonMandatoryPar/config.cfg create mode 100644 regression_test/objidOper/.gitignore create mode 100644 regression_test/objidOper/Makefile create mode 100644 regression_test/objidOper/TobjidOper.ttcn create mode 100644 regression_test/objidOper/config.cfg create mode 100644 regression_test/objidOper/indexer.cc create mode 100644 regression_test/octetstrOper/.gitignore create mode 100644 regression_test/octetstrOper/Makefile create mode 100644 regression_test/octetstrOper/ToctetstrOper.ttcn create mode 100644 regression_test/octetstrOper/config.cfg create mode 100644 regression_test/omitdef/.gitignore create mode 100644 regression_test/omitdef/Datatypes.asn create mode 100644 regression_test/omitdef/Dumping.hh create mode 100644 regression_test/omitdef/Makefile create mode 100644 regression_test/omitdef/PT_DefOpt.cc create mode 100644 regression_test/omitdef/PT_DefOpt.hh create mode 100644 regression_test/omitdef/Tsenderos.ttcn create mode 100644 regression_test/omitdef/config.cfg create mode 100644 regression_test/pattern_quadruples/.gitignore create mode 100644 regression_test/pattern_quadruples/Makefile create mode 100644 regression_test/pattern_quadruples/config.cfg create mode 100644 regression_test/pattern_quadruples/pattern_quadruples.ttcn create mode 100644 regression_test/post_commit_test create mode 100644 regression_test/preCompilerFlags/.gitignore create mode 100644 regression_test/preCompilerFlags/Makefile create mode 100755 regression_test/preCompilerFlags/TpreCompilerFlags.ttcnpp create mode 100755 regression_test/preCompilerFlags/config.cfg create mode 100755 regression_test/preCompilerFlags/test_include.inc create mode 100755 regression_test/preCompilerFlags/test_macro.inc create mode 100644 regression_test/predefFunction/.gitignore create mode 100644 regression_test/predefFunction/Makefile create mode 100644 regression_test/predefFunction/PreDef.cfg create mode 100644 regression_test/predefFunction/bit_to_OK.ttcn create mode 100644 regression_test/predefFunction/bit_to_SW.ttcn create mode 100644 regression_test/predefFunction/char_to_OK.ttcn create mode 100644 regression_test/predefFunction/char_to_SW.ttcn create mode 100644 regression_test/predefFunction/encdec_OK.ttcn create mode 100644 regression_test/predefFunction/enum_to_OK.ttcn create mode 100644 regression_test/predefFunction/enum_to_SW.ttcn create mode 100644 regression_test/predefFunction/float_to_OK.ttcn create mode 100644 regression_test/predefFunction/float_to_SW.ttcn create mode 100644 regression_test/predefFunction/hex_to_OK.ttcn create mode 100644 regression_test/predefFunction/hex_to_SW.ttcn create mode 100644 regression_test/predefFunction/int_to_OK.ttcn create mode 100644 regression_test/predefFunction/int_to_SW.ttcn create mode 100644 regression_test/predefFunction/isprecho_OK.ttcn create mode 100644 regression_test/predefFunction/length_of_OK.ttcn create mode 100644 regression_test/predefFunction/length_of_SW.ttcn create mode 100644 regression_test/predefFunction/oct_to_OK.ttcn create mode 100644 regression_test/predefFunction/oct_to_SW.ttcn create mode 100644 regression_test/predefFunction/regex_OK.ttcn create mode 100644 regression_test/predefFunction/replacer_OK.ttcn create mode 100644 regression_test/predefFunction/replacer_SW.ttcn create mode 100644 regression_test/predefFunction/rotter_OK.ttcn create mode 100644 regression_test/predefFunction/rotter_SW.ttcn create mode 100644 regression_test/predefFunction/shifty_OK.ttcn create mode 100644 regression_test/predefFunction/shifty_SW.ttcn create mode 100644 regression_test/predefFunction/size_of_OK.ttcn create mode 100644 regression_test/predefFunction/size_of_SW.ttcn create mode 100644 regression_test/predefFunction/str_to_OK.ttcn create mode 100644 regression_test/predefFunction/str_to_SW.ttcn create mode 100644 regression_test/predefFunction/sub_str_OK.ttcn create mode 100644 regression_test/predefFunction/sub_str_SW.ttcn create mode 100644 regression_test/predefFunction/tcname_OK.ttcn create mode 100644 regression_test/predefFunction/tcname_SW.ttcn create mode 100755 regression_test/prereq.pl create mode 100644 regression_test/recofOper/.gitignore create mode 100644 regression_test/recofOper/BerType.asn create mode 100644 regression_test/recofOper/Makefile create mode 100644 regression_test/recofOper/TrecofOper.ttcn create mode 100644 regression_test/recofOper/TrecofParamRef.ttcn create mode 100644 regression_test/recofOper/config.cfg create mode 100644 regression_test/recordOper/.gitignore create mode 100644 regression_test/recordOper/Makefile create mode 100644 regression_test/recordOper/TrecordOper.ttcn create mode 100644 regression_test/recordOper/config.cfg create mode 100644 regression_test/setOper/.gitignore create mode 100644 regression_test/setOper/Makefile create mode 100644 regression_test/setOper/TsetOper.ttcn create mode 100644 regression_test/setOper/config.cfg create mode 100644 regression_test/setofMatch/.gitignore create mode 100644 regression_test/setofMatch/Makefile create mode 100644 regression_test/setofMatch/TsetofMatch.ttcn create mode 100644 regression_test/setofMatch/config.cfg create mode 100644 regression_test/setofOper/.gitignore create mode 100644 regression_test/setofOper/Makefile create mode 100644 regression_test/setofOper/TsetofOper.ttcn create mode 100644 regression_test/setofOper/config.cfg create mode 100644 regression_test/singlecontrol/.gitignore create mode 100644 regression_test/singlecontrol/Makefile create mode 100644 regression_test/singlecontrol/alsohascontrolpart.ttcn create mode 100644 regression_test/singlecontrol/config.cfg create mode 100644 regression_test/singlecontrol/config1.cfg create mode 100644 regression_test/singlecontrol/config2.cfg create mode 100644 regression_test/singlecontrol/config_noexec.cfg create mode 100644 regression_test/singlecontrol/hascontrolpart.ttcn create mode 100644 regression_test/singlecontrol/nocontrolpart.ttcn create mode 100644 regression_test/singlecontrol/ouch.cfg create mode 100644 regression_test/slider/.gitignore create mode 100644 regression_test/slider/Makefile create mode 100644 regression_test/slider/PT1.cc create mode 100644 regression_test/slider/PT1.hh create mode 100644 regression_test/slider/UNDER.cc create mode 100644 regression_test/slider/UNDER.hh create mode 100644 regression_test/slider/dual.ttcn create mode 100644 regression_test/slider/dual2.ttcn create mode 100644 regression_test/slider/dualnegtest.ttcn create mode 100644 regression_test/slider/run.cfg create mode 100644 regression_test/slider/slider.ttcn create mode 100644 regression_test/templateAnytype/.gitignore create mode 100644 regression_test/templateAnytype/Makefile create mode 100644 regression_test/templateAnytype/TtemplateAnytype.ttcn create mode 100644 regression_test/templateAnytype/config.cfg create mode 100644 regression_test/templateBitstr/.gitignore create mode 100644 regression_test/templateBitstr/Makefile create mode 100644 regression_test/templateBitstr/TtemplateBitstr.ttcn create mode 100644 regression_test/templateBitstr/config.cfg create mode 100644 regression_test/templateBool/.gitignore create mode 100644 regression_test/templateBool/Makefile create mode 100644 regression_test/templateBool/TtemplateBool.ttcn create mode 100644 regression_test/templateBool/config.cfg create mode 100644 regression_test/templateChar/.gitignore create mode 100644 regression_test/templateChar/Makefile create mode 100644 regression_test/templateChar/TtemplateChar.ttcn create mode 100644 regression_test/templateChar/config.cfg create mode 100644 regression_test/templateCharstr/.gitignore create mode 100644 regression_test/templateCharstr/Makefile create mode 100644 regression_test/templateCharstr/TtemplateCharstr.ttcn create mode 100644 regression_test/templateCharstr/config.cfg create mode 100644 regression_test/templateEnum/.gitignore create mode 100644 regression_test/templateEnum/Makefile create mode 100644 regression_test/templateEnum/TtemplateEnum.ttcn create mode 100644 regression_test/templateEnum/config.cfg create mode 100644 regression_test/templateFloat/.gitignore create mode 100644 regression_test/templateFloat/Makefile create mode 100644 regression_test/templateFloat/TtemplateFloat.ttcn create mode 100644 regression_test/templateFloat/config.cfg create mode 100644 regression_test/templateInt/.gitignore create mode 100644 regression_test/templateInt/Makefile create mode 100644 regression_test/templateInt/TtemplateInt.ttcn create mode 100644 regression_test/templateInt/config.cfg create mode 100644 regression_test/templateOctetstr/.gitignore create mode 100644 regression_test/templateOctetstr/Makefile create mode 100644 regression_test/templateOctetstr/TtemplateOctetstr.ttcn create mode 100644 regression_test/templateOctetstr/config.cfg create mode 100644 regression_test/templateRec/.gitignore create mode 100644 regression_test/templateRec/Makefile create mode 100644 regression_test/templateRec/TtemplateRec.ttcn create mode 100644 regression_test/templateRec/TtemplateRecAsn.asn create mode 100644 regression_test/templateRec/config.cfg create mode 100644 regression_test/templateRecof/.gitignore create mode 100644 regression_test/templateRecof/Makefile create mode 100644 regression_test/templateRecof/TmultiplePermutations.ttcn create mode 100644 regression_test/templateRecof/TtemplateRecof.ttcn create mode 100644 regression_test/templateRecof/config.cfg create mode 100644 regression_test/templateSet/.gitignore create mode 100644 regression_test/templateSet/Makefile create mode 100644 regression_test/templateSet/TtemplateSet.ttcn create mode 100644 regression_test/templateSet/config.cfg create mode 100644 regression_test/templateSetof/.gitignore create mode 100644 regression_test/templateSetof/Makefile create mode 100644 regression_test/templateSetof/TtemplateSetof.ttcn create mode 100644 regression_test/templateSetof/config.cfg create mode 100644 regression_test/templateUnion/.gitignore create mode 100644 regression_test/templateUnion/Makefile create mode 100644 regression_test/templateUnion/TtemplateUnion.ttcn create mode 100644 regression_test/templateUnion/config.cfg create mode 100644 regression_test/testcase_defparam/.gitignore create mode 100644 regression_test/testcase_defparam/Makefile create mode 100644 regression_test/testcase_defparam/config.cfg create mode 100644 regression_test/testcase_defparam/tcdefparam.ttcn create mode 100644 regression_test/text2ttcn/Makefile create mode 100755 regression_test/text2ttcn/array_test.ttcn create mode 100755 regression_test/text2ttcn/bitstring_test.ttcn create mode 100755 regression_test/text2ttcn/boolean_test.ttcn create mode 100755 regression_test/text2ttcn/charstring_test.ttcn create mode 100644 regression_test/text2ttcn/component_test.ttcn create mode 100755 regression_test/text2ttcn/enum_test.ttcn create mode 100755 regression_test/text2ttcn/float_test.ttcn create mode 100644 regression_test/text2ttcn/functions.ttcn create mode 100755 regression_test/text2ttcn/hexstring_test.ttcn create mode 100755 regression_test/text2ttcn/integer_test.ttcn create mode 100644 regression_test/text2ttcn/objid_test.ttcn create mode 100755 regression_test/text2ttcn/octetstring_test.ttcn create mode 100755 regression_test/text2ttcn/record_test.ttcn create mode 100755 regression_test/text2ttcn/recordof_test.ttcn create mode 100755 regression_test/text2ttcn/set_test.ttcn create mode 100755 regression_test/text2ttcn/setof_test.ttcn create mode 100644 regression_test/text2ttcn/text2ttcn_1.cfg create mode 100644 regression_test/text2ttcn/text2ttcn_2.cfg create mode 100644 regression_test/text2ttcn/types.ttcn create mode 100755 regression_test/text2ttcn/ucharstring_test.ttcn create mode 100755 regression_test/text2ttcn/union_test.ttcn create mode 100644 regression_test/transparent/.gitignore create mode 100644 regression_test/transparent/Makefile create mode 100644 regression_test/transparent/run.cfg create mode 100644 regression_test/transparent/transparent.ttcn create mode 100644 regression_test/tryCatch/.gitignore create mode 100644 regression_test/tryCatch/Makefile create mode 100644 regression_test/tryCatch/PCOType.cc create mode 100644 regression_test/tryCatch/PCOType.hh create mode 100644 regression_test/tryCatch/external_function.cc create mode 100644 regression_test/tryCatch/tryCatch.cfg create mode 100644 regression_test/tryCatch/tryCatch_Functions.ttcn create mode 100644 regression_test/tryCatch/tryCatch_Testcases.ttcn create mode 100644 regression_test/ttcn2json/General_Types.ttcn create mode 100644 regression_test/ttcn2json/General_Types_e.json create mode 100755 regression_test/ttcn2json/Makefile create mode 100644 regression_test/ttcn2json/PIPEasp_PT.cc create mode 100644 regression_test/ttcn2json/PIPEasp_PT.hh create mode 100644 regression_test/ttcn2json/PIPEasp_PortType.ttcn create mode 100644 regression_test/ttcn2json/PIPEasp_Templates.ttcn create mode 100644 regression_test/ttcn2json/PIPEasp_Types.ttcn create mode 100644 regression_test/ttcn2json/Shell.ttcn create mode 100644 regression_test/ttcn2json/Testcases.ttcn create mode 100644 regression_test/ttcn2json/one.ttcn create mode 100644 regression_test/ttcn2json/one_e.json create mode 100644 regression_test/ttcn2json/three.ttcn create mode 100644 regression_test/ttcn2json/two.ttcn create mode 100644 regression_test/ttcn2json/zero.asn create mode 100644 regression_test/typeCompat/.gitignore create mode 100644 regression_test/typeCompat/ASN_Ext.asn create mode 100644 regression_test/typeCompat/Compat.ttcn create mode 100644 regression_test/typeCompat/Ext.ttcn create mode 100644 regression_test/typeCompat/Ext2.ttcn create mode 100644 regression_test/typeCompat/Makefile create mode 100644 regression_test/typeCompat/Std.ttcn create mode 100644 regression_test/typeCompat/config.cfg create mode 100644 regression_test/ucharstrOper/.gitignore create mode 100755 regression_test/ucharstrOper/Base64Testcases.ttcn create mode 100755 regression_test/ucharstrOper/Common.ttcn create mode 100644 regression_test/ucharstrOper/Makefile create mode 100644 regression_test/ucharstrOper/TucharstrOper.ttcn create mode 100755 regression_test/ucharstrOper/UTF16Testcases.ttcn create mode 100755 regression_test/ucharstrOper/UTF32Testcases.ttcn create mode 100755 regression_test/ucharstrOper/UTF8Testcases.ttcn create mode 100644 regression_test/ucharstrOper/config.cfg create mode 100644 regression_test/ucharstrOper/cstr_content.ttcn create mode 100644 regression_test/ucharstrOper/external.cc create mode 100644 regression_test/unionOper/.gitignore create mode 100644 regression_test/unionOper/Makefile create mode 100644 regression_test/unionOper/TunionOper.ttcn create mode 100644 regression_test/unionOper/config.cfg create mode 100644 regression_test/vcheck.pl create mode 100644 regression_test/verdictOper/.gitignore create mode 100644 regression_test/verdictOper/Makefile create mode 100644 regression_test/verdictOper/TverdictOper.ttcn create mode 100644 regression_test/verdictOper/config.cfg create mode 100644 regression_test/visibility/.gitignore create mode 100644 regression_test/visibility/Makefile create mode 100644 regression_test/visibility/Visibility.ttcn create mode 100644 regression_test/visibility/config.cfg create mode 100644 regression_test/visibility/module1.ttcn create mode 100644 regression_test/visibility/module2.ttcn create mode 100644 regression_test/visibility/module3.ttcn create mode 100644 regression_test/visibility/module4.ttcn create mode 100644 repgen/.gitignore create mode 100644 repgen/Makefile create mode 100644 repgen/logfilter.c create mode 100644 repgen/logformat.l create mode 100644 repgen/logmerge.c create mode 100644 repgen/parser.l create mode 100644 repgen/repgen.c create mode 100644 repgen/repgen.h create mode 100644 repgen/ttcn3_logfilter.1 create mode 100644 repgen/ttcn3_logformat.1 create mode 100644 repgen/ttcn3_logmerge.1 create mode 100644 titan_executor_api/.gitignore create mode 100644 titan_executor_api/TITAN_Executor_API/.classpath create mode 100644 titan_executor_api/TITAN_Executor_API/.gitignore create mode 100644 titan_executor_api/TITAN_Executor_API/.project create mode 100644 titan_executor_api/TITAN_Executor_API/build.xml create mode 100644 titan_executor_api/TITAN_Executor_API/doc/javadoc-overview/javadoc-overview.html create mode 100644 titan_executor_api/TITAN_Executor_API/doc/uml/TITAN_Executor_API_class_diagram.png create mode 100644 titan_executor_api/TITAN_Executor_API/doc/uml/TITAN_Executor_API_class_diagram.uxf create mode 100644 titan_executor_api/TITAN_Executor_API/doc/uml/TITAN_Executor_API_sequence_diagram.uxf create mode 100644 titan_executor_api/TITAN_Executor_API/doc/uml/TITAN_Executor_API_state_diagram.uxf create mode 100644 titan_executor_api/TITAN_Executor_API/doc/uml/TITAN_Executor_API_state_diagram_simple.png create mode 100644 titan_executor_api/TITAN_Executor_API/doc/uml/TITAN_Executor_API_state_diagram_simple.uxf create mode 100644 titan_executor_api/TITAN_Executor_API/doc/uml/TITAN_Executor_API_test_class_diagram.uxf create mode 100644 titan_executor_api/TITAN_Executor_API/javadoc.xml create mode 100644 titan_executor_api/TITAN_Executor_API/nb-build.xml create mode 100644 titan_executor_api/TITAN_Executor_API/nbproject/build-impl.xml create mode 100644 titan_executor_api/TITAN_Executor_API/nbproject/genfiles.properties create mode 100644 titan_executor_api/TITAN_Executor_API/nbproject/project.properties create mode 100644 titan_executor_api/TITAN_Executor_API/nbproject/project.xml create mode 100644 titan_executor_api/TITAN_Executor_API/readme.txt create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executor/jni/ComponentStruct.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executor/jni/HcStateEnum.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executor/jni/HostStruct.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executor/jni/IJNICallback.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executor/jni/JNIMiddleWare.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executor/jni/McStateEnum.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executor/jni/QualifiedName.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executor/jni/TcStateEnum.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executor/jni/Timeval.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executor/jni/TransportTypeEnum.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executor/jni/VerdictTypeEnum.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executorapi/HostController.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executorapi/IJniExecutorObserver.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executorapi/JniExecutor.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executorapi/exception/JniExecutorException.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executorapi/exception/JniExecutorIllegalArgumentException.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executorapi/exception/JniExecutorJniLoadException.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executorapi/exception/JniExecutorStartSessionException.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executorapi/exception/JniExecutorWrongStateException.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executorapi/package-info.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executorapi/util/Log.java create mode 100644 titan_executor_api/TITAN_Executor_API/src/org/eclipse/titan/executorapi/util/StringUtil.java create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/.classpath create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/.gitignore create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/.project create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/build.xml create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/manifest.mf create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/nb-build.xml create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/nbproject/build-impl.xml create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/nbproject/genfiles.properties create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/nbproject/project.properties create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/nbproject/project.xml create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/src/org/eclipse/titan/executorapi/demo/CommonData.java create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/src/org/eclipse/titan/executorapi/demo/DemoFrame.java create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/src/org/eclipse/titan/executorapi/demo/ExecuteCfgDialog.java create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/src/org/eclipse/titan/executorapi/demo/ExecuteControlDialog.java create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/src/org/eclipse/titan/executorapi/demo/ExecuteTestcaseDialog.java create mode 100644 titan_executor_api/TITAN_Executor_API_Demo/src/org/eclipse/titan/executorapi/demo/Main.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/.classpath create mode 100644 titan_executor_api/TITAN_Executor_API_test/.gitignore create mode 100644 titan_executor_api/TITAN_Executor_API_test/.project create mode 100644 titan_executor_api/TITAN_Executor_API_test/build.xml create mode 100644 titan_executor_api/TITAN_Executor_API_test/nb-build.xml create mode 100644 titan_executor_api/TITAN_Executor_API_test/nbproject/build-impl.xml create mode 100644 titan_executor_api/TITAN_Executor_API_test/nbproject/genfiles.properties create mode 100644 titan_executor_api/TITAN_Executor_API_test/nbproject/project.properties create mode 100644 titan_executor_api/TITAN_Executor_API_test/nbproject/project.xml create mode 100644 titan_executor_api/TITAN_Executor_API_test/readme.txt create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/HostControllerErrorIllegalArgTest.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/JniExecutorAsyncErrorIllegalArgTest.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/JniExecutorAsyncErrorTest.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/JniExecutorAsyncErrorWrongStateTest.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/JniExecutorAsyncHappySimpleTest.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/JniExecutorAsyncHappyTest.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/JniExecutorAsyncTest.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/JniExecutorSync.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/JniExecutorSyncTest.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/JniExecutorTest.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/NormalTestObserver.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/StringUtilTest.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/Test1Observer.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/Test2Observer.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/TestConstants.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/TestObserverBase.java create mode 100644 titan_executor_api/TITAN_Executor_API_test/src/org/eclipse/titan/executorapi/test/TestUtil.java create mode 100755 titan_executor_api/doc/Titan_Executor_API_User_Guide.doc create mode 100644 usrguide/.gitignore create mode 100644 usrguide/Makefile create mode 100644 usrguide/apiguide.doc create mode 100644 usrguide/installationguide.doc create mode 100644 usrguide/pdfgen.sh create mode 100644 usrguide/referenceguide.doc create mode 100644 usrguide/releasenotes.doc create mode 100644 usrguide/userguide.doc create mode 100644 xsdconvert/.gitignore create mode 100644 xsdconvert/Annotation.cc create mode 100644 xsdconvert/Annotation.hh create mode 100644 xsdconvert/ComplexType.cc create mode 100644 xsdconvert/ComplexType.hh create mode 100644 xsdconvert/FieldType.cc create mode 100644 xsdconvert/FieldType.hh create mode 100644 xsdconvert/GeneralFunctions.cc create mode 100644 xsdconvert/GeneralFunctions.hh create mode 100644 xsdconvert/GeneralTypes.hh create mode 100644 xsdconvert/ImportStatement.cc create mode 100644 xsdconvert/ImportStatement.hh create mode 100644 xsdconvert/List.hh create mode 100644 xsdconvert/Makefile create mode 100644 xsdconvert/Mstring.cc create mode 100644 xsdconvert/Mstring.hh create mode 100644 xsdconvert/PredefinedModules.cc create mode 100644 xsdconvert/RootType.cc create mode 100644 xsdconvert/RootType.hh create mode 100644 xsdconvert/SimpleType.cc create mode 100644 xsdconvert/SimpleType.hh create mode 100644 xsdconvert/TTCN3Module.cc create mode 100644 xsdconvert/TTCN3Module.hh create mode 100644 xsdconvert/TTCN3ModuleInventory.cc create mode 100644 xsdconvert/TTCN3ModuleInventory.hh create mode 100644 xsdconvert/XMLParser.cc create mode 100644 xsdconvert/XMLParser.hh create mode 100644 xsdconvert/converter.cc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4fb1668 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +doxygen +Install +Makefile.personal +.cproject +.TITAN* +*.o +*.exe +*.pdf +META-INF +build.properties diff --git a/JNI/.gitignore b/JNI/.gitignore new file mode 100644 index 0000000..e243211 --- /dev/null +++ b/JNI/.gitignore @@ -0,0 +1,2 @@ +lib*.so +*.o diff --git a/JNI/Makefile b/JNI/Makefile new file mode 100644 index 0000000..41753a5 --- /dev/null +++ b/JNI/Makefile @@ -0,0 +1,76 @@ +############################################################################### +# 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 +############################################################################### +# +# "org_eclipse_titan_executor_jni_JNIMiddleWare.h" is generated by javah (java header generator tool) +# DO NOT EDIT THAT FILE UNLESS YOU KNOW WHAT YOU ARE DOING +# +# CLI command for header generation: +# > javah -classpath . -jni org.eclipse.titan.executor.jni.JNIMiddleWare +# - must be issued in the /bin direcory within the project + +TOP := .. +include $(TOP)/Makefile.cfg + +CPPFLAGS += -I$(JDKDIR)/include +ifeq ($(PLATFORM), WIN32) +CPPFLAGS += -D__int64='long long' +endif + +ifeq ($(PLATFORM), LINUX) + CPPFLAGS += -I$(JDKDIR)/include/linux +endif +ifeq ($(PLATFORM), SOLARIS) + CPPFLAGS += -I$(JDKDIR)/include/solaris +endif +ifeq ($(PLATFORM), SOLARIS8) + CPPFLAGS += -I$(JDKDIR)/include/solaris +endif + +STATIC_SOURCES := jnimw.cc jninativelib.cc +HEADERS := jnimw.h org_eclipse_titan_executor_jni_JNIMiddleWare.h + +SOURCES := $(STATIC_SOURCES) + +OBJECTS := $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(SOURCES))) + +OTHER_OBJECTS := $(TOP)/mctr2/mctr/MctrError.o $(TOP)/mctr2/mctr/MainController.o \ + $(TOP)/mctr2/mctr/UserInterface.o $(TOP)/common/memory.o \ + $(TOP)/common/new.o $(TOP)/core/Textbuf.o $(TOP)/core/RInt.o $(TOP)/common/NetworkHandler.o \ + $(TOP)/mctr2/cli/config_read.lex.o $(TOP)/mctr2/cli/config_read.tab.o $(TOP)/mctr2/mctr/config_data.o \ + $(TOP)/common/config_preproc_p.tab.o $(TOP)/common/config_preproc.o $(TOP)/common/config_preproc_la.o \ + $(TOP)/common/path.o $(TOP)/common/memory.o $(TOP)/common/Path2.o + +ifeq ($(LICENSING), yes) + OTHER_OBJECTS += $(TOP)/common/license.o +endif + +TARGETS := libmctrjninative.so + +SOLARIS_LIBS = +SOLARIS8_LIBS := -lsocket -lnsl +LINUX_LIBS := +FREEBSD_LIBS = +WIN32_LIBS = + +# +# Rules for building the executable... +# +all run: $(TARGETS); + +libmctrjninative.so: $(OBJECTS) $(OTHER_OBJECTS) + $(LD) $(LDFLAGS) -o $@ $^ \ + $($(PLATFORM)_LIBS) -lpthread $(LICENSE_LIBS) -L$(OPENSSL_DIR)/lib -lcrypto + +install: $(TARGETS) +ifeq ($(DEBUG), no) + $(STRIP) $(TARGETS) +endif + mkdir -p $(LIBDIR) + cp $(TARGETS) $(LIBDIR) + +include $(TOP)/Makefile.genrules diff --git a/JNI/jnimw.cc b/JNI/jnimw.cc new file mode 100644 index 0000000..151afe1 --- /dev/null +++ b/JNI/jnimw.cc @@ -0,0 +1,286 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "jnimw.h" +#include +#include +#include +#include +#include +#include + +#include "../core/Logger.hh" + +using mctr::MainController; +using namespace jnimw; + +Jnimw *Jnimw::userInterface; +bool Jnimw::has_status_message_pending; +int Jnimw::pipe_size; + +/** + * The last MC state. It is needed by status_change(), as + * status change message is written to the pipe when any status (MC, TC, HC) was changed AND + * ( currently there is no status change message on the pipe (signalled by has_status_message_pending) + * OR MC state is changed ) + */ +mctr::mc_state_enum last_mc_state; + +pthread_mutex_t Jnimw::mutex = PTHREAD_MUTEX_INITIALIZER; + +/** + * Config data, which was created by Java_org_eclipse_titan_executor_jni_JNIMiddleWare_set_1cfg_1file() + * by a JNI request, and the result will be used by + * Java_org_eclipse_titan_executor_jni_JNIMiddleWare_configure(). + * This is done this way to use process_config_read_file() for processing the config file + * instead of processing it on the Java side. + */ +config_data Jnimw::mycfg; + +void Jnimw::lock() +{ + int result = pthread_mutex_lock(&mutex); + if (result > 0) { + fatal_error("Jni middleware::lock: " + "pthread_mutex_lock failed with code %d.", result); + } +} + +void Jnimw::unlock() +{ + int result = pthread_mutex_unlock(&mutex); + if (result > 0) { + fatal_error("Jni middleware:::unlock: " + "pthread_mutex_unlock failed with code %d.", result); + } +} + +void Jnimw::fatal_error(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + if (errno != 0) fprintf(stderr, " (%s)", strerror(errno)); + putc('\n', stderr); + exit(EXIT_FAILURE); +} + +int Jnimw::enterLoop(int, char*[]) { + return EXIT_SUCCESS; +} + +Jnimw::Jnimw() +{ + pipe_buffer = NULL; + pipe_fd[0] = -1; + pipe_fd[1] = -1; + + create_pipe(); + FD_ZERO(&readfds); + FD_SET(pipe_fd[0], &readfds); + + has_status_message_pending = false; + last_mc_state = mctr::MC_INACTIVE; + pipe_size = 0; + + if (pthread_mutex_init(&mutex, NULL)) + fatal_error("Jni middleware::constructor: pthread_mutex_init failed."); + +} + +Jnimw::~Jnimw() +{ + destroy_pipe(); + pthread_mutex_destroy(&mutex); +} + + +void strreverse(char* begin, char* end) { + char aux; + while(end>begin){ + aux=*end, *end--=*begin, *begin++=aux; + } +} + +/** + * Ansi C "itoa" based on Kernighan & Ritchie's "Ansi C": + */ +void itoa(int value, char* str) { + static char num[] = "0123456789"; + char* wstr=str; + + // Conversion. Number is reversed. + do *wstr++ = num[value%10]; while(value/=10); + *wstr='\0'; + + // Reverse string + strreverse(str,wstr-1); +} + +void create_packet_header(const int source_length, char* dest, char method_id) { + char packet_size[6]; + dest[0] = method_id; + itoa(source_length, packet_size); + int i; + for(i = 1; i < 6; i++) dest[i] = '0'; + dest[6] = '\0'; + int j = strlen(packet_size); + for(i = 0; i < j; i++) dest[5-i] = packet_size[j-i-1]; +} + +char* stuffer(const char* msg){ + char* msg_stuffed = (char*) malloc(strlen(msg)*2); + int i = 0; + int j = 0; + while(msg[i] != '\0') { + if(msg[i] != '|' && msg[i] != '\\') { + msg_stuffed[j++] = msg[i]; + } else { + msg_stuffed[j++] = '\\'; + msg_stuffed[j++] = msg[i]; + } + i++; + } + msg_stuffed[j] = '\0'; + + return msg_stuffed; +} + +//---------------------------------------------------------------------------- +// USERINTERFACE + +void Jnimw::status_change() +{ + lock(); + mctr::mc_state_enum mc_state = MainController::get_state(); + if(last_mc_state != mc_state || !has_status_message_pending){ + char str[7]; + sprintf( str,"S%02d000", mc_state ); + write_pipe( str ); + } + has_status_message_pending = true; + last_mc_state = mc_state; + unlock(); +} + +//---------------------------------------------------------------------------- +// USERINTERFACE + +void Jnimw::error(int severity, const char* msg) +{ + char *msg_stuffed = stuffer(msg); + expstring_t pipe_s; + + // creating packet header + char packet_header[7]; + expstring_t tmp; + tmp = mprintf("%d|%s", severity, msg_stuffed); + create_packet_header(strlen(tmp), packet_header, 'E'); + + pipe_s = mprintf("%s%s", packet_header, tmp); + free(msg_stuffed); + + write_pipe(pipe_s); +} + +//---------------------------------------------------------------------------- +// USERINTERFACE + +void Jnimw::notify(const struct timeval* time, const char* source, + int severity, const char* msg) +{ + char *source_stuffed = stuffer(source); + char *msg_stuffed = stuffer(msg); + expstring_t pipe_s; + + // creating packet header + char packet_header[7]; + expstring_t tmp; + tmp = mprintf("%ld|%ld|%s|%d|%s", time->tv_sec, time->tv_usec, source_stuffed, severity, msg_stuffed); + create_packet_header(strlen(tmp), packet_header, 'N'); + + pipe_s = mprintf("%s%s", packet_header, tmp); + write_pipe(pipe_s); + free(source_stuffed); + free(msg_stuffed); + Free(tmp); + Free(pipe_s); +} + +void Jnimw::create_pipe() +{ + if (pipe(pipe_fd)){ + printf("Jnimw::create_pipes(): pipe system call failed.\n"); + } +} + +void Jnimw::destroy_pipe() +{ + close(pipe_fd[0]); + pipe_fd[0] = -1; + close(pipe_fd[1]); + pipe_fd[1] = -1; +} + +bool Jnimw::is_pipe_readable(){ + // TODO maybe this could get faster + timeval time; + time.tv_sec = 0; + time.tv_usec = 0; + fd_set read_set; + FD_ZERO(&read_set); + FD_SET(pipe_fd[0], &read_set); + int ret = select(pipe_fd[0] + 1 , &read_set, NULL, NULL, &time); + return ret > 0; +} + +char* Jnimw::read_pipe() +{ + select(pipe_fd[0] + 1 , &readfds, NULL, NULL, NULL); + lock(); + + pipe_buffer = (char*)malloc(7); + int ret = read(pipe_fd[0], pipe_buffer, 6); + if(ret != 6){ + printf("Malformed packet arrived!\n"); + } + + pipe_size-= ret; + + if(pipe_buffer[0] == 'S'){ + has_status_message_pending = false; + + unlock(); + return pipe_buffer; + } + + int packet_size = (pipe_buffer[1]-48) * 10000 + (pipe_buffer[2]-48) * 1000 + + (pipe_buffer[3]-48) * 100 + (pipe_buffer[4]-48) * 10 + (pipe_buffer[5]-48); + + pipe_buffer = (char*)realloc(pipe_buffer, packet_size + 7); + + ret = read(pipe_fd[0],pipe_buffer + 6, packet_size); + if(ret != packet_size){ + printf("Jnimw::read_pipe(): read system call failed\n"); + } + pipe_buffer[packet_size + 6] = '\0'; + + pipe_size-=ret; + + unlock(); + return pipe_buffer; +} + +void Jnimw::write_pipe(const char *buf) +{ + if (write(pipe_fd[1], buf, strlen(buf)) < 0){ + printf("Jnimw::write_pipe(): write system call failed\n"); + } + + pipe_size+=strlen(buf); +} diff --git a/JNI/jnimw.h b/JNI/jnimw.h new file mode 100644 index 0000000..5b0da16 --- /dev/null +++ b/JNI/jnimw.h @@ -0,0 +1,92 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef JNIMW_JNIMW_H +#define JNIMW_JNIMW_H +//---------------------------------------------------------------------------- + +#include +#include +#include +#include "../core/Types.h" +#include "../mctr2/mctr/UserInterface.h" +#include "../mctr2/mctr/MainController.h" +#include "../common/memory.h" +#include "../mctr2/mctr/config_data.h" + +//---------------------------------------------------------------------------- + +namespace jnimw { + +//---------------------------------------------------------------------------- + +/** + * User interface jnimw implementation. + */ +class Jnimw : public mctr::UserInterface +{ +public: + static Jnimw *userInterface; + int pipe_fd[2]; + char *pipe_buffer; + fd_set readfds; + + static bool has_status_message_pending; + static int pipe_size; + + static pthread_mutex_t mutex; + + /** + * Configuration data which is filled by calling set_cfg_file() + * Based on Cli::mycfg + */ + static config_data mycfg; + +public: + /** + * Constructor, destructor. + */ + Jnimw(); + ~Jnimw(); + + virtual int enterLoop(int argc, char* argv[]); + + /* Callback interface */ + /** + * Status of MC has changed. + */ + virtual void status_change(); + + /** + * Error message from MC. + */ + virtual void error(int severity, const char* msg); + + /** + * General notification from MC. + */ + virtual void notify(const struct timeval* time, const char* source, + int severity, const char* msg); + + void create_pipe(); + void destroy_pipe(); + char* read_pipe(); + void write_pipe(const char *buf); + + bool is_pipe_readable(); + + static void lock(); + static void unlock(); + static void fatal_error(const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 1, 2), __noreturn__)); +}; +//---------------------------------------------------------------------------- + +} + +//---------------------------------------------------------------------------- +#endif // JNIMW_JNIMW_H diff --git a/JNI/jninativelib.cc b/JNI/jninativelib.cc new file mode 100644 index 0000000..b472414 --- /dev/null +++ b/JNI/jninativelib.cc @@ -0,0 +1,1495 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "jnimw.h" +#include "org_eclipse_titan_executor_jni_JNIMiddleWare.h" +#include +#include +#include +#include "../core/Textbuf.hh" +#include "../common/memory.h" +#include "../common/license.h" +#include "../common/version.h" +#include +#include + + +using mctr::MainController; +using namespace jnimw; + +JNIEXPORT jlong JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_init(JNIEnv *, jobject, jint max_ptcs) +{ + Jnimw *userInterface; + userInterface = new Jnimw(); + Jnimw::userInterface = userInterface; + MainController::initialize(*userInterface, (int)max_ptcs); + return (jlong)userInterface; +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_terminate(JNIEnv *, jobject) +{ + MainController::terminate(); + delete Jnimw::userInterface; + Jnimw::userInterface = NULL; +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_add_1host(JNIEnv *env, jobject, jstring group_name, jstring host_name) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + jboolean iscopy_grp; + jboolean iscopy_hst; + const char *grp_name = env->GetStringUTFChars(group_name, &iscopy_grp); + const char *hst_name = env->GetStringUTFChars(host_name, &iscopy_hst); + MainController::add_host(grp_name, hst_name); + env->ReleaseStringUTFChars(group_name, grp_name); + env->ReleaseStringUTFChars(host_name, hst_name); +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_assign_1component(JNIEnv *env, jobject, jstring host_or_group, jstring component_id) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + jboolean iscopy_hog; + jboolean iscopy_cid; + const char *hog = env->GetStringUTFChars(host_or_group, &iscopy_hog); + const char *cid = env->GetStringUTFChars(component_id, &iscopy_cid); + MainController::assign_component(hog, cid); + env->ReleaseStringUTFChars(host_or_group, hog); + env->ReleaseStringUTFChars(component_id, cid); +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_destroy_1host_1groups(JNIEnv *, jobject) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + MainController::destroy_host_groups(); +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_set_1kill_1timer(JNIEnv *, jobject, jdouble timer_val) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + MainController::set_kill_timer((double)timer_val); +} + +JNIEXPORT jint JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_start_1session(JNIEnv *env, jobject, jstring local_address, jint tcp_port, jboolean unixdomainsocketenabled) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return (jint)-1; + jboolean iscopy; + const char *local_addr = env->GetStringUTFChars(local_address, &iscopy); + if (strcmp(local_addr, "NULL") == 0) { + env->ReleaseStringUTFChars(local_address, local_addr); + local_addr = NULL; + } + unsigned short tcp_listen_port = (unsigned short)tcp_port; + int ret = MainController::start_session(local_addr, tcp_listen_port, unixdomainsocketenabled); + if (local_addr != NULL) env->ReleaseStringUTFChars(local_address, local_addr); + return (jint)ret; +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_shutdown_1session(JNIEnv *, jobject) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + MainController::shutdown_session(); +} + +/** + * ASYNCHRONOUS + * Configure MainController and HCs. + * It is also known as "Set parameter" operation. + * + * It can be called in the following states: + * MC_LISTENING -> MC_LISTENING_CONFIGURED will be the next state, when configuring operation is finished + * MC_LISTENING_CONFIGURED -> MC_LISTENING_CONFIGURED will be the next state, when configuring operation is finished + * MC_HC_CONNECTED -> MC_CONFIGURING immediately and MC_ACTIVE when configuring operation is finished + * + * @param env Pointer to the caller java environment (mandatory parameter of every JNI function) + * @param jobject The caller java object (mandatory parameter of every JNI function) + * @param config_file config string, generated from the config file by removing unnecessary parts. It can be empty string, and also null. + * Generating config string can be done in 2 ways: + * by "hand" (if the parameter is not empty string and not null): + * on the java side, and pass it as a parameter, for an example see JniExecutor.DEFAULT_CONFIG_STRING or BaseExecutor.generateCfgString() + * by MainController (if the parameter is empty string or null): + * call set_cfg_file() after init() with the cfg file, and let MainController process it and create the config string, + * and then config() can be called with empty string or null as a parameter, which means that config string from MainController config data will be used. + * + * NOTE: Function comment is here, because function declaration is in org_eclipse_titan_executor_jni_JNIMiddleWare.h, which is generated. + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_configure(JNIEnv *env, jobject, jstring config_file) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + jboolean iscopy; + if (config_file == NULL || env->GetStringLength( config_file ) == 0 ) { + // use config string, which was generated by MainController + MainController::configure(Jnimw::mycfg.config_read_buffer); + } + else { + const char *conf_file = env->GetStringUTFChars(config_file, &iscopy); + MainController::configure(conf_file); + env->ReleaseStringUTFChars(config_file, conf_file); + } +} + +/** + * The name of the config file is sent here for syntactic and semantic analysis. + * The result config string is needed by start_session() and configure(). + * Result is stored in Jnimw::mycfg. + * We need the following info from it: + * config_read_buffer: passed to configure() if parameter is an empty string + * local_address: needed by the java side for start_session() and starting the HC, it is read by calling get_mc_host() + * tcp_listen_port: needed by the java side for start_session(), it is read by calling get_port() + * kill_timer: processed in this function + * group_list: processed in this function + * component_list: processed in this function + * This code is based on the following code: Cli.cc: Cli::enterloop() + * + * @param env Pointer to the caller java environment (mandatory parameter of every JNI function) + * @param jobject The caller java object (mandatory parameter of every JNI function) + * @param conf_file_name The configuration file name of the TTCN-3 test project + * + * NOTE: Function comment is here, because function declaration is in org_eclipse_titan_executor_jni_JNIMiddleWare.h, which is generated. + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_set_1cfg_1file(JNIEnv *env, jobject, jstring config_file_name) +{ + if (!Jnimw::userInterface) + return; + jboolean iscopy; + if (config_file_name == NULL) + return; + const char *conf_file_name = env->GetStringUTFChars(config_file_name, &iscopy); + + if (process_config_read_file(conf_file_name, &Jnimw::mycfg)) { + MainController::error("Error was found in the configuration file. Exiting."); + } + else { + MainController::set_kill_timer(Jnimw::mycfg.kill_timer); + + for (int i = 0; i < Jnimw::mycfg.group_list_len; ++i) { + const group_item& item = Jnimw::mycfg.group_list[i]; + MainController::add_host( item.group_name, item.host_name ); + } + + for (int i = 0; i < Jnimw::mycfg.component_list_len; ++i) { + const component_item& item = Jnimw::mycfg.component_list[i]; + MainController::assign_component( item.host_or_group, item.component ); + } + } + + env->ReleaseStringUTFChars(config_file_name, conf_file_name); +} + +/** + * Local host address for start_session() and starting the HC + * This will contain valid information after successful run of Java_org_eclipse_titan_executor_jni_JNIMiddleWare_set_1cfg_1file() + * + * @param env Pointer to the caller java environment (mandatory parameter of every JNI function) + * @param jobject The caller java object (mandatory parameter of every JNI function) + * @return Local host address + * + * NOTE: Function comment is here, because function declaration is in org_eclipse_titan_executor_jni_JNIMiddleWare.h, which is generated. + */ +JNIEXPORT jstring JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1mc_1host(JNIEnv *env, jobject) +{ + return env->NewStringUTF( Jnimw::mycfg.local_addr != NULL ? Jnimw::mycfg.local_addr : "NULL" ); +} + +/** + * TCP listen port for start_session() + * This will contain valid information after successful run of Java_org_eclipse_titan_executor_jni_JNIMiddleWare_set_1cfg_1file() + * + * @param env Pointer to the caller java environment (mandatory parameter of every JNI function) + * @param jobject The caller java object (mandatory parameter of every JNI function) + * @return TCP listen port + * + * NOTE: Function comment is here, because function declaration is in org_eclipse_titan_executor_jni_JNIMiddleWare.h, which is generated. + */ +JNIEXPORT jint JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1port(JNIEnv *, jobject) +{ + return (jint)Jnimw::mycfg.tcp_listen_port; +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_create_1mtc(JNIEnv *, jobject, jint host_index) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + MainController::create_mtc((int)host_index); +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_exit_1mtc(JNIEnv *, jobject) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + MainController::exit_mtc(); +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_execute_1control(JNIEnv *env, jobject, jstring module_name) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + jboolean iscopy; + const char *mod_name = env->GetStringUTFChars(module_name, &iscopy); + MainController::execute_control(mod_name); + env->ReleaseStringUTFChars(module_name, mod_name); +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_execute_1testcase(JNIEnv *env, jobject, jstring module_name, jstring testcase_name) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + jboolean iscopy_mod; + jboolean iscopy_tes; + const char *mod_name = env->GetStringUTFChars(module_name, &iscopy_mod); + const char *testc_name = env->GetStringUTFChars(testcase_name, &iscopy_tes); + MainController::execute_testcase(mod_name, testc_name); + env->ReleaseStringUTFChars(module_name, mod_name); + env->ReleaseStringUTFChars(testcase_name, testc_name); +} + +/** + * Gets the length of the execute list. + * @param env Pointer to the caller java environment (mandatory parameter of every JNI function) + * @param jobject The caller java object (mandatory parameter of every JNI function) + * @return The length of the execute list, + * which is defined in the [EXECUTE] section in the configuration file. + * 0, if there is no [EXECUTE] section in the configuration file. + * + * NOTE: Function comment is here, because function declaration is in org_eclipse_titan_executor_jni_JNIMiddleWare.h, which is generated. + */ +JNIEXPORT jint JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1execute_1cfg_1len(JNIEnv *env, jobject) +{ + return (jint)Jnimw::mycfg.execute_list_len; +} + +/** + * Executes the index-th element form the execute list, + * which is defined in the [EXECUTE] section in the configuration file. + * Based on Cli::executeFromList() + * @param env Pointer to the caller java environment (mandatory parameter of every JNI function) + * @param jobject The caller java object (mandatory parameter of every JNI function) + * @param index The test index from the execute list + * + * NOTE: Function comment is here, because function declaration is in org_eclipse_titan_executor_jni_JNIMiddleWare.h, which is generated. + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_execute_1cfg(JNIEnv *env, jobject, jint index) +{ + if (!Jnimw::userInterface) + return; + if ( index < 0 || index >= Jnimw::mycfg.execute_list_len ) { + MainController::error("Java_org_eclipse_titan_executor_jni_JNIMiddleWare_execute_1cfg(): invalid argument: index"); + return; + } + const execute_list_item& item = Jnimw::mycfg.execute_list[ index ]; + if ( item.testcase_name == NULL ) { + MainController::execute_control( item.module_name ); + } else if ( !strcmp( item.testcase_name, "*" ) ) { + MainController::execute_testcase( item.module_name, NULL ); + } else { + MainController::execute_testcase( item.module_name, item.testcase_name ); + } +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_stop_1after_1testcase(JNIEnv *, jobject, jboolean new_state) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + MainController::stop_after_testcase((bool)new_state); +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_continue_1testcase(JNIEnv *, jobject) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + MainController::continue_testcase(); +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_stop_1execution(JNIEnv *, jobject) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return; + MainController::stop_execution(); +} + +JNIEXPORT jobject JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1state(JNIEnv *env, jobject) +{ + jclass cls = env->FindClass("org/eclipse/titan/executor/jni/McStateEnum"); + if (cls == NULL) { + printf("Can't find class org.eclipse.titan.executor.jni.McStateEnum\n"); + } + jfieldID fid = 0; + jobject ret; + // Fix for TR HO56282. + // MC's get_state() calls lock(), but the mutex is destroyed already at this + // point from JNI code... + if (!Jnimw::userInterface) { + fid = env->GetStaticFieldID(cls, "MC_INACTIVE", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_INACTIVE\n"); + } + } else { + switch (MainController::get_state()) { + case mctr::MC_INACTIVE: + fid = env->GetStaticFieldID(cls, "MC_INACTIVE", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_INACTIVE\n"); + } + break; + case mctr::MC_LISTENING: + fid = env->GetStaticFieldID(cls, "MC_LISTENING", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_LISTENING\n"); + } + break; + case mctr::MC_LISTENING_CONFIGURED: + fid = env->GetStaticFieldID(cls, "MC_LISTENING_CONFIGURED", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_LISTENING_CONFIGURED\n"); + } + break; + case mctr::MC_HC_CONNECTED: + fid = env->GetStaticFieldID(cls, "MC_HC_CONNECTED", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_HC_CONNECTED\n"); + } + break; + case mctr::MC_CONFIGURING: + fid = env->GetStaticFieldID(cls, "MC_CONFIGURING", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_CONFIGURING\n"); + } + break; + case mctr::MC_ACTIVE: + fid = env->GetStaticFieldID(cls, "MC_ACTIVE", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_ACTIVE\n"); + } + break; + case mctr::MC_SHUTDOWN: + fid = env->GetStaticFieldID(cls, "MC_SHUTDOWN", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_SHUTDOWN\n"); + } + break; + case mctr::MC_CREATING_MTC: + fid = env->GetStaticFieldID(cls, "MC_CREATING_MTC", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_CREATING_MTC\n"); + } + break; + case mctr::MC_READY: + fid = env->GetStaticFieldID(cls, "MC_READY", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_READY\n"); + } + break; + case mctr::MC_TERMINATING_MTC: + fid = env->GetStaticFieldID(cls, "MC_TERMINATING_MTC", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_TERMINATING_MTC\n"); + } + break; + case mctr::MC_EXECUTING_CONTROL: + fid = env->GetStaticFieldID(cls, "MC_EXECUTING_CONTROL", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_EXECUTING_CONTROL\n"); + } + break; + case mctr::MC_EXECUTING_TESTCASE: + fid = env->GetStaticFieldID(cls, "MC_EXECUTING_TESTCASE", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_EXECUTING_TESTCASE\n"); + } + break; + case mctr::MC_TERMINATING_TESTCASE: + fid = env->GetStaticFieldID(cls, "MC_TERMINATING_TESTCASE", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_TERMINATING_TESTCASE\n"); + } + break; + case mctr::MC_PAUSED: + fid = env->GetStaticFieldID(cls, "MC_PAUSED", + "Lorg/eclipse/titan/executor/jni/McStateEnum;"); + if (fid == 0) { + printf("Can't find field MC_PAUSED\n"); + } + break; + default: + printf("Unknown mc_state_enum state\n"); + } + } + ret = env->GetStaticObjectField(cls, fid); + env->ExceptionClear(); + return ret; +} + +JNIEXPORT jboolean JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1stop_1after_1testcase(JNIEnv *, jobject) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return (jboolean)true; + return (jboolean)MainController::get_stop_after_testcase(); +} + +JNIEXPORT jint JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1nof_1hosts(JNIEnv *, jobject) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return (jint)-1; + return (jint)MainController::get_nof_hosts(); +} + +JNIEXPORT jobject JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1host_1data(JNIEnv *env, jobject, jint host_index) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return NULL; + mctr::host_struct *hs = MainController::get_host_data((int)host_index); + if (hs == NULL) return NULL; + IPAddress *ip_addr = hs->ip_addr; + const char *hostname = hs->hostname; + const char *hostname_local = hs->hostname_local; + const char *machine_type = hs->machine_type; + const char *system_name = hs->system_name; + const char *system_release = hs->system_release; + const char *system_version = hs->system_version; + boolean *transport_supported = hs->transport_supported; + const char *log_source = hs->log_source; + mctr::hc_state_enum hc_state = hs->hc_state; + int hc_fd = hs->hc_fd; + Text_Buf *text_buf = hs->text_buf; + int n_components = hs->n_components; + component *components = hs->components; + mctr::string_set allowed_components = hs->allowed_components; + bool all_components_allowed = hs->all_components_allowed; + int n_active_components = hs->n_active_components; + + /*// --- DEBUG --- filling test data + in_addr t_i; + t_i.s_addr = 121345; + in_addr ip_addr = t_i; + const char *hostname = "test hostname"; + const char *hostname_local = "test hostname_local"; + const char *machine_type = "test machine_type"; + const char *system_name = "test system_name"; + const char *system_release = "test system_release"; + const char *system_version = "test system_version"; + boolean test[3] = {true, true, false}; + boolean *transport_supported = test; + const char *log_source = "test log_source"; + mctr::hc_state_enum hc_state = mctr::HC_CONFIGURING; + int hc_fd = 8; + Text_Buf *text_buf = new Text_Buf(); + text_buf->push_string("test Text_Buf"); + int n_components = 3; + int test_i[3] = {2,4,5}; + component *components = (component*) test_i; + mctr::string_set s_set; + s_set.n_elements = 3; + char *t_stringarray[3] = {"test 1", "test 2", "test 3"}; + s_set.elements = t_stringarray; + mctr::string_set allowed_components = s_set; + bool all_components_allowed = true; + int n_active_components = 5; + // --- END OF DEBUG ---*/ + + // creating HostStruct + jclass cls = env->FindClass("org/eclipse/titan/executor/jni/HostStruct"); + if( cls == NULL ) { + printf("Can't find class org.eclipse.titan.executor.jni.HostStruct\n"); + } + jfieldID fid; + jmethodID mid; + jobject HostStruct; + mid = env->GetMethodID(cls, "", "(IIII)V"); + HostStruct = env->NewObject(cls, mid, 3, text_buf->get_len(), n_components, allowed_components.n_elements); + + // processing struct fields + // ip_addr + const char *ipaddr = ip_addr->get_addr_str(); + fid = env->GetFieldID(cls, "ip_addr", "Ljava/lang/String;"); + if (fid == 0) { + printf("Can't find field hostname\n"); + } + env->SetObjectField(HostStruct, fid, env->NewStringUTF(ipaddr)); + + // hostname + fid = env->GetFieldID(cls, "hostname", "Ljava/lang/String;"); + if (fid == 0) { + printf("Can't find field hostname\n"); + } + env->SetObjectField(HostStruct, fid, env->NewStringUTF(hostname)); + + // hostname_local + fid = env->GetFieldID(cls, "hostname_local", "Ljava/lang/String;"); + if (fid == 0) { + printf("Can't find field hostname_local\n"); + } + env->SetObjectField(HostStruct, fid, env->NewStringUTF(hostname_local)); + + // machine_type + fid = env->GetFieldID(cls, "machine_type", "Ljava/lang/String;"); + if (fid == 0) { + printf("Can't find field machine_type\n"); + } + env->SetObjectField(HostStruct, fid, env->NewStringUTF(machine_type)); + + // system_name + fid = env->GetFieldID(cls, "system_name", "Ljava/lang/String;"); + if (fid == 0) { + printf("Can't find field system_name\n"); + } + env->SetObjectField(HostStruct, fid, env->NewStringUTF(system_name)); + + // system_release + fid = env->GetFieldID(cls, "system_release", "Ljava/lang/String;"); + if (fid == 0) { + printf("Can't find field system_release\n"); + } + env->SetObjectField(HostStruct, fid, env->NewStringUTF(system_release)); + + // system_version + fid = env->GetFieldID(cls, "system_version", "Ljava/lang/String;"); + if (fid == 0) { + printf("Can't find field system_version\n"); + } + env->SetObjectField(HostStruct, fid, env->NewStringUTF(system_version)); + + // transport_supported + fid = env->GetFieldID(cls, "transport_supported", "[Z"); + if (fid == 0) { + printf("Can't find field transport_supported\n"); + } + jbooleanArray TransportSupported = (jbooleanArray)env->GetObjectField(HostStruct, fid); + env->SetBooleanArrayRegion(TransportSupported, (jsize)0, 3,(jboolean *)transport_supported); + + // log_source + fid = env->GetFieldID(cls, "log_source", "Ljava/lang/String;"); + if (fid == 0) { + printf("Can't find field log_source\n"); + } + env->SetObjectField(HostStruct, fid, env->NewStringUTF(log_source)); + + // hc_state + fid = env->GetFieldID(cls, "hc_state", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid == 0) { + printf("Can't find field hc_state\n"); + } + + jclass cls_hc = env->FindClass("org/eclipse/titan/executor/jni/HcStateEnum"); + if( cls_hc == NULL ) { + printf("Can't find class org.eclipse.titan.executor.jni.HcStateEnum\n"); + } + jfieldID fid_hc = 0; + jobject ret; + switch(hc_state) { + case mctr::HC_IDLE: + fid_hc = env->GetStaticFieldID(cls_hc, "HC_IDLE", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hc == 0) { + printf("Can't find field HC_IDLE\n"); + } + break; + case mctr::HC_CONFIGURING: + fid_hc = env->GetStaticFieldID(cls_hc, "HC_CONFIGURING", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hc == 0) { + printf("Can't find field HC_CONFIGURING\n"); + } + break; + case mctr::HC_ACTIVE: + fid_hc = env->GetStaticFieldID(cls_hc, "HC_ACTIVE", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hc == 0) { + printf("Can't find field HC_ACTIVE\n"); + } + break; + case mctr::HC_OVERLOADED: + fid_hc = env->GetStaticFieldID(cls_hc, "HC_OVERLOADED", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hc == 0) { + printf("Can't find field HC_OVERLOADED\n"); + } + break; + case mctr::HC_CONFIGURING_OVERLOADED: + fid_hc = env->GetStaticFieldID(cls_hc, "HC_CONFIGURING_OVERLOADED", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hc == 0) { + printf("Can't find field HC_CONFIGURING_OVERLOADED\n"); + } + break; + // ----------------------------------------------- 6-7 + case mctr::HC_EXITING: + fid_hc = env->GetStaticFieldID(cls_hc, "HC_EXITING", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hc == 0) { + printf("Can't find field HC_EXITING\n"); + } + break; + case mctr::HC_DOWN: + fid_hc = env->GetStaticFieldID(cls_hc, "HC_DOWN", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hc == 0) { + printf("Can't find field HC_DOWN\n"); + } + break; + default: + printf("Unknown hc_state_enum state\n"); + } + ret = env->GetStaticObjectField(cls_hc, fid_hc); + env->ExceptionClear(); + env->SetObjectField(HostStruct, fid, ret); + + // hc_fd + fid = env->GetFieldID(cls, "hc_fd", "I"); + if (fid == 0) { + printf("Can't find field hc_fd\n"); + } + env->SetIntField(HostStruct, fid, (jint)hc_fd); + + // text_buf + fid = env->GetFieldID(cls, "text_buf", "[B"); + if (fid == 0) { + printf("Can't find field text_buf\n"); + } + jbyteArray TextBuf = (jbyteArray)env->GetObjectField(HostStruct, fid); + env->SetByteArrayRegion(TextBuf, (jsize)0, text_buf->get_len(), + const_cast((const jbyte *)text_buf->get_data())); + + // components + fid = env->GetFieldID(cls, "components", "[I"); + if (fid == 0) { + printf("Can't find field components\n"); + } + + jintArray Components = (jintArray)env->GetObjectField(HostStruct, fid); + env->SetIntArrayRegion(Components, (jsize)0,n_components,(jint *)components); + + // allowed_components + fid = env->GetFieldID(cls, "allowed_components", "[Ljava/lang/String;"); + if (fid == 0) { + printf("Can't find field allowed_components\n"); + } + jobjectArray allowedComponents = (jobjectArray) env->GetObjectField(HostStruct, fid); + for(int i = 0; i < allowed_components.n_elements; i++) { + env->SetObjectArrayElement(allowedComponents, i, env->NewStringUTF(allowed_components.elements[i])); + } + + // all_components_allowed + fid = env->GetFieldID(cls, "all_components_allowed", "Z"); + if (fid == 0) { + printf("Can't find field all_components_allowed\n"); + } + env->SetBooleanField(HostStruct, fid, (jboolean)all_components_allowed); + + // n_active_components + fid = env->GetFieldID(cls, "n_active_components", "I"); + if (fid == 0) { + printf("Can't find field n_active_components\n"); + } + env->SetIntField(HostStruct, fid, (jint)n_active_components); + + return HostStruct; +} + +JNIEXPORT jobject JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1component_1data(JNIEnv *env, jobject, jint component_reference) +{ + // Fix for TR HO56282. + if (!Jnimw::userInterface) + return NULL; + mctr::component_struct *cs = MainController::get_component_data((int)component_reference); + if (cs == NULL) return NULL; + + // getting data from struct + + // If any of the pointers are NULL, we return null. + // Some of the pointers may be NULL if its value is not initialized, + // or temporarily set to NULL, like text_buf is NULL during the create MTC operation: it is set to NULL when create_mtc() is called, + // and it will have valid data when asynchronous request of MTC creation is finished. + // Reading component data makes sense only in the following states: + // MC_READY, MC_EXECUTING_CONTROL, MC_EXECUTING_TESTCASE, MC_TERMINATING_TESTCASE, MC_PAUSED + component comp_ref = cs->comp_ref; + qualified_name comp_type = cs->comp_type; + const char *comp_name = cs->comp_name; + if ( NULL == comp_name ) { + return NULL; + } + const char *log_source = cs->log_source; + if ( NULL == log_source ) { + return NULL; + } + mctr::host_struct *comp_location = cs->comp_location; + if ( NULL == comp_location ) { + return NULL; + } + mctr::tc_state_enum tc_state = cs->tc_state; + verdicttype local_verdict = cs->local_verdict; + int tc_fd = cs->tc_fd; + Text_Buf *text_buf = cs->text_buf; + if ( NULL == text_buf ) { + return NULL; + } + qualified_name tc_fn_name = cs->tc_fn_name; + const char *return_type = cs->return_type; + if ( NULL == return_type ) { + return NULL; + } + int return_value_len = cs->return_value_len; + bool is_alive = cs->is_alive; + bool stop_requested = cs->stop_requested; + bool process_killed = cs->process_killed; + + /*// --- DEBUG --- filling test data + component comp_ref = (component) 5; + qualified_name comp_type; + comp_type.module_name = "test module"; + comp_type.definition_name = "test definition"; + const char *comp_name = "test comp_name"; + const char *log_source = "test log_source"; + // --- DEBUG --- filling inner host_struct + mctr::host_struct debug_comp_location; + in_addr t_i; + t_i.s_addr = 121345; + debug_comp_location.ip_addr = t_i; + debug_comp_location.hostname = "inner test hostname"; + debug_comp_location.hostname_local = "inner test hostname_local"; + debug_comp_location.machine_type = "inner test machine_type"; + debug_comp_location.system_name = "inner test system_name"; + debug_comp_location.system_release = "inner test system_release"; + debug_comp_location.system_version = "inner test system_version"; + boolean test[3] = {true, true, false}; + debug_comp_location.transport_supported = test; + debug_comp_location.log_source = "inner test log_source"; + debug_comp_location.hc_state = mctr::HC_CONFIGURING; + debug_comp_location.hc_fd = 8; + debug_comp_location.text_buf = new Text_Buf(); + debug_comp_location.text_buf->push_string("inner test Text_Buf"); + debug_comp_location.n_components = 3; + int test_i[3] = {2,4,5}; + debug_comp_location.components = (component*) test_i; + mctr::string_set s_set; + s_set.n_elements = 3; + char *t_stringarray[3] = {"inner test 1", "inner test 2", "inner test 3"}; + s_set.elements = t_stringarray; + debug_comp_location.allowed_components = s_set; + debug_comp_location.all_components_allowed = true; + debug_comp_location.n_active_components = 5; + // --- END OF DEBUG host_struct --- + mctr::host_struct *comp_location = &debug_comp_location; + mctr::tc_state_enum tc_state = mctr::TC_INITIAL; + verdicttype local_verdict = FAIL; + int tc_fd = 7; + Text_Buf *text_buf = new Text_Buf(); + text_buf->push_string("test Text_Buf component"); + qualified_name tc_fn_name; + tc_fn_name.module_name = "test tc_fn_name module_name"; + tc_fn_name.definition_name = "test tc_fn_name definition_name"; + const char *return_type = "test return_type"; + int return_value_len = 10; + bool is_alive = true; + bool stop_requested = false; + bool process_killed = false; + // --- END OF DEBUG ---*/ + + // creating ComponentStruct + jclass cls = env->FindClass("org/eclipse/titan/executor/jni/ComponentStruct"); + if( cls == NULL ) { + printf("Can't find class org.eclipse.titan.executor.jni.ComponentStruct\n"); + } + jfieldID fid; + jmethodID mid; + jobject ComponentStruct; + mid = env->GetMethodID(cls, "", "(I)V"); + ComponentStruct = env->NewObject(cls, mid, text_buf->get_len()); + + // processing struct fields + // comp_ref + fid = env->GetFieldID(cls, "comp_ref", "I"); + if (fid == 0) { + printf("Can't find field comp_ref\n"); + } + env->SetIntField(ComponentStruct, fid, (jint) comp_ref); + + // comp_type + fid = env->GetFieldID(cls, "comp_type", "Lorg/eclipse/titan/executor/jni/QualifiedName;"); + if (fid == 0) { + printf("Can't find field comp_type\n"); + } + jclass cls_q = env->FindClass("org/eclipse/titan/executor/jni/QualifiedName"); + if( cls_q == NULL ) { + printf("Can't find class QualifiedName\n"); + } + // creating new QualifiedName object + jmethodID mid_q = env->GetMethodID(cls_q, "", "(Ljava/lang/String;Ljava/lang/String;)V"); + jobject qname = env->NewObject(cls_q, mid_q, env->NewStringUTF(comp_type.module_name), + env->NewStringUTF(comp_type.definition_name)); + env->ExceptionClear(); + env->SetObjectField(ComponentStruct, fid, qname); + + // comp_name + fid = env->GetFieldID(cls, "comp_name", "Ljava/lang/String;"); + if (fid == 0) { + printf("Can't find field comp_name\n"); + } + env->SetObjectField(ComponentStruct, fid, env->NewStringUTF(comp_name)); + + // log_source + fid = env->GetFieldID(cls, "log_source", "Ljava/lang/String;"); + if (fid == 0) { + printf("Can't find field log_source\n"); + } + env->SetObjectField(ComponentStruct, fid, env->NewStringUTF(log_source)); + + // comp_location --------------------------------------- + fid = env->GetFieldID(cls, "comp_location", "Lorg/eclipse/titan/executor/jni/HostStruct;"); + jclass cls_hs = env->FindClass("org/eclipse/titan/executor/jni/HostStruct"); + if( cls_hs == NULL ) { + printf("Can't find class org.eclipse.titan.executor.jni.HostStruct\n"); + } + jfieldID fid_hs; + jmethodID mid_hs; + jobject HostStruct; + mid_hs = env->GetMethodID(cls_hs, "", "(IIII)V"); + HostStruct = env->NewObject(cls_hs, mid_hs, 3, comp_location->text_buf->get_len(), comp_location->n_components, comp_location->allowed_components.n_elements); + + if(env->ExceptionOccurred()) { + printf("error at creating HostStruct\n"); + env->ExceptionDescribe(); + env->ExceptionClear(); + } + // processing struct fields + // ip_addr + const char *ipaddr = comp_location->ip_addr->get_addr_str(); + fid_hs = env->GetFieldID(cls_hs, "ip_addr", "Ljava/lang/String;"); + if (fid_hs == 0) { + printf("Can't find field hostname\n"); + } + env->SetObjectField(HostStruct, fid_hs, env->NewStringUTF(ipaddr)); + + // hostname + fid_hs = env->GetFieldID(cls_hs, "hostname", "Ljava/lang/String;"); + if (fid_hs == 0) { + printf("Can't find field hostname\n"); + } + env->SetObjectField(HostStruct, fid_hs, env->NewStringUTF(comp_location->hostname)); + + // hostname_local + fid_hs = env->GetFieldID(cls_hs, "hostname_local", "Ljava/lang/String;"); + if (fid_hs == 0) { + printf("Can't find field hostname_local\n"); + } + env->SetObjectField(HostStruct, fid_hs, env->NewStringUTF(comp_location->hostname_local)); + + // machine_type + fid_hs = env->GetFieldID(cls_hs, "machine_type", "Ljava/lang/String;"); + if (fid_hs == 0) { + printf("Can't find field machine_type\n"); + } + env->SetObjectField(HostStruct, fid_hs, env->NewStringUTF(comp_location->machine_type)); + + // system_name + fid_hs = env->GetFieldID(cls_hs, "system_name", "Ljava/lang/String;"); + if (fid_hs == 0) { + printf("Can't find field system_name\n"); + } + env->SetObjectField(HostStruct, fid_hs, env->NewStringUTF(comp_location->system_name)); + + // system_release + fid_hs = env->GetFieldID(cls_hs, "system_release", "Ljava/lang/String;"); + if (fid_hs == 0) { + printf("Can't find field system_release\n"); + } + env->SetObjectField(HostStruct, fid_hs, env->NewStringUTF(comp_location->system_release)); + + // system_version + fid_hs = env->GetFieldID(cls_hs, "system_version", "Ljava/lang/String;"); + if (fid_hs == 0) { + printf("Can't find field system_version\n"); + } + env->SetObjectField(HostStruct, fid_hs, env->NewStringUTF(comp_location->system_version)); + + // transport_supported + fid_hs = env->GetFieldID(cls_hs, "transport_supported", "[Z"); + if (fid_hs == 0) { + printf("Can't find field transport_supported\n"); + } + jbooleanArray TransportSupported = (jbooleanArray)env->GetObjectField(HostStruct, fid_hs); + env->SetBooleanArrayRegion(TransportSupported, (jsize)0, 3,(jboolean *)comp_location->transport_supported); + + // log_source + fid_hs = env->GetFieldID(cls_hs, "log_source", "Ljava/lang/String;"); + if (fid_hs == 0) { + printf("Can't find field log_source\n"); + } + env->SetObjectField(HostStruct, fid_hs, env->NewStringUTF(comp_location->log_source)); + + // hc_state + fid_hs = env->GetFieldID(cls_hs, "hc_state", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hs == 0) { + printf("Can't find field hc_state\n"); + } + + jclass cls_hs_hc = env->FindClass("org/eclipse/titan/executor/jni/HcStateEnum"); + if( cls_hs_hc == NULL ) { + printf("Can't find class org.eclipse.titan.executor.jni.HcStateEnum\n"); + } + jfieldID fid_hs_hc = 0; + jobject ret; + switch(comp_location->hc_state) { + case mctr::HC_IDLE: + fid_hs_hc = env->GetStaticFieldID(cls_hs_hc, "HC_IDLE", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hs_hc == 0) { + printf("Can't find field HC_IDLE\n"); + } + break; + case mctr::HC_CONFIGURING: + fid_hs_hc = env->GetStaticFieldID(cls_hs_hc, "HC_CONFIGURING", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hs_hc == 0) { + printf("Can't find field HC_CONFIGURING\n"); + } + break; + case mctr::HC_ACTIVE: + fid_hs_hc = env->GetStaticFieldID(cls_hs_hc, "HC_ACTIVE", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hs_hc == 0) { + printf("Can't find field HC_ACTIVE\n"); + } + break; + case mctr::HC_OVERLOADED: + fid_hs_hc = env->GetStaticFieldID(cls_hs_hc, "HC_OVERLOADED", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hs_hc == 0) { + printf("Can't find field HC_OVERLOADED\n"); + } + break; + case mctr::HC_CONFIGURING_OVERLOADED: + fid_hs_hc = env->GetStaticFieldID(cls_hs_hc, "HC_CONFIGURING_OVERLOADED", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hs_hc == 0) { + printf("Can't find field HC_CONFIGURING_OVERLOADED\n"); + } + break; + // ----------------------------------------------- 6-7 + case mctr::HC_EXITING: + fid_hs_hc = env->GetStaticFieldID(cls_hs_hc, "HC_EXITING", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hs_hc == 0) { + printf("Can't find field HC_EXITING\n"); + } + break; + case mctr::HC_DOWN: + fid_hs_hc = env->GetStaticFieldID(cls_hs_hc, "HC_DOWN", "Lorg/eclipse/titan/executor/jni/HcStateEnum;"); + if (fid_hs_hc == 0) { + printf("Can't find field HC_DOWN\n"); + } + break; + default: + printf("Unknown hc_state_enum state\n"); + } + ret = env->GetStaticObjectField(cls_hs_hc, fid_hs_hc); + env->ExceptionClear(); + env->SetObjectField(HostStruct, fid_hs, ret); + + // hc_fd + fid_hs = env->GetFieldID(cls_hs, "hc_fd", "I"); + if (fid_hs == 0) { + printf("Can't find field hc_fd\n"); + } + env->SetIntField(HostStruct, fid_hs, (jint)comp_location->hc_fd); + + // text_buf + fid_hs = env->GetFieldID(cls_hs, "text_buf", "[B"); + if (fid_hs == 0) { + printf("Can't find field text_buf\n"); + } + jbyteArray TextBuf = (jbyteArray)env->GetObjectField(HostStruct, fid_hs); + env->SetByteArrayRegion(TextBuf, (jsize)0, comp_location->text_buf->get_len(), + const_cast((const jbyte *)text_buf->get_data())); + + // components + fid_hs = env->GetFieldID(cls_hs, "components", "[I"); + if (fid_hs == 0) { + printf("Can't find field components\n"); + } + + jintArray Components = (jintArray)env->GetObjectField(HostStruct, fid_hs); + env->SetIntArrayRegion(Components, (jsize)0, comp_location->n_components, (jint *)comp_location->components); + + // allowed_components + fid_hs = env->GetFieldID(cls_hs, "allowed_components", "[Ljava/lang/String;"); + if (fid_hs == 0) { + printf("Can't find field allowed_components\n"); + } + jobjectArray allowedComponents = (jobjectArray) env->GetObjectField(HostStruct, fid_hs); + for(int i = 0; i < comp_location->allowed_components.n_elements; i++) { + env->SetObjectArrayElement(allowedComponents, i, env->NewStringUTF(comp_location->allowed_components.elements[i])); + } + + // all_components_allowed + fid_hs = env->GetFieldID(cls_hs, "all_components_allowed", "Z"); + if (fid_hs == 0) { + printf("Can't find field all_components_allowed\n"); + } + env->SetBooleanField(HostStruct, fid_hs, (jboolean)comp_location->all_components_allowed); + + // n_active_components + fid_hs = env->GetFieldID(cls_hs, "n_active_components", "I"); + if (fid_hs == 0) { + printf("Can't find field n_active_components\n"); + } + env->SetIntField(HostStruct, fid_hs, (jint)comp_location->n_active_components); + + + env->SetObjectField(ComponentStruct, fid, HostStruct); // finally setting inner host_struct + // end of comp_location -------------------------------- + + // tc_state + fid = env->GetFieldID(cls, "tc_state", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid == 0) { + printf("Can't find field tc_state\n"); + } + + jclass cls_tc = env->FindClass("org/eclipse/titan/executor/jni/TcStateEnum"); + if( cls_tc == NULL ) { + printf("Can't find class org.eclipse.titan.executor.jni.TcStateEnum\n"); + } + jfieldID fid_tc = 0; + jobject ret_tc; + switch(tc_state) { + case mctr::TC_INITIAL: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_INITIAL", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_INITIAL\n"); + } + break; + case mctr::TC_IDLE: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_IDLE", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_IDLE\n"); + } + break; + case mctr::TC_CREATE: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_CREATE", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_CREATE\n"); + } + break; + case mctr::TC_START: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_START", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_START\n"); + } + break; + case mctr::TC_STOP: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_STOP", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_STOP\n"); + } + break; + // ----------------------------------------------- 6-10 + case mctr::TC_KILL: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_KILL", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_KILL\n"); + } + break; + case mctr::TC_CONNECT: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_CONNECT", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_CONNECT\n"); + } + break; + case mctr::TC_DISCONNECT: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_DISCONNECT", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_DISCONNECT\n"); + } + break; + case mctr::TC_MAP: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_MAP", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_MAP\n"); + } + break; + case mctr::TC_UNMAP: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_UNMAP", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_UNMAP\n"); + } + break; + // ----------------------------------------------- 11-15 + case mctr::TC_STOPPING: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_STOPPING", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_STOPPING\n"); + } + break; + case mctr::TC_EXITING: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_EXITING", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_EXITING\n"); + } + break; + case mctr::TC_EXITED: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_EXITED", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_EXITED\n"); + } + break; + case mctr::MTC_CONTROLPART: + fid_tc = env->GetStaticFieldID(cls_tc, "MTC_CONTROLPART", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field MTC_CONTROLPART\n"); + } + break; + case mctr::MTC_TESTCASE: + fid_tc = env->GetStaticFieldID(cls_tc, "MTC_TESTCASE", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field MTC_TESTCASE\n"); + } + break; + // ----------------------------------------------- 16-20 + case mctr::MTC_ALL_COMPONENT_STOP: + fid_tc = env->GetStaticFieldID(cls_tc, "MTC_ALL_COMPONENT_STOP", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field MTC_ALL_COMPONENT_STOP\n"); + } + break; + case mctr::MTC_ALL_COMPONENT_KILL: + fid_tc = env->GetStaticFieldID(cls_tc, "MTC_ALL_COMPONENT_KILL", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field MTC_ALL_COMPONENT_KILL\n"); + } + ret_tc = env->GetStaticObjectField(cls_tc, fid_tc); + env->ExceptionClear(); + break; + case mctr::MTC_TERMINATING_TESTCASE: + fid_tc = env->GetStaticFieldID(cls_tc, "MTC_TERMINATING_TESTCASE", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field MTC_TERMINATING_TESTCASE\n"); + } + break; + case mctr::MTC_PAUSED: + fid_tc = env->GetStaticFieldID(cls_tc, "MTC_PAUSED", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field MTC_PAUSED\n"); + } + break; + case mctr::PTC_FUNCTION: + fid_tc = env->GetStaticFieldID(cls_tc, "PTC_FUNCTION", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field PTC_FUNCTION\n"); + } + break; + // ----------------------------------------------- 21-25 + case mctr::PTC_STARTING: + fid_tc = env->GetStaticFieldID(cls_tc, "PTC_STARTING", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field PTC_STARTING\n"); + } + break; + case mctr::PTC_STOPPED: + fid_tc = env->GetStaticFieldID(cls_tc, "PTC_STOPPED", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field PTC_STOPPED\n"); + } + break; + case mctr::PTC_KILLING: + fid_tc = env->GetStaticFieldID(cls_tc, "PTC_KILLING", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field PTC_KILLING\n"); + } + break; + case mctr::PTC_STOPPING_KILLING: + fid_tc = env->GetStaticFieldID(cls_tc, "PTC_STOPPING_KILLING", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field PTC_STOPPING_KILLING\n"); + } + break; + case mctr::PTC_STALE: + fid_tc = env->GetStaticFieldID(cls_tc, "PTC_STALE", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field PTC_STALE\n"); + } + break; + // ----------------------------------------------- 26 + case mctr::TC_SYSTEM: + fid_tc = env->GetStaticFieldID(cls_tc, "TC_SYSTEM", "Lorg/eclipse/titan/executor/jni/TcStateEnum;"); + if (fid_tc == 0) { + printf("Can't find field TC_SYSTEM\n"); + } + break; + default: + printf("Unknown tc_state_enum state\n"); + } + ret_tc = env->GetStaticObjectField(cls_tc, fid_tc); + env->ExceptionClear(); + env->SetObjectField(ComponentStruct, fid, ret_tc); + + // local_verdict + fid = env->GetFieldID(cls, "local_verdict", "Lorg/eclipse/titan/executor/jni/VerdictTypeEnum;"); + if (fid == 0) { + printf("Can't find field local_verdict\n"); + } + jclass cls_v = env->FindClass("org/eclipse/titan/executor/jni/VerdictTypeEnum"); + if( cls_v == NULL ) { + printf("Can't find class org.eclipse.titan.executor.jni.VerdictTypeEnum\n"); + } + jfieldID fid_v = 0; + jobject ret_v; + switch(local_verdict) { + case NONE: + fid_v = env->GetStaticFieldID(cls_v, "NONE", "Lorg/eclipse/titan/executor/jni/VerdictTypeEnum;"); + if (fid_v == 0) { + printf("Can't find field NONE\n"); + } + break; + case PASS: + fid_v = env->GetStaticFieldID(cls_v, "PASS", "Lorg/eclipse/titan/executor/jni/VerdictTypeEnum;"); + if (fid_v == 0) { + printf("Can't find field PASS\n"); + } + break; + case INCONC: + fid_v = env->GetStaticFieldID(cls_v, "INCONC", "Lorg/eclipse/titan/executor/jni/VerdictTypeEnum;"); + if (fid_v == 0) { + printf("Can't find field INCONC\n"); + } + break; + case FAIL: + fid_v = env->GetStaticFieldID(cls_v, "FAIL", "Lorg/eclipse/titan/executor/jni/VerdictTypeEnum;"); + if (fid_v == 0) { + printf("Can't find field FAIL\n"); + } + break; + case ERROR: + fid_v = env->GetStaticFieldID(cls_v, "ERROR", "Lorg/eclipse/titan/executor/jni/VerdictTypeEnum;"); + if (fid_v == 0) { + printf("Can't find field ERROR\n"); + } + break; + default: + printf("Unknown tc_state_enum state\n"); + } + ret_v = env->GetStaticObjectField(cls_v, fid_v); + env->ExceptionClear(); + env->SetObjectField(ComponentStruct, fid, ret_v); + + // tc_fd + fid = env->GetFieldID(cls, "tc_fd", "I"); + if (fid == 0) { + printf("Can't find field tc_fd\n"); + } + env->SetIntField(ComponentStruct, fid, (jint)tc_fd); + + // text_buf + fid = env->GetFieldID(cls, "text_buf", "[B"); + if (fid == 0) { + printf("Can't find field text_buf\n"); + } + jbyteArray TextBuf_c = (jbyteArray)env->GetObjectField(ComponentStruct, fid); + env->SetByteArrayRegion(TextBuf_c, (jsize)0, text_buf->get_len(), + const_cast((const jbyte *)text_buf->get_data())); + + // tc_fn_name + fid = env->GetFieldID(cls, "tc_fn_name", "Lorg/eclipse/titan/executor/jni/QualifiedName;"); + if (fid == 0) { + printf("Can't find field tc_fn_name\n"); + } + jclass cls_qualified = env->FindClass("org/eclipse/titan/executor/jni/QualifiedName"); + if( cls_qualified == NULL ) { + printf("Can't find class org.eclipse.titan.executor.jni.QualifiedName\n"); + } + jmethodID mid_qualified; + jobject QualifiedName; + mid_qualified = env->GetMethodID(cls_qualified, "", "(Ljava/lang/String;Ljava/lang/String;)V"); + QualifiedName = env->NewObject(cls_qualified, mid_qualified, env->NewStringUTF(tc_fn_name.module_name), + env->NewStringUTF(tc_fn_name.definition_name)); + env->SetObjectField(ComponentStruct, fid, QualifiedName); + + // return_type + fid = env->GetFieldID(cls, "return_type", "Ljava/lang/String;"); + if (fid == 0) { + printf("Can't find field return_type\n"); + } + env->SetObjectField(ComponentStruct, fid, env->NewStringUTF(return_type)); + + // return_value_len + fid = env->GetFieldID(cls, "return_value_len", "I"); + if (fid == 0) { + printf("Can't find field return_value_len\n"); + } + env->SetIntField(ComponentStruct, fid, (jint)return_value_len); + + // is_alive + fid = env->GetFieldID(cls, "is_alive", "Z"); + if (fid == 0) { + printf("Can't find field is_alive\n"); + } + env->SetBooleanField(ComponentStruct, fid, (jboolean)is_alive); + + // stop_requested + fid = env->GetFieldID(cls, "stop_requested", "Z"); + if (fid == 0) { + printf("Can't find field stop_requested\n"); + } + env->SetBooleanField(ComponentStruct, fid, (jboolean)stop_requested); + + // process_killed + fid = env->GetFieldID(cls, "process_killed", "Z"); + if (fid == 0) { + printf("Can't find field process_killed\n"); + } + env->SetBooleanField(ComponentStruct, fid, (jboolean)process_killed); + + return ComponentStruct; +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_release_1data + (JNIEnv *, jobject) { + MainController::release_data(); +} + +JNIEXPORT jstring JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1mc_1state_1name + (JNIEnv *env, jobject, jobject state) { + jclass cls = env->GetObjectClass(state); + if( cls == NULL ) { + printf("Can't find class org.eclipse.titan.executor.jni.McStateEnum\n"); + } + jmethodID mid = env->GetMethodID(cls, "getValue", "()I"); + if( mid == NULL ) { + printf("Can't find method getValue\n"); + } + int value = env->CallIntMethod(state, mid); + const char *state_name = MainController::get_mc_state_name((mctr::mc_state_enum)value); + return (env->NewStringUTF(state_name)); +} + +JNIEXPORT jstring JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1hc_1state_1name + (JNIEnv *env, jobject, jobject state) { + jclass cls = env->GetObjectClass(state); + if( cls == NULL ) { + printf("Can't find class org.eclipse.titan.executor.jni.HcStateEnum\n"); + } + jmethodID mid = env->GetMethodID(cls, "getValue", "()I"); + if( mid == NULL ) { + printf("Can't find method getValue\n"); + } + int value = env->CallIntMethod(state, mid); + const char *state_name = MainController::get_hc_state_name((mctr::hc_state_enum)value); + return (env->NewStringUTF(state_name)); +} + +JNIEXPORT jstring JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1tc_1state_1name + (JNIEnv *env, jobject, jobject state) { + jclass cls = env->GetObjectClass(state); + if( cls == NULL ) { + printf("Can't find class org.eclipse.titan.executor.jni.TcStateEnum\n"); + } + jmethodID mid = env->GetMethodID(cls, "getValue", "()I"); + if( mid == NULL ) { + printf("Can't find method getValue\n"); + } + int value = env->CallIntMethod(state, mid); + const char *state_name = MainController::get_tc_state_name((mctr::tc_state_enum)value); + return (env->NewStringUTF(state_name)); +} + +JNIEXPORT jstring JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1transport_1name + (JNIEnv *env, jobject, jobject transport) { + jclass cls = env->GetObjectClass(transport); + if( cls == NULL ) { + printf("Can't find class org.eclipse.titan.executor.jni.TransportTypeEnum\n"); + } + jmethodID mid = env->GetMethodID(cls, "getValue", "()I"); + if( mid == NULL ) { + printf("Can't find method getValue\n"); + } + int value = env->CallIntMethod(transport, mid); + const char *transport_name = MainController::get_transport_name((transport_type_enum)value); + return (env->NewStringUTF(transport_name)); +} + +// ******************************************************* +// Other native functions +// ******************************************************* + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_check_1mem_1leak + (JNIEnv *env, jobject, jstring program_name) { + jboolean iscopy; + const char *p_name = env->GetStringUTFChars(program_name, &iscopy); + check_mem_leak(p_name); + env->ReleaseStringUTFChars(program_name, p_name); +} + +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_print_1license_1info + (JNIEnv *, jobject) { +#ifdef LICENSE + print_license_info(); +#endif +} + +JNIEXPORT jint JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_check_1license + (JNIEnv *, jobject) { + int max_ptcs; +#ifdef LICENSE + license_struct lstr; + init_openssl(); + load_license(&lstr); + if (!verify_license(&lstr)) { + free_license(&lstr); + free_openssl(); + exit(EXIT_FAILURE); + } + if (!check_feature(&lstr, FEATURE_MCTR)) { + fputs("The license key does not allow the starting of TTCN-3 " + "Main Controller.\n", stderr); + return 2; + } + max_ptcs = lstr.max_ptcs; + free_license(&lstr); + free_openssl(); +#else + max_ptcs = -1; +#endif + return (jint)max_ptcs; +} + +JNIEXPORT jstring JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_readPipe + (JNIEnv *env, jobject) { + char *buf = Jnimw::userInterface->read_pipe(); + return (env->NewStringUTF(buf)); +} + +JNIEXPORT jboolean JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_isPipeReadable + (JNIEnv *, jobject) { + return ((jboolean)Jnimw::userInterface->is_pipe_readable()); +} + +JNIEXPORT jlong JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_getSharedLibraryVersion + (JNIEnv *, jclass) { + return (jlong) TTCN3_VERSION; +} diff --git a/JNI/org_eclipse_titan_executor_jni_JNIMiddleWare.h b/JNI/org_eclipse_titan_executor_jni_JNIMiddleWare.h new file mode 100644 index 0000000..d1443dd --- /dev/null +++ b/JNI/org_eclipse_titan_executor_jni_JNIMiddleWare.h @@ -0,0 +1,316 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 +/////////////////////////////////////////////////////////////////////////////// +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_eclipse_titan_executor_jni_JNIMiddleWare */ + +#ifndef _Included_org_eclipse_titan_executor_jni_JNIMiddleWare +#define _Included_org_eclipse_titan_executor_jni_JNIMiddleWare +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: init + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_init + (JNIEnv *, jobject, jint); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: terminate + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_terminate + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: add_host + * Signature: (Ljava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_add_1host + (JNIEnv *, jobject, jstring, jstring); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: assign_component + * Signature: (Ljava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_assign_1component + (JNIEnv *, jobject, jstring, jstring); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: destroy_host_groups + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_destroy_1host_1groups + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: set_kill_timer + * Signature: (D)V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_set_1kill_1timer + (JNIEnv *, jobject, jdouble); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: start_session + * Signature: (Ljava/lang/String;IZ)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_start_1session + (JNIEnv *, jobject, jstring, jint, jboolean); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: shutdown_session + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_shutdown_1session + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: configure + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_configure + (JNIEnv *, jobject, jstring); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: set_cfg_file + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_set_1cfg_1file + (JNIEnv *, jobject, jstring); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: get_mc_host + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1mc_1host + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: get_port + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1port + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: create_mtc + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_create_1mtc + (JNIEnv *, jobject, jint); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: exit_mtc + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_exit_1mtc + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: execute_control + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_execute_1control + (JNIEnv *, jobject, jstring); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: execute_testcase + * Signature: (Ljava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_execute_1testcase + (JNIEnv *, jobject, jstring, jstring); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: get_execute_cfg_len + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1execute_1cfg_1len + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: execute_cfg + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_execute_1cfg + (JNIEnv *, jobject, jint); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: stop_after_testcase + * Signature: (Z)V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_stop_1after_1testcase + (JNIEnv *, jobject, jboolean); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: continue_testcase + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_continue_1testcase + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: stop_execution + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_stop_1execution + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: get_state + * Signature: ()Lorg/eclipse/titan/executor/jni/McStateEnum; + */ +JNIEXPORT jobject JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1state + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: get_stop_after_testcase + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1stop_1after_1testcase + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: get_nof_hosts + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1nof_1hosts + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: get_host_data + * Signature: (I)Lorg/eclipse/titan/executor/jni/HostStruct; + */ +JNIEXPORT jobject JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1host_1data + (JNIEnv *, jobject, jint); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: get_component_data + * Signature: (I)Lorg/eclipse/titan/executor/jni/ComponentStruct; + */ +JNIEXPORT jobject JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1component_1data + (JNIEnv *, jobject, jint); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: release_data + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_release_1data + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: get_mc_state_name + * Signature: (Lorg/eclipse/titan/executor/jni/McStateEnum;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1mc_1state_1name + (JNIEnv *, jobject, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: get_hc_state_name + * Signature: (Lorg/eclipse/titan/executor/jni/HcStateEnum;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1hc_1state_1name + (JNIEnv *, jobject, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: get_tc_state_name + * Signature: (Lorg/eclipse/titan/executor/jni/TcStateEnum;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1tc_1state_1name + (JNIEnv *, jobject, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: get_transport_name + * Signature: (Lorg/eclipse/titan/executor/jni/TransportTypeEnum;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_get_1transport_1name + (JNIEnv *, jobject, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: check_mem_leak + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_check_1mem_1leak + (JNIEnv *, jobject, jstring); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: print_license_info + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_print_1license_1info + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: check_license + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_check_1license + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: readPipe + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_readPipe + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: isPipeReadable + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_isPipeReadable + (JNIEnv *, jobject); + +/* + * Class: org_eclipse_titan_executor_jni_JNIMiddleWare + * Method: getSharedLibraryVersion + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_org_eclipse_titan_executor_jni_JNIMiddleWare_getSharedLibraryVersion + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..766ca7e --- /dev/null +++ b/Makefile @@ -0,0 +1,91 @@ +############################################################################### +# 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 +############################################################################### +# Main Makefile for the TTCN-3 Test Executor +# For use with GNU make only. + +TOP := . +include $(TOP)/Makefile.cfg + +# Dirlist for "all", "clean", "distclean" +ALLDIRS := common compiler2 repgen xsdconvert + +ifndef MINGW + ALLDIRS += core core2 mctr2 loggerplugins +endif + +# JNI not supported on Cygwin or Mingw +ifneq ($(PLATFORM), WIN32) + ifeq ($(JNI), yes) + ALLDIRS += JNI + endif +endif + +#ALLDIRS += ctags + +# Dirlist for "dep", "tags" +DEPDIRS := $(ALLDIRS) + +ALLDIRS += usrguide + +# Dirlist for "install" +INSTALLDIRS := $(ALLDIRS) + +INSTALLDIRS += etc help hello + +########################################################### + +all run clean distclean: + @for dir in $(ALLDIRS); do \ + $(MAKE) -C $$dir $@ || exit; \ + done + +dep tags: + @for dir in $(DEPDIRS); do \ + $(MAKE) -C $$dir $@ || exit; \ + done + +install: + if test -h $(TTCN3_DIR); then \ + echo $(TTCN3_DIR) is a symlink, you cannot be serious; exit 1; fi +ifdef MINGW + $(info cross your fingers...) +endif + -rm -rf $(TTCN3_DIR) +ifeq ($(INCLUDE_EXTERNAL_LIBS), yes) + mkdir -p $(TTCN3_DIR)/lib + cp -d $(OPENSSL_DIR)/lib/libcrypto.so* $(TTCN3_DIR)/lib + cp -d $(XMLDIR)/lib/libxml2.so* $(TTCN3_DIR)/lib +endif + @for dir in $(INSTALLDIRS); do \ + $(MAKE) -C $$dir $@ || exit; \ + done +ifeq ($(LICENSING), yes) + mkdir -p $(ETCDIR)/license + cp license/license.dat $(ETCDIR)/license +endif + chmod -R +r,go-w $(TTCN3_DIR) + +# check is the standard GNU target for running tests +# (avoids clash with shell builtin 'test') +check: + make -C regression_test report + +ifneq (,$(findstring prereq,$(MAKECMDGOALS))) +# Export all variables into the environment for the prereq target +export +endif + + +# no need to include Makefile.genrules + +.PHONY: all clean distclean dep tags install psi dox check confess prereq + + +Makefile.personal: SHELL:=/bin/bash +Makefile.personal: + if [ -f $(TOP)/makefiles/$@.$${HOSTNAME:=$${COMPUTERNAME}} ]; then ln -s $(TOP)/makefiles/$@.$${HOSTNAME} $@; else touch $@; fi diff --git a/Makefile.cfg b/Makefile.cfg new file mode 100644 index 0000000..6c8e47b --- /dev/null +++ b/Makefile.cfg @@ -0,0 +1,359 @@ +############################################################################### +# Copyright (c) 2000-2014 Ericsson Telecom AB +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################### +ifndef TOP +$(error please define TOP) +endif + +# Configurations for the Free Open Source Software version, if available +ifneq ($(wildcard $(TOP)/MakefileFOSS.cfg), ) + include $(TOP)/MakefileFOSS.cfg +else + # Set whether licensing is enabled: (yes or no) + LICENSING := yes + + # Set whether to send usage statistics: (yes or no) + USAGE_STATS := yes +endif + +# Define SRCDIR to the root of Titan sources to enable out-of-tree build +#SRCDIR := ${HOME}/workspace/TTCNv3 + +# Set these variables to fit your system: + +# The target directory where the Test Executor will be installed to: +TTCN3_DIR := ${TOP}/Install + +# New installed files are run from make install, so they are added to the PATH +PATH := ${PATH}:${TTCN3_DIR}/bin + +# Set it to 'yes' for developing or 'no' for release. +DEBUG := no + +# Set it to 'yes' to generate coverage data (requires DEBUG=yes) +COVERAGE := no + +# Your platform. Allowed values: SOLARIS, SOLARIS8, LINUX, FREEBSD, +# WIN32. Decided automagically if not defined (recommended). +# PLATFORM := + +# Uncomment the following for "native" Win32 +#MINGW := -DMINGW -mno-cygwin + +# Utility for building lexical analyzers (tokenizers): +FLEX := flex + +# Utility for building parsers: +BISON := bison + +# The C compiler used for building: +CC := gcc + +# The C++ compiler used for building: +CXX := g++ + +# generate userguide at install ('make release' always generates it) +GEN_PDF := no + +# Set whether to build the CLI for MC: (yes or no) +CLI := yes + +# set whether to build the JNI native library: (yes or no) +JNI := yes + +# Path of the Java Developement Kit installation +# (must be at least version 1.5.0_10) +JDKDIR := /mnt/TTCN/Tools/jdk1.5.0_11 + +# Path of OpenSSL installation: (always required) +OPENSSL_DIR := default + +# Location of libxml2 +XMLDIR := default + +## ## ## ## ## Variables below are automatically set ## ## ## ## ## + +# Flags for the C(++) preprocessor: +# Prevent a warning about yyinput being defined but not used +CPPFLAGS := -DYY_NO_INPUT +ifeq ($(DEBUG), yes) + CPPFLAGS += -DMEMORY_DEBUG -DFATAL_DEBUG +else + CPPFLAGS += -DNDEBUG +endif + +# MingW flags need to be passed to the preprocessor during ctags configure +CPPFLAGS += $(MINGW) + + +# Flags shared between C and C++ +COMPILERFLAGS := -Wall + +# 'Hardcore' settings +# Unlikely to work for GCC below 4.x +#COMPILERFLAGS += -Werror -pedantic -W -Wno-unused-parameter -O1 + +# Flags for the C compiler. +# std=gnu9x shuts up warnings about long long and variadic macros +CCFLAGS = $(COMPILERFLAGS) -std=gnu9x +ifeq ($(DEBUG), yes) + CCFLAGS += -g + CCFLAGS += -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align \ + -Wstrict-prototypes +else + CCFLAGS += -O2 +endif + +# Flags for the C++ compiler: +CXXFLAGS = $(COMPILERFLAGS) -Wno-long-long + +# Only the default Cygwin compiler can be used for Mingw. +# Its version is 3.4.4, too low. +ifndef MINGW +# Only GCC 4.x understands -Wno-variadic-macros, comment out for lower versions +#CXXFLAGS += -Wno-variadic-macros +endif + +ifeq ($(DEBUG), yes) + CXXFLAGS += -g + CXXFLAGS += -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align +else + CXXFLAGS += -O2 +endif + +# Flags for the C/C++ compilers to generate dependency list (-M or -MM +# for gcc or clang, -xM or -xM1 for Sun C compiler). + +ifneq ($(filter gcc% clang%, $(notdir $(CC))),) +CCDEPFLAG := -MM +CXXDEPFLAG := -MM +else +# Let's hope it's the Sun compiler +CCDEPFLAG := -xM1 +CXXDEPFLAG := -xM1 +endif + +# The command for maintaining static libraries: +AR := ar + +# The command for building the shared libraries: +# It shall be set to either "$(CXX) -G" or "$(CXX) -shared" depending +# on the linker you use. +LD = $(CXX) -shared + +# Flags for linking binary executables (e.g. for profiling): +LDFLAGS = $(MINGW) +ifeq ($(DEBUG), yes) + LDFLAGS += -g +endif + +# The command for removing symbol table from the executables: +STRIP := strip + +# Flags for flex: +FLEXFLAGS := -B -s -Cr +ifeq ($(DEBUG), yes) + FLEXFLAGS += -b -p +# FLEXFLAGS += -d +else +# Comment out the line below if flex version 2.5.4[a] is used. +# This version does not support optimized tables together with yylineno. + FLEXFLAGS += -Cfe +endif + +# Flags for bison: +BISONFLAGS := -d +ifeq ($(DEBUG), yes) + BISONFLAGS += -t -v +endif + +ifeq ($(COVERAGE), yes) +ifneq ($(DEBUG), yes) + $(error TURN ON DEBUG MODE FOR COVERAGE) +else + CPPFLAGS += -DCOVERAGE_BUILD + COMPILERFLAGS += -fprofile-arcs -ftest-coverage + LDFLAGS += -fprofile-arcs -ftest-coverage -lgcov +endif +endif + +# Directory which contains the code for POSIX regular expression handling. +# It is needed on platforms where the system's libc does not support POSIX +# regexps. This is the case for Mingw. +ifdef MINGW +# If your platform isn't Mingw but lacks POSIX regular expressions, +# comment out the ifdef/endif +REGEX_DIR := /mnt/TTCN/Tools/CPP/regex-glibc-2.5.1 +endif + +# Warning! Never set the above directories to /usr. +# If your OpenSSL, Qt is installed under /usr you'd better set +# these variables to a fake (non-existent) directory. If this is the case, +# gcc will find the required headers and libs anyway, but -I/usr/include +# might confuse it. + +# This is especially true on Windows with Mingw installed as a Cygwin package. +# -mno-cygwin alters the include serach path to find the Mingw headers. +# Passing -I/usr/include would cause the Mingw compiler to read the Cygwin +# headers, and the compilation will fail. + +# The path name where the LaTeX binaries can be found. (optional) +# If this variable is not defined the User Documentation will not be built +# or installed. +TEXPATH := /usr/local/teTeX2.0.2/bin/sparc-sun-solaris2.8 + +# Override common settings with personal preferences if needed +-include $(TOP)/Makefile.personal + +########################################################################### +# You don't have to alter anything below this line. + +# Setting PLATFORM automagically if it is not defined. +ifndef PLATFORM +PLATFORM1 := $(shell uname -s) +PLATFORM2 := $(shell uname -r) +PLATFORM3 := $(shell uname -m) +ifeq ($(PLATFORM1), SunOS) + ifneq ($(PLATFORM2), 5.6) + PLATFORM := SOLARIS8 + PLATSUFFIX = -sol8 + else + PLATFORM := SOLARIS + PLATSUFFIX = -sol6 + endif # 5.8 +endif # SunOS +ifeq ($(PLATFORM1), Linux) + PLATFORM := LINUX + PLATSUFFIX = -linux +endif # Linux +ifeq ($(PLATFORM1), FreeBSD) + PLATFORM := FREEBSD +endif # FreeBSD +ifeq ($(findstring CYGWIN, $(PLATFORM1)), CYGWIN) + PLATFORM := WIN32 + PLATSUFFIX = -cygwin +endif # CYGWIN +endif # ifndef PLATFORM +ifndef PLATFORM + PLATFORM := $(error PLEASE CHECK THE PLATFORM SETTINGS) +endif # ifndef PLATFORM + +# Derived variables, which you should never change. + +ifdef MINGW + +# Target directory for binaries: +BINDIR := $(TTCN3_DIR)/programs +# Target directory for manual pages: +MANDIR := $(TTCN3_DIR)/manuals +# Target directory for other files (nedit/xemacs additions, etc.) +ETCDIR := $(TTCN3_DIR) + +else + +# Target directory for binaries: +BINDIR := $(TTCN3_DIR)/bin +# Target directory for manual pages: +MANDIR := $(TTCN3_DIR)/man +# Target directory for other files (nedit/xemacs additions, etc.) +ETCDIR := $(TTCN3_DIR)/etc + +endif + +# Target directory for header files: +INCDIR := $(TTCN3_DIR)/include +# Target directory for libraries: +LIBDIR := $(TTCN3_DIR)/lib +# Target directory for html help pages: +HELPDIR := $(TTCN3_DIR)/help +# Target directory for the documentation: +DOCDIR := $(TTCN3_DIR)/doc +# Target directory for the demo "Hello World!" +DEMODIR := $(TTCN3_DIR)/demo + +CPPFLAGS += -D$(PLATFORM) + +ifeq ($(LICENSING), yes) + CPPFLAGS += -DLICENSE + LICENSE_LIBS = -L$(OPENSSL_DIR)/lib -lcrypto +else + LICENSE_LIBS := +endif + +ifeq ($(USAGE_STATS), yes) + CPPFLAGS += -DUSAGE_STATS +endif + +# Windows/Cygwin specific settings +ifeq ($(PLATFORM), WIN32) + EXESUFFIX := .exe + LDFLAGS += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc + + ifdef MINGW + MINGW_LIBS := -lgdi32 + endif +else + EXESUFFIX := + + ifdef MINGW + $(error MingW not supported on $(PLATFORM)) + endif + + CCFLAGS += -fPIC + CXXFLAGS += -fPIC + LDFLAGS += -fPIC +endif + +# Try to use -isystem for Qt headers (this is a GCC feature). +# This avoids the myriads of warnings issued for the Qt headers. +ifneq (,$(findstring SOLARIS,$(PLATFORM))) +# Avoid using it on Solaris, because +# -isystem puts an implicit "extern C" around every system header, +# which causes compilation of Qt headers to fail miserably :-( +# (this could be fixed by recompiling GCC) + INCLUDEQT := -I +else +# Not Solaris + INCLUDEQT := -isystem +endif + +# Setting EPOLL usage - It is Linux specific +ifeq ($(PLATFORM), LINUX) + CPPFLAGS += -DUSE_EPOLL +endif + +#not useful in compiler2/asn1, for example +#REL_DIR := $(notdir $(CURDIR)) + +export ABS_TOP := $(abspath $(TOP))/ +ifeq "$(ABS_TOP)" "/" +# abspath only from GNU make 3.81, here's a replacement +ABS_TOP := $(shell cd $(TOP); pwd)/ +endif + +ifdef SRCDIR + +REL_DIR := $(subst $(ABS_TOP),,$(CURDIR)) + +ABS_SRC := $(SRCDIR)/$(REL_DIR) + +CPPFLAGS += -I. -I$(ABS_SRC) + +SRC_TOP := $(SRCDIR) + +else + +ABS_SRC := $(abspath $(CURDIR)) +ifeq "$(ABS_SRC)" "" +ABS_SRC := $(shell cd $(CURDIR); pwd) +endif + +SRC_TOP := $(TOP) + +endif + + diff --git a/Makefile.genrules b/Makefile.genrules new file mode 100644 index 0000000..b33ef4c --- /dev/null +++ b/Makefile.genrules @@ -0,0 +1,160 @@ +############################################################################### +# 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 +############################################################################### +# General stuff (to be included at the end of makefiles). The +# following variables are used: DEPFILES, SUBDIRS... + +tags: $(SOURCES) +ifdef SUBDIRS + @for i in $(SUBDIRS) ; do \ + (cd $$i && $(MAKE) tags) || exit 1; \ + done +endif + etags --members *.hh *.h *.c *.cc + +dep: +ifdef SUBDIRS + @for i in $(SUBDIRS) ; do \ + (cd $$i && $(MAKE) dep) || exit 1; \ + done +endif +ifdef DEPFILES + $(MAKE) $(DEPFILES) +endif + +clean: +ifdef SUBDIRS + @for i in $(SUBDIRS) ; do \ + (cd $$i && $(MAKE) clean) || exit 1; \ + done +endif + $(RM) $(TARGETS) $(OBJECTS) $(TOBECLEANED) + +distclean: +ifdef SUBDIRS + @for i in $(SUBDIRS) ; do \ + (cd $$i && $(MAKE) distclean) || exit 1; \ + done +endif + $(RM) $(TARGETS) $(OBJECTS) $(TOBECLEANED) \ + $(GENERATED_HEADERS) $(GENERATED_SOURCES) \ + $(GENERATED_OTHERS) \ + $(DEPFILES) TAGS *.gcno *.gcda + +# This target allows us to "make ../clean" +../% $(foreach dir, $(SUBDIRS), $(dir)/%): + cd $(dir $@) && $(MAKE) $(notdir $@) + +# General rules to compile C(++) files. +# +# These macros implement "silent" rules during building. +# Define the V make variable or environment variable to a nonzero value to get +# the exact call to the compiler: e.g. make V=1 +# +# Define the VD variable to get the exact (verbose) action while +# generating dependencies. +# +NULL := +SPACE := ${NULL} ${NULL} + +DEF_V := 0 +DEF_VD:= 0 + +V_CC_0 = @echo " (CC) " $<;$(SPACE) +V_CXX_0 = @echo " (C++) " $<;$(SPACE) +V_DEP_0 = @echo " (dep) " $<;$(SPACE) + +V_CC_ = $(V_CC_$(DEF_V)) +V_CXX_ = $(V_CXX_$(DEF_V)) +V_DEP_ = $(V_DEP_$(DEF_VD)) + +V_CC = $(V_CC_$(V)) +V_CXX = $(V_CXX_$(V)) +V_DEP = $(V_DEP_$(VD)) + +%.o: %.c + $(V_CC)$(CC) -c $(CPPFLAGS) $(CCFLAGS) $< -o $@ + +%.o: %.cc + $(V_CXX)$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@ + +# Preprocess C/C++ files +%.i: %.c + $(CC) -E $(CPPFLAGS) $(CCFLAGS) \ + $< > $@ + +%.ii: %.cc + $(CXX) -E $(CPPFLAGS) $(CXXFLAGS) \ + $< > $@ + +# General rules to create the dependency file. + +%.d: %.c + $(V_DEP)set -e; $(CC) $(CCDEPFLAG) $(CPPFLAGS) $< \ + | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@; \ + [ -s $@ ] || rm -f $@ + +%.d: %.cc + $(V_DEP)set -e; $(CXX) $(CXXDEPFLAG) $(CPPFLAGS) $< \ + | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@; \ + [ -s $@ ] || rm -f $@ + +ifdef DEPFILES + ifndef MAKECMDGOALS + DEPFILES_NEEDED := yes + else + DEPFILES_NEEDED := $(filter-out clean distclean, $(MAKECMDGOALS)) + endif + ifdef DEPFILES_NEEDED + DEPFILES_INCLUDE := $(filter-out $(MAKECMDGOALS), $(DEPFILES)) + ifdef DEPFILES_INCLUDE + ifeq (,$(findstring n,$(MAKEFLAGS))) + # -n was *not* given to make + -include $(DEPFILES_INCLUDE) + endif + endif + endif +endif + +# Building PDFs from man pages (for MinGW) +%.pdf: %.1 + man2pdf ./$< $@ +# The "./" prefix is important, it tells man that the input is a filename, +# so it shouldn't search through MANPATH. + +# List of fake targets: +.PHONY: all install tags dep clean distclean + +# Disable all built-in suffix rules of make +.SUFFIXES: + +# Do not delete generated headers while building .d files +# (.PRECIOUS would also keep them if make is killed) +.SECONDARY: $(GENERATED_HEADERS) + +ifdef SRCDIR + +REQUIRED_MAKE_VERSION = 3.81 +# 3.80 is known not to work; 3.82 does work +REAL_MAKE_VERSION = $(firstword $(MAKE_VERSION)) +EARLIER_MAKE_VERSION = $(firstword $(sort $(REAL_MAKE_VERSION) $(REQUIRED_MAKE_VERSION))) +ifeq "$(REQUIRED_MAKE_VERSION)" "$(EARLIER_MAKE_VERSION)" + +# Declare a search path for every source. +# "vpath %.cc $(ABS_SRC)" would lump in generated .cc files, +# potentially picking up generated files laying around in the source dir +# instead of generating them in the build dir. +$(foreach src, $(STATIC_SOURCES) $(ORIGINATORS), $(eval vpath $(src) $(ABS_SRC))) + +else + +# alas, make 3.80 can't cope with the "foreach/eval vpath" above +#$(warning no OOBE with make $(MAKE_VERSION)) + +endif + +endif diff --git a/README.cygwin b/README.cygwin new file mode 100644 index 0000000..43be04a --- /dev/null +++ b/README.cygwin @@ -0,0 +1,116 @@ +Cygwin setup + - If Cygwin is installed already, refresh your Cygwin installation + Titan is always build for the newest Cygwin version available. + Start the Cygwin setup utility (see below), it will refresh your + installed Cygwin packages to the newest versions. + - If Cygwin is not installed yet: + + (A) Download and execute the latest cygwin installer utility, + please use the 64-bit version installer: + https://cygwin.com/setup-x86_64.exe + + (B) Select Install from Internet (recommended to save local disk space) + + (C) Choose Cygwin installation root directory (C:\cygwin is recommended) + Select All Users, or Just Me. + + (D) Select "Local Package Directory" (typically the same directory, + where the setup....exe Cygwin installer utility is stored). + + (E) Use Internet Explorer Proxy Settings (recommended). + + (F) Select a download mirror site. + + (G) In the package selection dialog, + Note: You can select different views to find the required packages + easier and/or search the packages via the search field. + + There are 3 hierarchical levels of minimally required packages, + depending on your task. + Note: Cygwin installer will automatically select the packages the + manually selected ones are depending on; do NOT deselect + any automatically selected package! + a) Test execution ONLY (command line or from Eclipse Executor): + Base: (Default setting of the installer) + Net: openssl + Tcl: expect + b) Test case development: in addition to the above select the + following packages: + Devel: binutils + Devel: gcc-g++ + Devel: make + Libs: libxml2-devel + Net: openssl-devel (automatically installs Net:openssl + as well, if selected) + c) To compile your own Titan Cygwin binary: in addition to the + above, select the following packages: + Devel: bison + Devel: ctags + Devel: cygwin32-expat + Devel: diffstat + Devel: flex + Devel: gcc-core + Editors: (optional) + Libs: libncurses-devel + Libs: libreadline-devel + + If, after selecting the required packages and clicking on the + "Next" button, a "Resolving Dependcies" window lists further + required packages, ensure that the "Select required packages + (RECOMMENDED)" checkbox is checked and click the "Next" button. + + (H) Select the Create icon on Desktop checkbox + + (I) (Optional) + Your "unix" home directory, by default is: + /home/ + If you are (also) working in command line mode, it is a good + practice to change this to the folder where your TTCN-3 projects + are. + Edit the file /etc/passw: + In the line: + :unused:::U-\, + S-1-5-21-nnnnnn...nnnnnn:/home/:/bin/bash + + replace "/home/" with the folder of your preference. + Note: you can access all Windows drives from Cygwin as + /cygdrive/". + Example: to set your "unix" home directory to the "My_Home" folder + within your Windows Documents folder, you should replace + "/home/" by + "/cygdrive/c/Users//Documents/My_Home" + WARNING: The path of your "unix" home directory shall not contain + any space! + + (J) Using the bynary Titan package: download the Titan package for from + GitHub. Unpack the Titan package into a folder of your choice. + Note: It is not a requirement, but is a kind of best practice to + place Titan into a subfolder within your "unix" home directory. + Edit the /home//.bashrc + file. Add these lines to it: + export PATH=${TTCN3_DIR}/bin:${PATH} + export LD_LIBRARY_PATH=${TTCN3_DIR}/lib:${LD_LIBRARY_PATH} + + (K) Compile Titan with Cygwin: + Get the latest source code from GitHub. + Download and install JDK from Oracle's download site: + http://www.oracle.com/technetwork/java/javase/downloads/index.html + Edit the /home//.bashrc + as above. + Create titan/Makefile.personal with the following content: + TTCN3_DIR := /home//git/titan/Install + JDKDIR := /home//jdk + JNI := no + GUI := no + GEN_PDF := no + DEBUG := no + Compile Titan: + cd titan + make -j + make install + The compiled files will be placed into the titan/Install directory. + + (L) If you want to use graphical tools (like nedit for example), then you need to install the Cygwin/X + component too. The install procedure can be found at the homepage: + http://x.cygwin.com/docs/ug/cygwin-x-ug.html + diff --git a/README.linux b/README.linux new file mode 100644 index 0000000..fa9270c --- /dev/null +++ b/README.linux @@ -0,0 +1,89 @@ +Build and install Titan on Linux + +1.Install required libraries: +(examples are given for Ubuntu 12.04/14.04; for other Linuxes, pls. use the relevant library installation method) + +sudo apt-get install g++ expect libssl-dev libxml2-dev libncurses5-dev flex bison +xutils-dev is needed by makedepend: +sudo apt-get install xutils-dev +The following packages may be needed for titan_eclipse/automatic_build: +sudo apt-get install ant xsltproc + +2.Clone the titan directory from git into /home//titan + +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. +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. ( In this case, you won't be able to execute Titan test cases from the Eclipse plug-in) + +Create ~/titan/Makefile.personal to override settings in Makefile.cfg with the following content: + +TTCN3_DIR := /home//titan/Install +JNI := no +GEN_PDF := yes + + + + +2) JNI enabled + +install JDK into /home//jdk + +Create ~/titan/Makefile.personal to override settings in Makefile.cfg with the following content: + +TTCN3_DIR := /home//titan/Install +JDKDIR := /home//jdk +JNI := yes +GEN_PDF := yes + + + +3. Run make + +make + +4. Run make install + +make install + +This will install Titan into /home//titan/Install + +5. Optionally , run function/regression tests + +set environment variable TTCN3_DIR to /home//titan/Install + +(setenv TTCN3_DIR /home//titan/Install for csh, +export TTCN3_DIR=/home//titan/Install for bash ) + + + +cd /home//titan/function_test +make + +( or make |& tee outputfile if you want to save the output for verification) +cd /home//titan/regression_test +make run +( or make run |& tee outputfile if you want to save the output for verification) + +These tests might run for half an hour (regr.tests) to two hours (func.tests) + +6. Optionally , copy Titan into its' final directory. +From here on, you can continue with the Titan installation guide, see /Install/docs, to set environment variables etc. + + + + diff --git a/common/.gitignore b/common/.gitignore new file mode 100644 index 0000000..1a5ba15 --- /dev/null +++ b/common/.gitignore @@ -0,0 +1,16 @@ +*.d +config_preproc_la.cc +hostid +hostid.exe +lex.backup +pattern_la.cc +pattern_p.cc +pattern_p.hh +pattern_p.output +pattern_uni.hh +pattern_uni.cc +pattern_uni_lex.cc +pattern_uni.output +config_preproc_p.output +config_preproc_p.tab.cc +config_preproc_p.tab.hh diff --git a/common/CharCoding.hh b/common/CharCoding.hh new file mode 100644 index 0000000..9a4bde2 --- /dev/null +++ b/common/CharCoding.hh @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef CHARCODING_HH +#define CHARCODING_HH + +/** Character Coding types. + * Needed by both the compiler and runtime */ + +namespace CharCoding { + + enum CharCodingType { + UNKNOWN, + ASCII, + UTF_8, + UTF16, + UTF16BE, + UTF16LE, + UTF32, + UTF32BE, + UTF32LE + }; + +} + +#endif /* CHARCODING_HH */ + diff --git a/common/JSON_Tokenizer.cc b/common/JSON_Tokenizer.cc new file mode 100644 index 0000000..cb58f0c --- /dev/null +++ b/common/JSON_Tokenizer.cc @@ -0,0 +1,373 @@ +#include + +#include "JSON_Tokenizer.hh" +#include "memory.h" +#include + +static const char TABS[] = + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; +const size_t MAX_TABS = sizeof(TABS) - 1; // 64 + +void JSON_Tokenizer::init(const char* p_buf, const size_t p_buf_len) +{ + if (p_buf != 0 && p_buf_len != 0) { + buf_ptr = mcopystrn(p_buf, p_buf_len); + } else { + buf_ptr = 0; + } + buf_len = p_buf_len; + buf_pos = 0; + depth = 0; + previous_token = JSON_TOKEN_NONE; +} + +JSON_Tokenizer::~JSON_Tokenizer() +{ + Free(buf_ptr); +} + +void JSON_Tokenizer::put_c(const char c) +{ + buf_ptr = mputprintf(buf_ptr, "%c", c); + ++buf_len; +} + +void JSON_Tokenizer::put_s(const char* s) +{ + buf_ptr = mputstr(buf_ptr, s); + buf_len += strlen(s); +} + +void JSON_Tokenizer::put_depth() +{ + put_s(TABS + ((depth > MAX_TABS) ? 0 : MAX_TABS - depth)); +} + +bool JSON_Tokenizer::skip_white_spaces() +{ + while(buf_pos < buf_len) { + switch(buf_ptr[buf_pos]) { + case ' ': + case '\r': + case '\n': + case '\t': + case '\f': + ++buf_pos; + break; + default: + return true; + } + } + return false; +} + +bool JSON_Tokenizer::check_for_string() +{ + if ('\"' == buf_ptr[buf_pos]) { + ++buf_pos; + } else { + return false; + } + while (buf_pos < buf_len) { + if ('\"' == buf_ptr[buf_pos]) { + return true; + } + else if ('\\' == buf_ptr[buf_pos]) { + // skip escaped character (so escaped quotes (\") are not mistaken for the ending quotes) + ++buf_pos; + } + ++buf_pos; + } + return false; +} + +bool JSON_Tokenizer::check_for_number() +{ + bool first_digit = false; // first non-zero digit reached + bool zero = false; // first zero digit reached + bool decimal_point = false; // decimal point (.) reached + bool exponent_mark = false; // exponential mark (e or E) reached + bool exponent_sign = false; // sign of the exponential (- or +) reached + + if ('-' == buf_ptr[buf_pos]) { + ++buf_pos; + } + + while (buf_pos < buf_len) { + switch(buf_ptr[buf_pos]) { + case '.': + if (decimal_point || exponent_mark || (!first_digit && !zero)) { + return false; + } + decimal_point = true; + first_digit = false; + zero = false; + break; + case 'e': + case 'E': + if (exponent_mark || (!first_digit && !zero)) { + return false; + } + exponent_mark = true; + first_digit = false; + zero = false; + break; + case '0': + if (!first_digit && (exponent_mark || (!decimal_point && zero))) { + return false; + } + zero = true; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (!first_digit && zero && (!decimal_point || exponent_mark)) { + return false; + } + first_digit = true; + break; + case '-': + case '+': + if (exponent_sign || !exponent_mark || zero || first_digit) { + return false; + } + exponent_sign = true; + break; + default: + return first_digit || zero; + } + + ++buf_pos; + } + return first_digit || zero; +} + +bool JSON_Tokenizer::check_for_separator() +{ + if (buf_pos < buf_len) { + switch(buf_ptr[buf_pos]) { + case ',': + ++buf_pos; + // no break + case ':': + case '{': + case '}': + case '[': + case ']': + return true; + default: + return false; + } + } + return true; +} + +bool JSON_Tokenizer::check_for_literal(const char* p_literal) +{ + size_t len = strlen(p_literal); + size_t start_pos = buf_pos; + + if (buf_len - buf_pos >= len && + 0 == strncmp(buf_ptr + buf_pos, p_literal, len)) { + buf_pos += len; + if (!skip_white_spaces() || check_for_separator()) { + return true; + } else { + // must be followed by a separator (or only white spaces until the buffer ends) -> undo buffer action + buf_pos = start_pos; + } + } + return false; +} + +int JSON_Tokenizer::get_next_token(json_token_t* p_token, char** p_token_str, size_t* p_str_len) +{ + size_t start_pos = buf_pos; + *p_token = JSON_TOKEN_NONE; + if (0 != p_token_str && 0 != p_str_len) { + *p_token_str = 0; + *p_str_len = 0; + } + + if (skip_white_spaces()) { + char c = buf_ptr[buf_pos]; + switch (c) { + case '{': + case '[': + *p_token = ('{' == c) ? JSON_TOKEN_OBJECT_START : JSON_TOKEN_ARRAY_START; + ++buf_pos; + break; + case '}': + case ']': + ++buf_pos; + if (skip_white_spaces() && !check_for_separator()) { + // must be followed by a separator (or only white spaces until the buffer ends) + *p_token = JSON_TOKEN_ERROR; + } else { + *p_token = ('}' == c) ? JSON_TOKEN_OBJECT_END : JSON_TOKEN_ARRAY_END; + } + break; + case '\"': { + // string value or field name + size_t string_start_pos = buf_pos; + if(!check_for_string()) { + // invalid string value + *p_token = JSON_TOKEN_ERROR; + break; + } + size_t string_end_pos = ++buf_pos; // step over the string's ending quotes + if (skip_white_spaces() && ':' == buf_ptr[buf_pos]) { + // name token - don't include the starting and ending quotes + *p_token = JSON_TOKEN_NAME; + if (0 != p_token_str && 0 != p_str_len) { + *p_token_str = buf_ptr + string_start_pos + 1; + *p_str_len = string_end_pos - string_start_pos - 2; + } + ++buf_pos; + } else if (check_for_separator()) { + // value token - include the starting and ending quotes + *p_token = JSON_TOKEN_STRING; + if (0 != p_token_str && 0 != p_str_len) { + *p_token_str = buf_ptr + string_start_pos; + *p_str_len = string_end_pos - string_start_pos; + } + } else { + // value token, but there is no separator after it -> error + *p_token = JSON_TOKEN_ERROR; + break; + } + break; + } // case: string value or field name + default: + if (('0' <= buf_ptr[buf_pos] && '9' >= buf_ptr[buf_pos]) || + '-' == buf_ptr[buf_pos]) { + // number value + size_t number_start_pos = buf_pos; + if (!check_for_number()) { + // invalid number + *p_token = JSON_TOKEN_ERROR; + break; + } + size_t number_length = buf_pos - number_start_pos; + if (skip_white_spaces() && !check_for_separator()) { + // must be followed by a separator (or only white spaces until the buffer ends) + *p_token = JSON_TOKEN_ERROR; + break; + } + *p_token = JSON_TOKEN_NUMBER; + if (0 != p_token_str && 0 != p_str_len) { + *p_token_str = buf_ptr + number_start_pos; + *p_str_len = number_length; + } + break; + } // if (number value) + else if (check_for_literal("true")) { + *p_token = JSON_TOKEN_LITERAL_TRUE; + break; + } + else if (check_for_literal("false")) { + *p_token = JSON_TOKEN_LITERAL_FALSE; + break; + } + else if (check_for_literal("null")) { + *p_token = JSON_TOKEN_LITERAL_NULL; + break; + } + else { + *p_token = JSON_TOKEN_ERROR; + break; + } + } // switch (current char) + } // if (skip_white_spaces()) + + return buf_pos - start_pos; +} + +void JSON_Tokenizer::put_separator() +{ + if (JSON_TOKEN_NAME != previous_token && JSON_TOKEN_NONE != previous_token && + JSON_TOKEN_ARRAY_START != previous_token && JSON_TOKEN_OBJECT_START != previous_token) { + put_c(','); + if (pretty) { + put_c('\n'); + put_depth(); + } + } +} + +int JSON_Tokenizer::put_next_token(json_token_t p_token, const char* p_token_str) +{ + int start_len = buf_len; + switch(p_token) { + case JSON_TOKEN_OBJECT_START: + case JSON_TOKEN_ARRAY_START: { + put_separator(); + put_c( (JSON_TOKEN_OBJECT_START == p_token) ? '{' : '[' ); + if (pretty) { + put_c('\n'); + ++depth; + put_depth(); + } + break; + } + case JSON_TOKEN_OBJECT_END: + case JSON_TOKEN_ARRAY_END: { + if (pretty) { + if (JSON_TOKEN_OBJECT_START != previous_token && JSON_TOKEN_ARRAY_START != previous_token) { + put_c('\n'); + --depth; + put_depth(); + } else if (MAX_TABS >= depth) { + // empty object or array -> remove the extra tab added at the start token + --depth; + --buf_len; + buf_ptr[buf_len] = 0; + } + } + put_c( (JSON_TOKEN_OBJECT_END == p_token) ? '}' : ']' ); + break; + } + case JSON_TOKEN_NUMBER: + case JSON_TOKEN_STRING: + put_separator(); + put_s(p_token_str); + break; + case JSON_TOKEN_LITERAL_TRUE: + put_separator(); + put_s("true"); + break; + case JSON_TOKEN_LITERAL_FALSE: + put_separator(); + put_s("false"); + break; + case JSON_TOKEN_LITERAL_NULL: + put_separator(); + put_s("null"); + break; + case JSON_TOKEN_NAME: + put_separator(); + put_c('\"'); + put_s(p_token_str); + if (pretty) { + put_s("\" : "); + } else { + put_s("\":"); + } + break; + default: + return 0; + } + + previous_token = p_token; + return buf_len - start_len; +} + diff --git a/common/JSON_Tokenizer.hh b/common/JSON_Tokenizer.hh new file mode 100644 index 0000000..6775c69 --- /dev/null +++ b/common/JSON_Tokenizer.hh @@ -0,0 +1,160 @@ +#ifndef JSON_TOKENIZER_HH +#define JSON_TOKENIZER_HH + +#include + +/** JSON token types */ +enum json_token_t { + JSON_TOKEN_ERROR = 0, // not actually a token, used when get_next_token() fails + JSON_TOKEN_NONE, // not actually a token, used for initializing + JSON_TOKEN_OBJECT_START, // "{" + JSON_TOKEN_OBJECT_END, // "}" + JSON_TOKEN_ARRAY_START, // "[" + JSON_TOKEN_ARRAY_END, // "]" + JSON_TOKEN_NAME, // field name (key) in a JSON object, followed by ":" + JSON_TOKEN_NUMBER, // JSON number value + JSON_TOKEN_STRING, // JSON string value + JSON_TOKEN_LITERAL_TRUE, // "true" value + JSON_TOKEN_LITERAL_FALSE, // "false" value + JSON_TOKEN_LITERAL_NULL // "null" value +}; + +/** A class for building and processing JSON documents. Stores the document in a buffer. + * Can build JSON documents by inserting tokens into an empty buffer. + * Can extract tokens from an existing JSON document. */ +class JSON_Tokenizer { + +private: + + /** The buffer that stores the JSON document + * This is a buffer with exponential allocation (expstring), only uses expstring + * memory operations from memory.h (ex.: mputstr, mputprintf) */ + char* buf_ptr; + + /** Number of bytes currently in the buffer */ + size_t buf_len; + + /** Current position in the buffer */ + size_t buf_pos; + + /** Current depth in the JSON document (only used if pretty printing is set */ + unsigned int depth; + + /** Stores the previous JSON token inserted by put_next_token() */ + json_token_t previous_token; + + /** Activates or deactivates pretty printing + * If active, put_next_token() and put_separator() will add extra newlines + * and indenting to the JSON code to make it more readable for you humans, + * otherwise it will be compact (no white spaces). */ + bool pretty; + + /** Initializes the properties of the tokenizer. + * The buffer is initialized with the parameter data (unless it's empty). */ + void init(const char* p_buf, const size_t p_buf_len); + + /** Inserts a character to the end of the buffer */ + void put_c(const char c); + + /** Inserts a null-terminated string to the end of the buffer */ + void put_s(const char* s); + + /** Indents a new line in JSON code depending on the current depth. + * If the maximum depth is reached, the code is not indented further. + * Used only if pretty printing is set. */ + void put_depth(); + + /** Skips white spaces until a non-white-space character is found. + * Returns false if the end of the buffer is reached before a non-white-space + * character is found, otherwise returns true. */ + bool skip_white_spaces(); + + /** Attempts to find a JSON string at the current buffer position. + * Returns true if a valid string is found before the end of the buffer + * is reached, otherwise returns false. */ + bool check_for_string(); + + /** Attempts to find a JSON number at the current buffer position. + * For number format see http://json.org/. + * Returns true if a valid number is found before the end of the buffer + * is reached, otherwise returns false. */ + bool check_for_number(); + + /** Checks if the current character in the buffer is a valid JSON separator. + * Separators are: commas (,), colons (:) and curly and square brackets ({}[]). + * This function also steps over the separator if it's a comma. + * Returns true if a separator is found, otherwise returns false. */ + bool check_for_separator(); + + /** Attempts to find a specific JSON literal at the current buffer position. + * Returns true if the literal is found, otherwise returns false. + * @param p_literal [in] Literal value to find */ + bool check_for_literal(const char* p_literal); + + /** Adds a separating comma (,) if the previous token is a value, or an object or + * array end mark. */ + void put_separator(); + + /** No copy constructor. Implement if needed. */ + JSON_Tokenizer(const JSON_Tokenizer&); + + /** No assignment operator. Implement if needed. */ + JSON_Tokenizer& operator=(const JSON_Tokenizer&); + +public: + /** Constructs a tokenizer with an empty buffer. + * Use put_next_token() to build a JSON document and get_buffer()/get_buffer_length() to retrieve it */ + JSON_Tokenizer(bool p_pretty = false) : pretty(p_pretty) { init(0, 0); } + + /** Constructs a tokenizer with the buffer parameter. + * Use get_next_token() to read JSON tokens and get_pos()/set_pos() to move around in the buffer */ + JSON_Tokenizer(const char* p_buf, const size_t p_buf_len) : pretty(false) { init(p_buf, p_buf_len); } + + /** Destructor. Frees the buffer. */ + ~JSON_Tokenizer(); + + /** Reinitializes the tokenizer with a new buffer. */ + inline void set_buffer(const char* p_buf, const size_t p_buf_len) { init(p_buf, p_buf_len); } + + /** Retrieves the buffer containing the JSON document. */ + inline const char* get_buffer() { return buf_ptr; } + + /** Retrieves the length of the buffer containing the JSON document. */ + inline size_t get_buffer_length() { return buf_len; } + + /** Extracts a JSON token from the current buffer position. + * @param p_token [out] Extracted token type, or JSON_TOKEN_ERROR if no token + * could be extracted, or JSON_TOKEN_NONE if the buffer end is reached + * @param p_token_str [out] A pointer to the token data (if any): + * the name of a JSON object field (without quotes), or the string representation + * of a JSON number, or a JSON string (with quotes and double-escaped). + * @param p_str_len [out] The character length of the token data (if there is data) + * @return The number of characters extracted + * @note The token data is not copied, *p_token_str will point to the start of the + * data in the tokenizer's buffer. */ + int get_next_token(json_token_t* p_token, char** p_token_str, size_t* p_str_len); + + /** Gets the current read position in the buffer. + * This is where get_next_token() will read from next. */ + inline size_t get_buf_pos() { return buf_pos; } + + /** Sets the current read position in the buffer. + * This is where get_next_buffer() will read from next. */ + inline void set_buf_pos(const size_t p_buf_pos) { buf_pos = p_buf_pos; } + + /** Adds the specified JSON token to end of the buffer. + * @param p_token [in] Token type + * @param p_token_str [in] The name of a JSON object field (without quotes), or + * the string representation of a JSON number, or a JSON string (with quotes + * and double-escaped). For all the other tokens this parameter will be ignored. + * @return The number of characters added to the JSON document */ + int put_next_token(json_token_t p_token, const char* p_token_str = 0); + +}; // class JSON_Tokenizer + +// A dummy JSON tokenizer, use when there is no actual JSON document +static JSON_Tokenizer DUMMY_BUFFER; + + +#endif /* JSON_TOKENIZER_HH */ + diff --git a/common/Makefile b/common/Makefile new file mode 100644 index 0000000..3b11451 --- /dev/null +++ b/common/Makefile @@ -0,0 +1,116 @@ +############################################################################### +# 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 +############################################################################### +# Makefile for the common directory of the TTCN-3 Test Executor + +TOP := .. +include $(TOP)/Makefile.cfg + +TARGETS := + +# The origin of GENERATED_SOURCES +ORIGINATORS := pattern_la.l pattern_p.y pattern_uni.y config_preproc_la.l config_preproc_p.y + +GENERATED_SOURCES := pattern_la.cc pattern_p.cc pattern_uni.cc config_preproc_la.cc config_preproc_p.tab.cc + +# Sources in the CVS + +STATIC_SOURCES := memory.c new.cc userinfo.c path.c config_preproc.cc Quadruple.cc Path2.cc ModuleVersion.cc JSON_Tokenizer.cc + +ifndef MINGW +STATIC_SOURCES += NetworkHandler.cc +endif + +ifeq ($(USAGE_STATS), yes) + STATIC_SOURCES += usage_stats.cc +endif + +ifeq ($(LICENSING), yes) + STATIC_SOURCES += license.c + ifeq ($(PLATFORM), WIN32) + STATIC_SOURCES += hostid.c + TARGETS += hostid$(EXESUFFIX) + endif + ifeq ($(PLATFORM), INTERIX) + STATIC_SOURCES += hostid.c + TARGETS += hostid$(EXESUFFIX) + endif +endif + +SOURCES := $(STATIC_SOURCES) $(GENERATED_SOURCES) + +GENERATED_HEADERS := pattern_p.hh pattern_uni.hh config_preproc_p.tab.hh + +GENERATED_OTHERS := pattern_p.output pattern_uni.output lex.backup + +OBJECTS := $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(SOURCES))) + +DEPFILES := $(patsubst %.cc,%.d,$(patsubst %.c,%.d,$(SOURCES))) + +SUBDIRS := + +CPPFLAGS += -D_REENTRANT + +ifdef REGEX_DIR + CPPFLAGS += -I$(REGEX_DIR)/include +endif + +all run: $(OBJECTS) $(TARGETS) + +install: $(OBJECTS) $(TARGETS) +ifdef MINGW + @echo Skipped ${CURDIR} for MinGW +else + mkdir -p $(INCDIR) + cp version.h memory.h platform.h ttcn3float.hh pattern.hh CharCoding.hh JSON_Tokenizer.hh $(INCDIR) +ifneq ($(TARGETS), ) + ifeq ($(DEBUG), no) + $(STRIP) $(TARGETS) + endif + mkdir -p $(BINDIR) + cp $(TARGETS) $(BINDIR) +endif +endif + +hostid$(EXESUFFIX): hostid.o license.o memory.o + $(CC) $(LDFLAGS) -o $@ $^ $(LICENSE_LIBS) $(MINGW_LIBS) + +pattern_la.cc: pattern_la.l + $(FLEX) $(FLEXFLAGS) -o$@ $< + +pattern_p.cc pattern_p.hh: pattern_p.y + $(BISON) $(BISONFLAGS) $< + +pattern_uni.cc pattern_uni.hh: pattern_uni.y + $(BISON) $(BISONFLAGS) $< + +config_preproc_la.cc: config_preproc_la.l + $(FLEX) $(FLEXFLAGS) -o$@ $< + +config_preproc_p.tab.cc config_preproc_p.tab.hh: config_preproc_p.y + $(BISON) $(BISONFLAGS) -o config_preproc_p.tab.cc -p config_process_ $< + +# Target-specific variable alteration +# Target-specific += causes make 3.79.1 to crash, hence this old style +ifdef OPENSSL_DIR +ifneq ($(OPENSSL_DIR), default) +license.o license.d: CPPFLAGS := $(CPPFLAGS) -I$(OPENSSL_DIR)/include +endif +endif + +include ../Makefile.genrules + + +#vpath pattern_la.l $(ABS_SRC) +#vpath pattern_p.y $(ABS_SRC) +#vpath pattern_uni_lex.l $(ABS_SRC) +#vpath pattern_uni.y $(ABS_SRC) +#vpath config_preproc_la.l $(ABS_SRC) +#vpath config_preproc_p.y $(ABS_SRC) + +# no vpath for GENERATED_SOURCES ! + diff --git a/common/ModuleVersion.cc b/common/ModuleVersion.cc new file mode 100644 index 0000000..b08d5c5 --- /dev/null +++ b/common/ModuleVersion.cc @@ -0,0 +1,44 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 +/////////////////////////////////////////////////////////////////////////////// +#undef new + +#include +#include +#include "ModuleVersion.hh" +#include "dbgnew.hh" + +std::string ModuleVersion::toString() const { + std::stringstream stream; + const char separator = ' '; + if (!productNumber.empty()) { + stream << productNumber; + } + + if (suffix != 0) { + stream << "/" << suffix; + } + if (release != 0) { + stream << separator << 'R' << release << separator + << (char)('A' + patch); + } + if (build != 0) { + stream << separator << build; + } + + if (!extra.empty()) { + stream << extra; + } + return stream.str(); +} + +bool ModuleVersion::operator<(const ModuleVersion& other) const{ + return productNumber < other.productNumber + && suffix < other.suffix + && build < other.build + && extra < other.extra; +} diff --git a/common/ModuleVersion.hh b/common/ModuleVersion.hh new file mode 100644 index 0000000..be54651 --- /dev/null +++ b/common/ModuleVersion.hh @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _MODULE_VERSION_H +#define _MODULE_VERSION_H + +#undef new +#include +#include +#include "dbgnew.hh" + +class ModuleVersion { + public: + ModuleVersion() {} + + ModuleVersion(const char* const p_productNumber, + unsigned int p_suffix, unsigned int p_release, + unsigned int p_patch, unsigned int p_build, + const char* const p_extra) + : productNumber(p_productNumber ? p_productNumber : ""), + suffix(p_suffix), + release(p_release), + patch(p_patch), + build(p_build), + extra(p_extra ? p_extra : "") { + // Do nothing + } + + bool hasProductNumber() const { return !productNumber.empty(); } + std::string toString() const; + + bool operator<(const ModuleVersion& other) const; + + private: + std::string productNumber; + unsigned int suffix; + unsigned int release; + unsigned int patch; + unsigned int build; + std::string extra; +}; + +#endif diff --git a/common/NetworkHandler.cc b/common/NetworkHandler.cc new file mode 100644 index 0000000..95a81cd --- /dev/null +++ b/common/NetworkHandler.cc @@ -0,0 +1,440 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "NetworkHandler.hh" + +#include +#include +#include + +#include +#include +#include + +#include "memory.h" +#include "../core/Textbuf.hh" + +IPAddress::~IPAddress() { } + +NetworkHandler::NetworkHandler() : m_family(ipv4) { } + +void NetworkHandler::set_family(const char *p_addr) +{ + if (!p_addr || IPv4Address::is_valid(p_addr)) m_family = ipv4; +#if defined(LINUX) || defined(CYGWIN17) + else if (IPv6Address::is_valid(p_addr)) m_family = ipv6; +#endif + else m_family = ipv0; +} + +int NetworkHandler::socket() +{ + return socket(m_family); +} + +int NetworkHandler::socket(const NetworkFamily& p_family) +{ +#if defined(LINUX) || defined(CYGWIN17) + return ::socket(p_family == ipv4 ? AF_INET : AF_INET6, SOCK_STREAM, 0); +#else + (void)p_family; + return ::socket(AF_INET, SOCK_STREAM, 0); +#endif +} + +HCNetworkHandler::HCNetworkHandler() : m_mc_addr(NULL), m_local_addr(NULL) { } + +HCNetworkHandler::~HCNetworkHandler() +{ + delete m_mc_addr; + delete m_local_addr; +} + +bool HCNetworkHandler::set_local_addr(const char *p_addr, unsigned short p_port) +{ + if (!p_addr) return false; + switch (m_family) { + case ipv4: m_local_addr = new IPv4Address(p_addr, p_port); break; +#if defined(LINUX) || defined(CYGWIN17) + case ipv6: m_local_addr = new IPv6Address(p_addr, p_port); break; +#endif + default: + break; + } + return m_local_addr != NULL; +} + +bool HCNetworkHandler::set_mc_addr(const char *p_addr, unsigned short p_port) +{ + if (!p_addr) return false; + switch (m_family) { + case ipv4: m_mc_addr = new IPv4Address(p_addr, p_port); break; +#if defined(LINUX) || defined(CYGWIN17) + case ipv6: m_mc_addr = new IPv6Address(p_addr, p_port); break; +#endif + default: + break; + } + return m_mc_addr != NULL; +} + +int HCNetworkHandler::getsockname_local_addr(int p_sockfd) +{ + if (m_local_addr != NULL) delete m_local_addr; + switch (m_family) { + case ipv4: m_local_addr = new IPv4Address(); break; +#if defined(LINUX) || defined(CYGWIN17) + case ipv6: m_local_addr = new IPv6Address(); break; +#endif + default: return -1; + } + return m_local_addr->getsockname(p_sockfd); +} + +int HCNetworkHandler::bind_local_addr(int p_sockfd) const +{ + m_local_addr->set_port(0); + return ::bind(p_sockfd, m_local_addr->get_addr(), m_local_addr->get_addr_len()); +} + +#ifdef SOLARIS +#define CAST_AWAY_CONST_FOR_SOLARIS6 (sockaddr *) +#else +#define CAST_AWAY_CONST_FOR_SOLARIS6 +#endif + +int HCNetworkHandler::connect_to_mc(int p_sockfd) const +{ + return ::connect(p_sockfd, CAST_AWAY_CONST_FOR_SOLARIS6 m_mc_addr->get_addr(), + m_mc_addr->get_addr_len()); +} + +IPAddress *IPAddress::create_addr(const NetworkFamily& p_family) +{ + switch (p_family) { + case ipv4: + return new IPv4Address(); +#if defined(LINUX) || defined(CYGWIN17) + case ipv6: + return new IPv6Address(); +#endif + default: + return NULL; + } +} + +IPAddress *IPAddress::create_addr(const char *p_addr) +{ + if (p_addr == NULL) + return NULL; + if (IPv4Address::is_valid(p_addr)) + return new IPv4Address(p_addr); +#if defined(LINUX) || defined(CYGWIN17) + else if (IPv6Address::is_valid(p_addr)) + return new IPv6Address(p_addr); +#endif + else + return NULL; +} + +IPv4Address::IPv4Address() +{ + clean_up(); + m_addr.sin_family = AF_INET; + m_addr.sin_addr.s_addr = htonl(INADDR_ANY); + m_addr.sin_port = htons(0); +} + +IPv4Address::IPv4Address(const char *p_addr, unsigned short p_port) +{ + set_addr(p_addr, p_port); +} + +IPv4Address::~IPv4Address() +{ + clean_up(); +} + +bool IPv4Address::is_valid(const char *p_addr) +{ + if (p_addr == NULL) { + return false; + } else { + IPv4Address addr; + return addr.set_addr(p_addr); + } +} + +bool IPv4Address::is_local() const +{ + // Or: (ntohl(m_addr.sin_addr.s_addr) & 0xff000000u) == 0x7f000000u. + return m_addr.sin_addr.s_addr == inet_addr("127.0.0.1"); +} + +bool IPv4Address::set_addr(const char *p_addr, unsigned short p_port) +{ + clean_up(); + if (p_addr != NULL) { + struct hostent *hptr = gethostbyname(p_addr); + if (hptr != NULL && (size_t)hptr->h_length == sizeof(struct in_addr)) { + m_addr.sin_family = AF_INET; + m_addr.sin_port = htons(p_port); + memset(m_addr.sin_zero, 0, sizeof(m_addr.sin_zero)); + memcpy(&m_addr.sin_addr, hptr->h_addr_list[0], hptr->h_length); + strncpy(m_addr_str, inet_ntoa(m_addr.sin_addr), sizeof(m_addr_str)); + strncpy(m_host_str, hptr->h_name, sizeof(m_host_str)); + return true; + } + } + return false; +} + +int IPv4Address::accept(int p_sockfd) +{ + clean_up(); + socklen_type addrlen = sizeof(m_addr); + int fd = ::accept(p_sockfd, (struct sockaddr *)&m_addr, &addrlen); + if (fd >= 0) { + strncpy(m_addr_str, inet_ntoa(m_addr.sin_addr), sizeof(m_addr_str)); + if (m_addr.sin_addr.s_addr != htonl(INADDR_ANY)) { + struct hostent *hptr = + gethostbyaddr((const char *)&m_addr.sin_addr, + sizeof(m_addr.sin_addr), m_addr.sin_family); + if (hptr != NULL && (size_t)hptr->h_length == sizeof(struct in_addr)) { + strncpy(m_host_str, hptr->h_name, sizeof(m_host_str)); + } + } + } + return fd; +} + +int IPv4Address::getsockname(int p_sockfd) +{ + clean_up(); + socklen_type addrlen = sizeof(m_addr); + int s = ::getsockname(p_sockfd, (struct sockaddr *)&m_addr, &addrlen); + if (s >= 0) { + strncpy(m_addr_str, inet_ntoa(m_addr.sin_addr), sizeof(m_addr_str)); + if (m_addr.sin_addr.s_addr != htonl(INADDR_ANY)) { + struct hostent *hptr = + gethostbyaddr((const char *)&m_addr.sin_addr, + sizeof(m_addr.sin_addr), m_addr.sin_family); + if (hptr != NULL && (size_t)hptr->h_length == sizeof(struct in_addr)) { + strncpy(m_host_str, hptr->h_name, sizeof(m_host_str)); + } + } + } + return s; +} + +bool IPv4Address::operator==(const IPAddress& p_addr) const +{ + return memcmp(&m_addr.sin_addr, &(((const IPv4Address&)p_addr).m_addr.sin_addr), sizeof(m_addr.sin_addr)) == 0; +} + +bool IPv4Address::operator!=(const IPAddress& p_addr) const +{ + return !(*this == p_addr); +} + +IPAddress& IPv4Address::operator=(const IPAddress& p_addr) +{ + clean_up(); + memcpy(&m_addr, &((const IPv4Address&)p_addr).m_addr, sizeof(m_addr)); + strncpy(m_host_str, ((const IPv4Address&)p_addr).m_host_str, sizeof(m_host_str)); + strncpy(m_addr_str, ((const IPv4Address&)p_addr).m_addr_str, sizeof(m_addr_str)); + return *this; +} + +void IPv4Address::push_raw(Text_Buf& p_buf) const +{ + p_buf.push_raw(sizeof(m_addr.sin_family), &m_addr.sin_family); + p_buf.push_raw(sizeof(m_addr.sin_port), &m_addr.sin_port); + p_buf.push_raw(sizeof(m_addr.sin_addr), &m_addr.sin_addr); + p_buf.push_raw(sizeof(m_addr.sin_zero), &m_addr.sin_zero); +} + +void IPv4Address::pull_raw(Text_Buf& p_buf) +{ + clean_up(); + p_buf.pull_raw(sizeof(m_addr.sin_family), &m_addr.sin_family); + p_buf.pull_raw(sizeof(m_addr.sin_port), &m_addr.sin_port); + p_buf.pull_raw(sizeof(m_addr.sin_addr), &m_addr.sin_addr); + p_buf.pull_raw(sizeof(m_addr.sin_zero), &m_addr.sin_zero); +} + +void IPv4Address::clean_up() +{ + memset(&m_addr, 0, sizeof(m_addr)); + memset(m_host_str, 0, sizeof(m_host_str)); + memset(m_addr_str, 0, sizeof(m_addr_str)); +} + +#if defined(LINUX) || defined(CYGWIN17) +IPv6Address::IPv6Address() +{ + clean_up(); + m_addr.sin6_family = AF_INET6; + m_addr.sin6_addr = in6addr_any; + m_addr.sin6_port = htons(0); +} + +IPv6Address::IPv6Address(const char *p_addr, unsigned short p_port) +{ + set_addr(p_addr, p_port); +} + +IPv6Address::~IPv6Address() +{ + clean_up(); +} + +const char *IPv6Address::get_addr_str() const +{ + if (strlen(m_addr_str) > 0) { + // The host name should always contain the interface's name for link-local addresses. + return (strlen(m_host_str) > 0 && strstr(m_host_str, "%") != NULL) ? m_host_str : m_addr_str; + } else { + return m_host_str; + } +} + +bool IPv6Address::set_addr(const char *p_addr, unsigned short p_port) +{ + clean_up(); + struct addrinfo hints, *res; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_CANONNAME | AI_PASSIVE; + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; // Any. + char p_port_str[6]; + memset(p_port_str, 0, sizeof(p_port_str)); + snprintf(p_port_str, sizeof(p_port_str), "%u", p_port); + int s = getaddrinfo(p_addr, p_port_str, &hints, &res); + if (s == 0) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void*)res->ai_addr; + // The (void*) shuts up the "cast increases required alignment" warning. + // Hopefully, the res->ai_addr points to a properly aligned sockaddr_in6 + // and we won't have problems like these if we decide to support Sparc: + // http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=340384 + memcpy(&m_addr, addr, sizeof(m_addr)); + m_addr.sin6_port = htons(p_port); + inet_ntop(res->ai_family, &(addr->sin6_addr), m_addr_str, sizeof(m_addr_str)); + strncpy(m_host_str, res->ai_canonname, sizeof(m_host_str)); + freeaddrinfo(res); + return true; + } + return false; +} + +int IPv6Address::accept(int p_sockfd) +{ + clean_up(); + socklen_type addrlen = sizeof(m_addr); + int fd = ::accept(p_sockfd, (struct sockaddr *)&m_addr, &addrlen); + if (fd >= 0) { + if (!inet_ntop(AF_INET6, &m_addr.sin6_addr, m_addr_str, sizeof(m_addr_str))) { + fprintf(stderr, "IPv6Address::accept(): Unable to convert IPv6 address " + "from binary to text form: %s\n", strerror(errno)); + } + int s = getnameinfo((struct sockaddr *)&m_addr, sizeof(m_addr), + m_host_str, sizeof(m_host_str), NULL, 0, 0); + if (s != 0) { + fprintf(stderr, "IPv6Address::accept(): Address to name translation " + "failed: %s\n", gai_strerror(s)); + } + } + return fd; +} + +int IPv6Address::getsockname(int p_sockfd) +{ + clean_up(); + socklen_type addrlen = sizeof(m_addr); + int s1 = ::getsockname(p_sockfd, (struct sockaddr *)&m_addr, &addrlen); + if (s1 >= 0) { + if (!inet_ntop(AF_INET6, &m_addr.sin6_addr, m_addr_str, sizeof(m_addr_str))) { + fprintf(stderr, "IPv6Address::getsockname(): Unable to convert IPv6 " + "address from binary to text form: %s\n", strerror(errno)); + } + int s2 = getnameinfo((struct sockaddr *)&m_addr, sizeof(m_addr), + m_host_str, sizeof(m_host_str), NULL, 0, 0); + if (s2 != 0) { + fprintf(stderr, "IPv6Address::getsockname(): Address to name " + "translation failed: %s\n", gai_strerror(s2)); + } + } + return s1; +} + +bool IPv6Address::operator==(const IPAddress& p_addr) const +{ + return memcmp(&m_addr.sin6_addr, &(((const IPv6Address&)p_addr).m_addr.sin6_addr), sizeof(m_addr.sin6_addr)) == 0; +} + +bool IPv6Address::operator!=(const IPAddress& p_addr) const +{ + return !(*this == p_addr); +} + +IPAddress& IPv6Address::operator=(const IPAddress& p_addr) +{ + clean_up(); + memcpy(&m_addr, &((const IPv6Address&)p_addr).m_addr, sizeof(m_addr)); + strncpy(m_host_str, ((const IPv6Address&)p_addr).m_host_str, sizeof(m_host_str)); + strncpy(m_addr_str, ((const IPv6Address&)p_addr).m_addr_str, sizeof(m_addr_str)); + return *this; +} + +void IPv6Address::push_raw(Text_Buf& p_buf) const +{ + p_buf.push_raw(sizeof(m_addr.sin6_family), &m_addr.sin6_family); + p_buf.push_raw(sizeof(m_addr.sin6_port), &m_addr.sin6_port); + p_buf.push_raw(sizeof(m_addr.sin6_flowinfo), &m_addr.sin6_flowinfo); + p_buf.push_raw(sizeof(m_addr.sin6_addr), &m_addr.sin6_addr); + p_buf.push_raw(sizeof(m_addr.sin6_scope_id), &m_addr.sin6_scope_id); +} + +void IPv6Address::pull_raw(Text_Buf& p_buf) +{ + clean_up(); + p_buf.pull_raw(sizeof(m_addr.sin6_family), &m_addr.sin6_family); + p_buf.pull_raw(sizeof(m_addr.sin6_port), &m_addr.sin6_port); + p_buf.pull_raw(sizeof(m_addr.sin6_flowinfo), &m_addr.sin6_flowinfo); + p_buf.pull_raw(sizeof(m_addr.sin6_addr), &m_addr.sin6_addr); + p_buf.pull_raw(sizeof(m_addr.sin6_scope_id), &m_addr.sin6_scope_id); +} + +void IPv6Address::clean_up() +{ + memset(&m_addr, 0, sizeof(m_addr)); + memset(m_host_str, 0, sizeof(m_host_str)); + memset(m_addr_str, 0, sizeof(m_addr_str)); +} + +bool IPv6Address::is_local() const +{ + const unsigned char localhost_bytes[] = + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; + const unsigned char mapped_ipv4_localhost[] = + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1 }; + + return (memcmp(m_addr.sin6_addr.s6_addr, localhost_bytes, 16) == 0 + || memcmp(m_addr.sin6_addr.s6_addr, mapped_ipv4_localhost, 16) == 0); +} + +bool IPv6Address::is_valid(const char *p_addr) +{ + if (p_addr == NULL) { + return false; + } else { + IPv6Address addr; + return addr.set_addr(p_addr); + } +} +#endif // LINUX || CYGWIN17 diff --git a/common/NetworkHandler.hh b/common/NetworkHandler.hh new file mode 100644 index 0000000..138bb67 --- /dev/null +++ b/common/NetworkHandler.hh @@ -0,0 +1,188 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef NETWORKHANDLER_H_ +#define NETWORKHANDLER_H_ + +#include "platform.h" +// platform.h includes sys/socket.h +#include +#include +#include + +#ifdef WIN32 +#include + +#if CYGWIN_VERSION_DLL_MAJOR >= 1007 +#define CYGWIN17 +#else +#define CYGWIN15 +#endif + +#endif + +// For legacy (e.g. Solaris 6) systems. +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif + +typedef enum { ipv0 = -1, ipv4 = 0, ipv6 } NetworkFamily; + +class Text_Buf; + +class IPAddress; +class IPv4Address; +#if defined(LINUX) || defined(CYGWIN17) +class IPV6Address; +#endif +class NetworkHandler; +class HCNetworkHandler; + +class IPAddress { +public: + virtual ~IPAddress() = 0; + static IPAddress *create_addr(const NetworkFamily& p_family); + static IPAddress *create_addr(const char *p_addr); + // Always return something. + virtual const char *get_host_str() const = 0; + virtual const char *get_addr_str() const = 0; + virtual bool operator==(const IPAddress& p_addr) const = 0; + virtual bool operator!=(const IPAddress& p_addr) const = 0; + virtual IPAddress& operator=(const IPAddress& p_addr) = 0; + // Encode and decode the address and the corresponding port for internal + // communication. Used by connected ports. + virtual void push_raw(Text_Buf& p_buf) const = 0; + virtual void pull_raw(Text_Buf& p_buf) = 0; + virtual void clean_up() = 0; + virtual int accept(int p_sockfd) = 0; + // Return the current address and port to which the socket is bound to. + virtual int getsockname(int p_sockfd) = 0; + virtual unsigned short get_port() const = 0; + virtual void set_port(unsigned short p_port) = 0; + virtual bool set_addr(const char *p_addr, unsigned short p_port = 0) = 0; + virtual const struct sockaddr *get_addr() const = 0; + virtual socklen_type get_addr_len() const = 0; + virtual bool is_local() const = 0; +}; + +class IPv4Address : public IPAddress { +public: + IPv4Address(); + // Does DNS lookup. + IPv4Address(const char *p_addr, unsigned short p_port = 0 /* Any port. */); + //IPv4Address(const IPv4Address& p_addr) = default; + //There are no pointers, so the compiler generated copy is OK. + ~IPv4Address(); + + bool operator==(const IPAddress& p_addr) const; + bool operator!=(const IPAddress& p_addr) const; + IPAddress& operator=(const IPAddress& p_addr); + void push_raw(Text_Buf& p_buf) const; + void pull_raw(Text_Buf& p_buf); + void clean_up(); + int accept(int p_sockfd); + int getsockname(int p_sockfd); + inline unsigned short get_port() const { return ntohs(m_addr.sin_port); } + inline void set_port(unsigned short p_port) { m_addr.sin_port = htons(p_port); } + bool set_addr(const char *p_addr, unsigned short p_port = 0); + inline const struct sockaddr *get_addr() const { return (const struct sockaddr *)&m_addr; } + inline socklen_type get_addr_len() const { return sizeof(m_addr); } + inline const char *get_host_str() const { return strlen(m_host_str) > 0 ? m_host_str : m_addr_str; } + inline const char *get_addr_str() const { return strlen(m_addr_str) > 0 ? m_addr_str : m_host_str; } + static bool is_valid(const char *p_addr); + bool is_local() const; +private: + sockaddr_in m_addr; + char m_host_str[NI_MAXHOST]; // DNS name. + char m_addr_str[INET_ADDRSTRLEN]; // Address in numeric format. +}; + +#if defined(LINUX) || defined(CYGWIN17) +class IPv6Address : public IPAddress { +public: + IPv6Address(); + // Does DNS lookup. + IPv6Address(const char *p_addr, unsigned short p_port = 0 /* Any port. */); + //IPv6Address(const IPv6Address& p_addr) = default; + //There are no pointers, so the compiler generated copy is OK. + ~IPv6Address(); + + bool operator==(const IPAddress& p_addr) const; + bool operator!=(const IPAddress& p_addr) const; + IPAddress& operator=(const IPAddress& p_addr); + void push_raw(Text_Buf& p_buf) const; + void pull_raw(Text_Buf& p_buf); + void clean_up(); + int accept(int p_sockfd); + int getsockname(int p_sockfd); + inline unsigned short get_port() const { return ntohs(m_addr.sin6_port); } + inline void set_port(unsigned short p_port) { m_addr.sin6_port = htons(p_port); } + bool set_addr(const char *p_addr, unsigned short p_port = 0); + inline const struct sockaddr *get_addr() const { return (const struct sockaddr *)&m_addr; } + inline socklen_type get_addr_len() const { return sizeof(m_addr); } + inline const char *get_host_str() const { return strlen(m_host_str) > 0 ? m_host_str : m_addr_str; } + const char *get_addr_str() const; + static bool is_valid(const char *p_addr); + bool is_local() const; +private: + sockaddr_in6 m_addr; + char m_host_str[NI_MAXHOST]; // DNS name. + char m_addr_str[INET6_ADDRSTRLEN]; // Address in numeric format. +}; +#endif // LINUX || CYGWIN17 + +class NetworkHandler { +public: + NetworkHandler(); + NetworkHandler(const NetworkFamily& p_family); + NetworkHandler(const char *p_addr); + + inline void set_family(const NetworkFamily& p_family) { m_family = p_family; } + void set_family(const char *p_addr); + inline const NetworkFamily& get_family() const { return m_family; } + int socket(); + static int socket(const NetworkFamily& p_family); +private: + NetworkHandler(const NetworkHandler& p_handler); + NetworkHandler& operator=(const NetworkHandler& p_handler); +protected: + NetworkFamily m_family; +}; + +class HCNetworkHandler : public NetworkHandler { +public: + HCNetworkHandler(); + ~HCNetworkHandler(); + + bool set_local_addr(const char *p_addr, unsigned short p_port = 0 /* Any port. */); + bool set_mc_addr(const char *p_addr, unsigned short p_port = 0 /* Any port. */); + int getsockname_local_addr(int p_sockfd); + int bind_local_addr(int p_sockfd) const; + int connect_to_mc(int p_sockfd) const; + inline const char *get_mc_host_str() const { return m_mc_addr->get_host_str(); } + inline const char *get_mc_addr_str() const { return m_mc_addr->get_addr_str(); } + inline const char *get_local_host_str() const { return m_local_addr->get_host_str(); } + inline const char *get_local_addr_str() const { return m_local_addr->get_addr_str(); } + inline IPAddress *get_mc_addr() const { return m_mc_addr; } + inline IPAddress *get_local_addr() const { return m_local_addr; } + inline unsigned short get_mc_port() const { return m_mc_addr->get_port(); } + inline unsigned short get_local_port() const { return m_local_addr->get_port(); } +private: + HCNetworkHandler(const HCNetworkHandler& p_handler); + HCNetworkHandler& operator=(const HCNetworkHandler& p_handler); + + IPAddress *m_mc_addr; + IPAddress *m_local_addr; +}; + +#endif // NETWORKHANDLER_H_ diff --git a/common/Path2.cc b/common/Path2.cc new file mode 100644 index 0000000..a150300 --- /dev/null +++ b/common/Path2.cc @@ -0,0 +1,97 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "Path2.hh" + +#include "path.h" +//#include "dbgnew.hh" + +using std::string; + +const char Path::SEPARATOR = '/'; + +std::string Path::normalize(const std::string& original) { + std::string result; + bool last_slash = false; + for (size_t i = 0; i < original.size(); ++i) { + if (original[i] != SEPARATOR) { + result += original[i]; + last_slash = false; + continue; + } + + if (!last_slash) { + last_slash = true; + result += original[i]; + } + } + return result; +} + +std::string Path::get_abs_path(const std::string& fname) { + if (fname.empty()) { + return std::string(1, SEPARATOR); + } + + if (fname[0] == SEPARATOR) { + return normalize(fname); + } + + expstring_t working_dir = get_working_dir(); + std::string work_dir(working_dir); + Free(working_dir); + work_dir += SEPARATOR; + work_dir.append(fname); + return normalize(work_dir); +} + +std::string Path::get_file(const std::string& path) { + size_t idx = path.rfind(SEPARATOR); + + if (idx == string::npos) { + return path; + } + if (idx == path.size() - 1) { + return string(); + } + + return path.substr(idx + 1); +} + +string Path::get_dir(const string& path) { + size_t idx = path.rfind(SEPARATOR); + + if (idx == string::npos) { + return string(); + } + return path.substr(0, idx + 1); +} + +string Path::compose(const string& path1, const string& path2) { + if (path1.empty()) { + return path2; + } + + if (path2.empty()) { + return path1; + } + + string result = path1; + if (result[result.size() - 1] != SEPARATOR + && path2[0] != SEPARATOR) { + result += SEPARATOR; + } + + result.append(path2); + + return result; +} + +bool Path::is_absolute(const string& path) { + return (!path.empty() && path[0] == SEPARATOR); +} + diff --git a/common/Path2.hh b/common/Path2.hh new file mode 100644 index 0000000..a2170c9 --- /dev/null +++ b/common/Path2.hh @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef PATH_HH_ +#define PATH_HH_ + +#include + + +class Path { +private: + Path(); +public: + static const char SEPARATOR; + + static std::string normalize(const std::string& original); + + /* Creates a normalized absolute path from the given filename. + * The relative path will be resolved according to + * the current working directory. */ + static std::string get_abs_path(const std::string& fname); + + /* Returns the filename from the path. (The suffix after the last '/') + * e.g.: "abc/def" -> "def" + * "abc" -> "abc" + * "abc/" -> "" + */ + static std::string get_file(const std::string& path); + /* Returns the directory part of the given path. + * e.g.: "/a/b/cde -> "/a/b/" + * "abc" -> "" + * "../abc" -> "../" + * "/" -> "/" */ + static std::string get_dir(const std::string& path); + + static std::string compose(const std::string& path1, const std::string& path2); + + static bool is_absolute(const std::string& path); +}; + +#endif diff --git a/common/Quadruple.cc b/common/Quadruple.cc new file mode 100644 index 0000000..2b8111c --- /dev/null +++ b/common/Quadruple.cc @@ -0,0 +1,619 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "memory.h" +#include "pattern.hh" +#include "Quadruple.hh" + +Quad::Quad() : u() { + u.value = 0; +} + +Quad::Quad(unsigned int value) : u() { + u.value = value; +} + +Quad::Quad(unsigned char group, unsigned char plane, unsigned char row, + unsigned char cell) : u() { + u.comp.group = group; + u.comp.plane = plane; + u.comp.row = row; + u.comp.cell = cell; +} + +Quad::Quad(const Quad& rhs) : u() { + u.value = rhs.u.value; +} + +unsigned int Quad::get_value() const { + return u.value; +} + +void Quad::set(int field, unsigned char c) { + switch (field) { + case 0: + u.comp.group = c; + break; + case 1: + u.comp.plane = c; + break; + case 2: + u.comp.row = c; + break; + case 3: + u.comp.cell = c; + break; + } +} + +void Quad::set(unsigned char group, unsigned char plane, unsigned char row, + unsigned char cell) { + u.comp.group = group; + u.comp.plane = plane; + u.comp.row = row; + u.comp.cell = cell; +} + +const Quad Quad::operator-(const Quad& rhs) const { + return Quad(u.value - rhs.u.value); +} + +const Quad& Quad::operator=(const Quad& rhs) { + u.value = rhs.u.value; + return *this; +} + +bool Quad::operator==(unsigned int i) const { + return u.value == i; +} + +bool Quad::operator==(const Quad& rhs) const { + return u.value == rhs.u.value; +} + +bool Quad::operator<=(const Quad& rhs) const { + return u.value <= rhs.u.value; +} + +bool Quad::operator>=(const Quad& rhs) const { + return u.value >= rhs.u.value; +} + +bool Quad::operator<(const Quad& rhs) const { + return u.value < rhs.u.value; +} + +bool Quad::operator<(const QuadInterval& rhs) const { + return u.value < rhs.lower.u.value; +} + +unsigned char Quad::operator[](int i) const { + switch(i) { + case 0: + return u.comp.group; + case 1: + return u.comp.plane; + case 2: + return u.comp.row; + case 3: + return u.comp.cell; + default: + TTCN_pattern_error("Accessing a nonexistent field of a quadruple: %d.", i); + } + return 0; // to get rid of the warning +} + +char* Quad::get_hexrepr() const { + return Quad::get_hexrepr(u.value); +} + +char* Quad::get_hexrepr(unsigned int value) { + char hex[9]; + hex[8] = '\0'; + get_hexrepr(value, hex); + return mcopystr(hex); +} + +void Quad::get_hexrepr(const Quad& q, char* const str) { + str[0] = 'A' + (q.u.comp.group >> 4); // high end + str[1] = 'A' + (q.u.comp.group & 15); + str[2] = 'A' + (q.u.comp.plane >> 4); + str[3] = 'A' + (q.u.comp.plane & 15); + str[4] = 'A' + (q.u.comp.row >> 4); + str[5] = 'A' + (q.u.comp.row & 15); + str[6] = 'A' + (q.u.comp.cell >> 4); + str[7] = 'A' + (q.u.comp.cell & 15); // low end +} + +char* Quad::char_hexrepr(unsigned char c) { + char hex[3]; + hex[2] = '\0'; + hex[1] = (c & 15) + 'A'; + hex[0] = (c >> 4) + 'A'; + return mcopystr(hex); +} + +// QuadInterval ---------------------------------------------------------------- + +QuadInterval::QuadInterval(Quad p_lower, Quad p_upper) : + lower(p_lower), upper(p_upper) +{ +} + +QuadInterval::QuadInterval(const QuadInterval& rhs) +: lower(rhs.lower), upper(rhs.upper) { +} + +const Quad& QuadInterval::get_lower() const { + return lower; +} + +const Quad& QuadInterval::get_upper() const { + return upper; +} + +bool QuadInterval::contains(const Quad& rhs) const { + return lower <= rhs && upper >= rhs; +} + +bool QuadInterval::contains(const QuadInterval& rhs) const { + return lower <= rhs.lower && upper >= rhs.upper; +} + +bool QuadInterval::has_intersection(const QuadInterval& rhs) const { + return (rhs.lower <= upper && rhs.lower >= lower) || + (rhs.upper <= upper && rhs.upper >= lower); +} + +void QuadInterval::join(const QuadInterval& rhs) { + if (rhs.lower <= lower) + lower = rhs.lower; + if (rhs.upper >= upper) + upper = rhs.upper; +} + +bool QuadInterval::operator <(const Quad& rhs) const { + return upper < rhs; +} + +bool QuadInterval::operator <(const QuadInterval& rhs) const { + return !has_intersection(rhs) && upper < rhs.lower; +} + +unsigned int QuadInterval::width() const { + return (upper - lower).get_value(); +} + +char* QuadInterval::generate_posix() { + expstring_t res = memptystr(); + expstring_t str = 0; + int diff[4]; + int i, j, c, k; + for (i = 0; i < 4; i++) + diff[i] = upper[i] - lower[i]; + Quad q1, q2; + for (c = 0; c < 4 && diff[c] == 0; c++) ; + while (c < 4) { + if (c < 3) + for (i = 0; i <= diff[c]; i++) { + if (i > 0) + res = mputc(res, '|'); + if (diff[c] > 0) { + if (i == 0) { + res = mputc(res, '('); + q1 = q2 = lower; + bool pipe = true; + for (j = 3; j > c; j--) { + if (j == 3 || (j < 3 && q1[j] < 255)) { + if (j < 3 && pipe) + res = mputc(res, '|'); + for (k = 0; k < j; k++) { + res = mputprintf(res, "%s", str = Quad::char_hexrepr(q1[k])); + Free(str); + } + q2.set(j, 255); + res = mputprintf(res, "%s", + str = generate_hex_interval(q1[j], q2[j])); + Free(str); + q1.set(j, 0); + if (j > 0 && q1[j-1] < 255) + q1.set(j - 1, q1[j-1] + 1); + for (k = j + 1; k < 4; k++) { + res = mputprintf(res, "%s", + str = generate_hex_interval(0, 255)); + Free(str); + } + pipe = true; + } else + pipe = false; + } + res = mputc(res, ')'); + } else if (i < diff[c]) { + for (j = 0; j < c; j++) { + res = mputstr(res, str = Quad::char_hexrepr(lower[j])); + Free(str); + } + str = generate_hex_interval(lower[c] + 1, + (unsigned char)(lower[c] + diff[c] - 1)); + res = mputprintf(res, "%s", str); + Free(str); + k = (3 - c) * 2; + if (k < 6) { + for (j = 0; j < k; j++) + res = mputc(res, '.'); + } else + res = mputprintf(res, ".\\{%d\\}", k); + i = diff[c] - 1; + } else { + res = mputc(res, '('); + for (k = c; k < 4 && c < 3; k++) { + q1 = 0; + q2 = upper; + for (j = 0; j <= c; j++) { + q1.set(j, upper[j]); + res = mputstr(res, str = Quad::char_hexrepr(q1[j])); + Free(str); + } + c++; + if (c < 3) + q2.set(c, upper[c] - 1); + res = mputstr(res, str = generate_hex_interval(q1[c], q2[c])); + Free(str); + for (j = c + 1; j < 4; j++) { + q2.set(j, 255); + res = mputstr(res, str = generate_hex_interval(q1[j], q2[j])); + Free(str); + } + if (k < 3 && c < 3) { + res = mputc(res, '|'); + } + } + res = mputc(res, ')'); + return res; + } + } else if (diff[c] == 0) { + c++; + i = diff[c]; + } else { + TTCN_pattern_error("In set interval: end is lower than start."); + Free(res); + return 0; + } + } + else { + for (j = 0; j < 3; j++) { + res = mputstr(res, str = Quad::char_hexrepr(lower[j])); + Free(str); + } + res = mputstr(res, str = generate_hex_interval(lower[3], upper[3])); + Free(str); + return res; + } + } + return res; +} + +char* QuadInterval::generate_hex_interval(unsigned char source, + unsigned char dest) { + expstring_t res = memptystr(); + int s_lo, s_hi, d_lo, d_hi, lo, hi; + s_lo = (source & 15) + 'A'; + s_hi = (source >> 4) + 'A'; + d_lo = (dest & 15) + 'A'; + d_hi = (dest >> 4) + 'A'; + lo = d_lo - s_lo; + hi = d_hi - s_hi; + if (hi > 0) + res = mputc(res, '('); + + if (hi == 0) { + if (lo < 0) { // This is possibly reported during parsing. + TTCN_pattern_error("Illegal interval in set: start > end."); + } else if (lo > 0) { + res = mputc(res, (char)s_hi); + if (s_lo == 'A' && d_lo == 'P') + res = mputc(res, '.'); + else + res = mputprintf(res, "[%c-%c]", s_lo, d_lo); + } else { + res = mputc(res, (char)s_hi); + res = mputc(res, (char)s_lo); + } + return res; + } + + bool alt = false; + if (hi > 0) { + if (s_lo != 'A') { + res = mputprintf(res, "%c[%c-P]", s_hi, s_lo); + s_hi++; + alt = true; + } + if (d_lo != 'P') { + if (alt) + res = mputc(res, '|'); + else + alt = true; + res = mputprintf(res, "%c[A-%c]", d_hi, d_lo); + d_hi--; + } + if (d_hi > s_hi) { + if (alt) + res = mputc(res, '|'); + if (s_hi == 'A' && d_hi == 'P') + res = mputc(res, '.'); + else + res = mputprintf(res, "[%c-%c]", s_hi, d_hi); + res = mputc(res, '.'); + } + } + + if (hi > 0) + res = mputc(res, ')'); + return res; +} + +// -------- QuadSet ------------------------------------------------------------ + +QuadSet::QuadSet() : + set(0), negate(false) +{ +} + +bool QuadSet::add(Quad* p_quad) { + bool contains = false; + quadset_node_t* it = set; + quadset_node_t* after = 0, *it_old = 0; + while (it) { + switch (it->etype) { + case QSET_QUAD: + contains = *(it->u.p_quad) == *p_quad; + if (!contains && *p_quad < *(it->u.p_quad)) + after = it_old; + break; + case QSET_INTERVAL: + contains = it->u.p_interval->contains(*p_quad); + if (!contains && *p_quad < *(it->u.p_quad)) + after = it_old; + break; + } + it_old = it; + it = it->next; + } + if (!contains) { + quadset_node_t* newnode = new quadset_node_t; + newnode->etype = QSET_QUAD; + newnode->u.p_quad = p_quad; + if (after == 0) { // largest element in the set so far + newnode->next = 0; + if (it_old != 0) + it_old->next = newnode; + else + set = newnode; + } else { + newnode->next = after->next; + after->next = newnode; + } + return true; + } else { + delete p_quad; + return false; + } +} + +void QuadSet::add(QuadInterval* interval) { + bool contains = false; + quadset_node_t* it = set; + quadset_node_t* after = 0, *it_old = 0; + while (it) { + switch (it->etype) { + case QSET_QUAD: + if (interval->contains(*(it->u.p_quad))) { // delete the quad + delete it->u.p_quad; + if (it == set) + set = it->next; + quadset_node_t* p = it; + it = it->next; + delete p; + continue; + } else if (*interval < *(it->u.p_quad)) { + after = it_old; + } + break; + case QSET_INTERVAL: + contains = it->u.p_interval->contains(*interval); + if (!contains) { + if (it->u.p_interval->has_intersection(*interval)) { // merge + it->u.p_interval->join(*interval); + delete interval; + join_if_possible(it); + return; + } else if (*interval < *(it->u.p_interval)) + after = it_old; + } + break; + } + it_old = it; + it = it->next; + } + if (!contains) { + quadset_node_t* newnode = new quadset_node_t; + newnode->etype = QSET_INTERVAL; + newnode->u.p_interval = interval; + if (after == 0) { // largest element in the set so far + newnode->next = 0; + if (it_old != 0) + it_old->next = newnode; + else + set = newnode; + } else { + newnode->next = after->next; + after->next = newnode; + } + } else { + delete interval; + } +} + +void QuadSet::join(QuadSet* rhs) { + quadset_node_t* it = rhs->set; + while (it) { + switch (it->etype) { + case QSET_QUAD: + add(new Quad(*(it->u.p_quad))); + break; + case QSET_INTERVAL: + add(new QuadInterval(*(it->u.p_interval))); + break; + } + it = it->next; + } +} + +void QuadSet::set_negate(bool neg) { + negate = neg; +} + +bool QuadSet::has_quad(const Quad& q) const { + quadset_node_t* it = set; + while (it) { + switch(it->etype) { + case QSET_QUAD: + if (q == *(it->u.p_quad)) + return true; + break; + case QSET_INTERVAL: + if (it->u.p_interval->contains(q)) + return true; + } + it = it->next; + } + return false; +} + +bool QuadSet::is_empty() const { + return 0 == set; +} + +char* QuadSet::generate_posix() { + expstring_t str = 0; + if (negate) + do_negate(); + char* res = memptystr(); + res = mputc(res, '('); + quadset_node_t* it = set; + while (it) { + if (it != set) + res = mputc(res, '|'); + switch (it->etype) { + case QSET_QUAD: + str = it->u.p_quad->get_hexrepr(); + res = mputprintf(res, "%s", str); + Free(str); + break; + case QSET_INTERVAL: + str = it->u.p_interval->generate_posix(); + res = mputprintf(res, "%s", str); + Free(str); + break; + } + it = it->next; + } + res = mputc(res, ')'); + return res; +} + +QuadSet::~QuadSet() { + clean(set); +} + +void QuadSet::clean(quadset_node_t* start) { + quadset_node_t* it = start; + while (it) { + switch (it->etype) { + case QSET_QUAD: + delete it->u.p_quad; + break; + case QSET_INTERVAL: + delete it->u.p_interval; + break; + } + quadset_node_t* p = it; + it = it->next; + delete p; + } +} + +void QuadSet::do_negate() { + QuadSet* qs = new QuadSet(); + quadset_node_t* it = set; + Quad q1, q2; + while (it) { + switch (it->etype) { + case QSET_QUAD: + q2 = it->u.p_quad->get_value() - 1; + qs->add_negate_interval(q1, q2); + q1 = q2.get_value() + 1; + break; + case QSET_INTERVAL: + q2 = it->u.p_interval->get_lower().get_value() - 1; + qs->add_negate_interval(q1, q2); + q1 = it->u.p_interval->get_upper().get_value() + 1; + break; + } + it = it->next; + } + if (!(q1 == 0)) { + q2.set(255, 255, 255, 255); + qs->add_negate_interval(q1, q2); + }/* else + delete q1;*/ + clean(set); + set = qs->set; + qs->set = 0; + delete qs; +} + +void QuadSet::add_negate_interval(const Quad& q1, const Quad& q2) { + unsigned int w; + if (q2 >= q1) { + w = q2.get_value() - q1.get_value(); + if (w > 0) + add(new QuadInterval(q1, q2)); + else { + add(new Quad(q2)); + } + } +} + +void QuadSet::join_if_possible(quadset_node_t* start) { + quadset_node_t* it = start->next; + while (it) { + switch (it->etype) { + case QSET_QUAD: + if (start->u.p_interval->contains(*(it->u.p_quad))) { + delete it->u.p_quad; + quadset_node_t* p = it; + it = it->next; + delete p; + continue; + } + break; + case QSET_INTERVAL: + if (start->u.p_interval->has_intersection(*(it->u.p_interval))) { + start->u.p_interval->join(*(it->u.p_interval)); + delete it->u.p_interval; + quadset_node_t* p = it; + it = it->next; + delete p; + continue; + } + break; + } + it = it->next; + } +} diff --git a/common/Quadruple.hh b/common/Quadruple.hh new file mode 100644 index 0000000..2b98dae --- /dev/null +++ b/common/Quadruple.hh @@ -0,0 +1,232 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Ttcn_Quadruple_HH +#define _Ttcn_Quadruple_HH + +class QuadInterval; + +/** \class Quad + * \brief Represents a quadruple. + * + * The stored value can be accessed as an integer or as fields of the + * quadruple. The aim is to help the generation of the posix regular expression + * from TTCN-3 pattern of type universal charstring. This class can create the + * string representation needed by pattern matching functions. + * + * The string representation: + * Every field of the quadruple is converted to its hexadecimal representation + * but the regular 0..F interval is substituted with the continuous A..P + * interval. One quadruple is represented with 8 characters, each from A-P. + */ +class Quad { + + union { + unsigned int value; +#if defined(__sparc__) || defined(__sparc) + struct { + unsigned char group; /* big endian, MSB */ + unsigned char plane; + unsigned char row; + unsigned char cell; + } comp; +#else + struct { + unsigned char cell; /* little endian, LSB */ + unsigned char row; + unsigned char plane; + unsigned char group; + } comp; +#endif + } u; + +public: + + /** + * Default constructor initializes the quadruple to \q{0,0,0,0} + */ + Quad(); + Quad(unsigned int value); + Quad(unsigned char group, unsigned char plane, unsigned char row, + unsigned char cell); + Quad(const Quad& rhs); + + unsigned int get_value() const; + + void set(unsigned char group, unsigned char plane, unsigned char row, + unsigned char cell); + + /** + * Sets the given field of the quadruple. + * @param field 0 - group ... 3 - cell. + * @param c Value to set. + */ + void set(int field, unsigned char c); + + const Quad operator-(const Quad& rhs) const; + const Quad& operator=(const Quad& rhs); + bool operator==(unsigned int i) const; + bool operator==(const Quad& rhs) const; + bool operator<=(const Quad& rhs) const; + bool operator>=(const Quad& rhs) const; + + bool operator<(const Quad& rhs) const; + bool operator<(const QuadInterval& rhs) const; + + /** + * Getter function for easy access to fields. + * @param i Field selector: 0 - group ... 3 - cell + * @return Value of the field. + */ + unsigned char operator[](int i) const; + + /** + * Returns the hex representation of this quadruple. [A-P]{8} + * The string must be deallocated by the caller with Free() + */ + char* get_hexrepr() const; + + /** + * Returns the hex representation of \p value. [A-P]{8} + * The string must be deallocated by the caller with Free() + */ + static char* get_hexrepr(unsigned int value); + + /** Fills \p str with the hex representation. + * str[0] gets the upper half of the most significant byte (group) + * str[7] gets the lower half of the least significant byte (cell) + */ + static void get_hexrepr(const Quad& q, char* const str); + + /** + * Returns the hex representation of one field of the quadruple. [A-P]{2} + * The string must be deallocated by the caller with Free() + */ + static char* char_hexrepr(unsigned char c); +}; + +/** \class QuadInterval + * \brief Represents an interval in a regular expression set. + * + * The interval is given with its lower and upper boundary. Boundaries are + * given as pointers to quadruples: \a lower and \a upper. + * + * To help creating more optimal regular expressions some basic operation is + * implemented: \a contains, \a has_intersection, \a join. + */ +class QuadInterval { + Quad lower; + Quad upper; + + friend class Quad; + +public: + QuadInterval(Quad p_lower, Quad p_upper); + + QuadInterval(const QuadInterval& rhs); + + const Quad& get_lower() const; + const Quad& get_upper() const; + + bool contains(const Quad& rhs) const; + bool contains(const QuadInterval& rhs) const; + bool has_intersection(const QuadInterval& rhs) const; + void join(const QuadInterval& rhs); + + /** + * operator<() + * @param rhs A quadruple. + * @return true if value of \a rhs is larger than value of the upper boundary. + */ + bool operator<(const Quad& rhs) const; + /** + * operator<() + * @param rhs A QuadInterval. + * @return true if \a rhs does not intersect with \a this and lower boundary + * of \a rhs is larger than upper boundary of \a this. + */ + bool operator<(const QuadInterval& rhs) const; + + unsigned int width() const; + + /** + * Generate a posix regular expression for the interval. + * @return pointer to the string which should be freed by the caller. + */ + char* generate_posix(); + +private: + char* generate_hex_interval(unsigned char source, unsigned char dest); +}; + +/** \class QuadSet + * \brief Represents a set in a regular expression. + * + * Stores the quadruples and the intervals in the set and creates a posix + * regular expression. + */ +class QuadSet { + + enum elemtype_t { + QSET_QUAD, + QSET_INTERVAL + }; + + /** + * Linked list storing the quadruples and intervals. This list is kept sorted + * to ease the POSIX regular expression generation in case of negated sets. + */ + typedef struct _quadset_node_t { + union { + Quad* p_quad; + QuadInterval* p_interval; + } u; + _quadset_node_t* next; + elemtype_t etype; + } quadset_node_t; + + quadset_node_t* set; + bool negate; + + /// Copy constructor disabled + QuadSet(const QuadSet&); + /// Assignment disabled + QuadSet& operator=(const QuadSet&); +public: + QuadSet(); + + bool add(Quad* p_quad); + void add(QuadInterval* interval); + + void join(QuadSet* rhs); + + void set_negate(bool neg); + + bool has_quad(const Quad& q) const; + bool is_empty() const; + + /** + * Generate a posix regular expression for the set. + * @return pointer to the string which should be freed by the caller. + */ + char* generate_posix(); + + ~QuadSet(); + +private: + void clean(quadset_node_t* start); + + /** + * Generate the disjoint set of \a this. + */ + void do_negate(); + + void add_negate_interval(const Quad& q1, const Quad& q2); + void join_if_possible(quadset_node_t* start); +}; + +#endif diff --git a/common/cfg_process_utils.hh b/common/cfg_process_utils.hh new file mode 100644 index 0000000..05ecf16 --- /dev/null +++ b/common/cfg_process_utils.hh @@ -0,0 +1,108 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef CFG_PROCESS_UTILS_HH_ +#define CFG_PROCESS_UTILS_HH_ + + +#include +#include + +#include "Path2.hh" + +template +class IncludeElem { +public: + std::string dir; + std::string fname; + FILE* fp; + T_BUFFER_STATE buffer_state; + int line_number; + + + IncludeElem(const std::string& fname_) + : dir(Path::get_dir(fname_)), fname(Path::get_file(fname_)), + fp(NULL), buffer_state(NULL), line_number(-1) { } + + IncludeElem(const std::string& fname_, FILE* fp_) + : dir(Path::get_dir(fname_)), fname(Path::get_file(fname_)), + fp(fp_), buffer_state(NULL), line_number(-1) { } + + bool equals(const std::string& path) const { + return Path::compose(dir, fname) == path; + } + + std::string get_full_path() const { + return Path::compose(dir, fname); + } + +}; + +template +std::string dump_include_chain(const std::deque >& chain) { + + std::string result; + if (chain.empty()) { + return result; + } + + typename std::deque >::const_iterator it = chain.begin(); + result.append(it->dir).append(it->fname); + for (++it; it != chain.end(); ++it) { + result.append("->"); + result.append(it->dir).append(it->fname); + } + return result; +} + +template +std::string switch_lexer(std::deque >* p_include_chain, + const std::string& include_file, T_BUFFER_STATE p_current_buffer, + T_BUFFER_STATE (*p_yy_create_buffer)(FILE*, int), + void (*p_yy_switch_to_buffer)(T_BUFFER_STATE), + int p_current_line, int p_buf_size) { + + if (include_file.empty()) { + return std::string("Empty file name."); + } + + std::string abs_path; + if (Path::is_absolute(include_file)) { + abs_path = include_file; + } else { + abs_path = Path::normalize(Path::compose(p_include_chain->back().dir, include_file)); + } + + for (typename std::deque >::iterator it = p_include_chain->begin(); + it != p_include_chain->end(); ++it) { + if (it->equals(abs_path)) { + p_include_chain->push_back(IncludeElem(abs_path)); + std::string error_msg("Circular import chain detected:\n"); + error_msg.append(dump_include_chain(*p_include_chain)); + p_include_chain->pop_back(); + return error_msg; + } + } + + p_include_chain->back().buffer_state = p_current_buffer; + p_include_chain->back().line_number = p_current_line; + + FILE* fp = fopen(abs_path.c_str(), "r"); + if (!fp) { + std::string error_msg("File not found: "); + error_msg.append(abs_path); + return error_msg; + } + + IncludeElem new_elem(abs_path, fp); + p_include_chain->push_back(new_elem); + new_elem.buffer_state = p_yy_create_buffer(fp, p_buf_size); + p_yy_switch_to_buffer(new_elem.buffer_state); + return std::string(""); +} + +#endif diff --git a/common/config_preproc.cc b/common/config_preproc.cc new file mode 100644 index 0000000..db1d3d3 --- /dev/null +++ b/common/config_preproc.cc @@ -0,0 +1,379 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "config_preproc.h" +#include +#include +#include + +void string_chain_add(string_chain_t **ec, char *s) +{ + string_chain_t *i = *ec, *new_ec; + if (i != NULL) { + for ( ; ; ) { + if (!strcmp(i->str, s)) { + Free(s); + return; + } + if (i->next == NULL) break; + i = i->next; + } + } + new_ec = (string_chain_t*) Malloc(sizeof(*new_ec)); + new_ec->str = s; + new_ec->next = NULL; + if (i != NULL) i->next = new_ec; + else *ec = new_ec; +} + +char* string_chain_cut(string_chain_t **ec) +{ + string_chain_t *i = *ec; + if (i != NULL) { + char *s = i->str; + *ec = i->next; + Free(i); + return s; + } else return NULL; +} + +/** search the position of a key; returns 1 if found, 0 otherwise. the + * position is returned in \a pos. */ +static int string_map_pos(const string_map_t *map, const char *key, size_t *pos) +{ + size_t l=0, r=map->n; + string_keyvalue_t **data=map->data; + while(lkey, key)<0) l=m+1; + else r=m; + } + if(l>=map->n) { + *pos=map->n; + return 0; + } + else { + *pos=l; + if(!strcmp(data[l]->key, key)) return 1; + return 0; + } +} + +const char* string_map_add(string_map_t *map, char *key, + char *value, size_t value_len) +{ + size_t pos; + if (string_map_pos(map, key, &pos)) { + /* replacing the old value */ + Free(map->data[pos]->value); + map->data[pos]->value = value; + map->data[pos]->value_len = value_len; + return map->data[pos]->key; + } else { + /* creating a new entry */ + map->n++; + map->data = (string_keyvalue_t**) + Realloc(map->data, (map->n) * sizeof(*map->data)); + memmove(map->data + pos + 1, map->data + pos, + (map->n - pos - 1) * sizeof(*map->data)); + map->data[pos] = (string_keyvalue_t*)Malloc(sizeof(**map->data)); + map->data[pos]->key = key; + map->data[pos]->value = value; + map->data[pos]->value_len = value_len; + return NULL; + } +} + +const char* string_map_get_bykey(const string_map_t *map, + const char *key, size_t *value_len) +{ + size_t pos; + const char* s; + if(string_map_pos(map, key, &pos)) { + *value_len=map->data[pos]->value_len; + return map->data[pos]->value; + } + else if((s=getenv(key))) { + *value_len=strlen(s); + return s; + } + else { + *value_len=0; + return NULL; + } +} + +string_map_t* string_map_new(void) +{ + string_map_t *map=(string_map_t*)Malloc(sizeof(string_map_t)); + map->n=0; + map->data=NULL; + return map; +} + +/* Used only for debugging purposes +void string_map_dump(const string_map_t *map) +{ + size_t i; + fprintf(stderr, "--------\n- n: %u -\n--------\n", map->n); + for(i=0; in; i++) + fprintf(stderr, "%u: `%s' -> `%s' (%u)\n", i, + map->data[i]->key, map->data[i]->value, + map->data[i]->value_len); + fprintf(stderr, "--------\n"); +} +*/ + +void string_map_free(string_map_t *map) +{ + size_t i; + for(i=0; in; i++) { + Free(map->data[i]->key); + Free(map->data[i]->value); + Free(map->data[i]); + } + Free(map->data); + Free(map); +} + +char *get_macro_id_from_ref(const char *str) +{ + char *ret_val = NULL; + if (str != NULL && str[0] == '$' && str[1] == '{') { + size_t i = 2; + /* skip over the whitespaces after the brace */ + while (str[i] == ' ' || str[i] == '\t') i++; + if ((str[i] >= 'A' && str[i] <= 'Z') || + (str[i] >= 'a' && str[i] <= 'z')) { + /* the first character of the id shall be a letter */ + do { + ret_val = mputc(ret_val, str[i]); + i++; + } while ((str[i] >= 'A' && str[i] <= 'Z') || + (str[i] >= 'a' && str[i] <= 'z') || + (str[i] >= '0' && str[i] <= '9') || + str[i] == '_'); + if (str[i] != ' ' && str[i] != '\t' && str[i] != ',' && str[i] != '}') { + /* the next character after the id is not a whitespace or , or } */ + Free(ret_val); + ret_val = NULL; + } + } + } + return ret_val; +} + +int string_is_int(const char *str, size_t len) +{ + enum { INITIAL, FIRST, ZERO, MORE, ERR } state = INITIAL; + /* state: expected characters + * INITIAL: +, -, first digit + * FIRST: first digit + * MORE, ZERO: more digit(s) + * ERR: error was found, stop + */ + size_t i; + if(str==NULL || str[0]=='\0') return 0; + for (i = 0; str[i] != '\0'; i++) { + char c = str[i]; + switch (state) { + case INITIAL: + if (c == '+' || c == '-') state = FIRST; + else if (c == '0') state = ZERO; + else if (c >= '1' && c <= '9') state = MORE; + else state = ERR; + break; + case FIRST: + if (c == '0') state = ZERO; + else if (c >= '1' && c <= '9') state = MORE; + else state = ERR; + break; + case ZERO: + if (c >= '0' && c <= '9') { + state = MORE; + } else state = ERR; + break; + case MORE: + if (c >= '0' && c <= '9') /* do nothing */; + else state = ERR; + default: + break; + } + if (state == ERR) return 0; + } + if (state != ZERO && state != MORE) return 0; + if(i!=len) return 0; + return 1; +} + +int string_is_float(const char *str, size_t len) +{ + enum { INITIAL, FIRST_M, ZERO_M, MORE_M, FIRST_F, MORE_F, INITIAL_E, + FIRST_E, ZERO_E, MORE_E, ERR } state = INITIAL; + /* state: expected characters + * INITIAL: +, -, first digit of integer part in mantissa + * FIRST_M: first digit of integer part in mantissa + * ZERO_M, MORE_M: more digits of mantissa, decimal dot, E + * FIRST_F: first digit of fraction + * MORE_F: more digits of fraction, E + * INITIAL_E: +, -, first digit of exponent + * FIRST_E: first digit of exponent + * ZERO_E, MORE_E: more digits of exponent + * ERR: error was found, stop + */ + size_t i; + if(str==NULL || str[0]=='\0') return 0; + for (i = 0; str[i] != '\0'; i++) { + char c = str[i]; + switch (state) { + case INITIAL: + if (c == '+' || c == '-') state = FIRST_M; + else if (c == '0') state = ZERO_M; + else if (c >= '1' && c <= '9') state = MORE_M; + else state = ERR; + break; + case FIRST_M: + if (c == '0') state = ZERO_M; + else if (c >= '1' && c <= '9') state = MORE_M; + else state = ERR; + break; + case ZERO_M: + if (c == '.') state = FIRST_F; + else if (c == 'E' || c == 'e') state = INITIAL_E; + else if (c >= '0' && c <= '9') { + state = MORE_M; + } else state = ERR; + break; + case MORE_M: + if (c == '.') state = FIRST_F; + else if (c == 'E' || c == 'e') state = INITIAL_E; + else if (c >= '0' && c <= '9') /* do nothing */; + else state = ERR; + break; + case FIRST_F: + if (c >= '0' && c <= '9') state = MORE_F; + else state = ERR; + break; + case MORE_F: + if (c == 'E' || c == 'e') state = INITIAL_E; + else if (c >= '0' && c <= '9') /* do nothing */; + else state = ERR; + break; + case INITIAL_E: + if (c == '+' || c == '-') state = FIRST_E; + else if (c == '0') state = ZERO_E; + else if (c >= '1' && c <= '9') state = MORE_E; + else state = ERR; + break; + case FIRST_E: + if (c == '0') state = ZERO_E; + else if (c >= '1' && c <= '9') state = MORE_E; + else state = ERR; + break; + case ZERO_E: + if (c >= '0' && c <= '9') { + state = MORE_E; + } else state = ERR; + break; + case MORE_E: + if (c >= '0' && c <= '9') /* do nothing */; + else state = ERR; + default: + break; + } + if (state == ERR) return 0; + } + if (state != MORE_F && state != ZERO_E && state != MORE_E + && state != ZERO_M && state != MORE_M) + return 0; + if(i!=len) return 0; + return 1; +} + +int string_is_id(const char *str, size_t len) +{ + size_t i; + int has_hyphen, has_underscore; + char first_char; + if (len == 0) return 0; + first_char = str[0]; + if ((first_char < 'a' || first_char > 'z') && + (first_char < 'A' || first_char > 'Z')) return 0; + has_hyphen = 0; + has_underscore = 0; + for (i = 1; i < len; i++) { + char c = str[i]; + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9')) { + /* do nothing */ + } else if (c == '_') { + if (has_hyphen) return 0; + else has_underscore = 1; + } else if (c == '-') { + if (has_underscore || str[i - 1] == '-' || i == len - 1 || + first_char < 'a' || first_char > 'z') return 0; + else has_hyphen = 1; + } else return 0; + } + return 1; +} + +int string_is_bstr(const char *str, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) { + char c = str[i]; + if (c != '0' && c != '1') return 0; + } + return 1; +} + +int string_is_hstr(const char *str, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) { + char c = str[i]; + if ((c < '0' || c >'9') && (c < 'A' || c > 'F') && (c < 'a' || c > 'f')) + return 0; + } + return 1; +} + +int string_is_ostr(const char *str, size_t len) +{ + if (len % 2) return 0; + else return string_is_hstr(str, len); +} + +int string_is_hostname(const char *str, size_t len) +{ + enum { INITIAL, ALPHANUM, DOT, DASH, COLON, PERCENT } state = INITIAL; + size_t i; + for (i = 0; i < len; i++) { + char c = str[i]; + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9')) { + state = ALPHANUM; + } else if (c == '.') { + if (state == ALPHANUM) state = DOT; + else return 0; + } else if (c == ':') { + if (state == INITIAL || state == ALPHANUM || state == COLON) state = COLON; + else return 0; + } else if (c == '%') { + if (state == ALPHANUM) state = PERCENT; + else return 0; + } else if (c == '-' || c == '_') { + if (state == INITIAL || state == DOT || state == COLON || state == PERCENT) return 0; + else state = DASH; + } else { + return 0; + } + } + if (state == ALPHANUM || state == DOT) return 1; + else return 0; +} diff --git a/common/config_preproc.h b/common/config_preproc.h new file mode 100644 index 0000000..026d095 --- /dev/null +++ b/common/config_preproc.h @@ -0,0 +1,98 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Common_config_preproc_H +#define _Common_config_preproc_H + +#include + +#include "memory.h" + + extern void config_preproc_error(const char *error_str, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); + +#ifdef __cplusplus +extern "C" { +#endif + + extern void path_error(const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + extern std::string get_cfg_preproc_current_file(); + extern int config_preproc_yylineno; + + /** this struct is used to maintain a list of config files */ + typedef struct string_chain_t { + char *str; + struct string_chain_t *next; + } string_chain_t; + + /** adds a new string to the end of chain (reference), if it is not + * contained by the chain */ + void string_chain_add(string_chain_t **ec, char *s); + /** cuts the head of the chain (reference!) and returns that + * string */ + char* string_chain_cut(string_chain_t **ec); + + /** struct to store string key-value pairs. the value can contain + * null-characters so we store also the length. */ + typedef struct string_keyvalue_t { + char *key; + char *value; + size_t value_len; + } string_keyvalue_t; + + /** an array. keep it sorted */ + typedef struct string_map_t { + size_t n; + string_keyvalue_t **data; + } string_map_t; + + /** adds a new key-value pair. if the key exists, it will be + * overwritten, and the return value is the (old) key. */ + const char* string_map_add(string_map_t *map, char *key, + char *value, size_t value_len); + + /** returns NULL if no such key. the length of value is returned in + * \a value_len */ + const char* string_map_get_bykey(const string_map_t *map, const char *key, + size_t *value_len); + + /** constructor */ + string_map_t* string_map_new(void); + /** destructor */ + void string_map_free(string_map_t *map); + + /** Parses out and returns the macro identifier from macro reference \a str. + * The input shall be in format "${,something}", NULL pointer is + * returned otherwise. Whitespaces are allowed anywhere within the braces. + * The returned string shall be deallocated by the caller using Free(). */ + char *get_macro_id_from_ref(const char *str); + + /** Entry point for preprocessing config files. + * + * @param [in] filename the main config file + * @param [out] filenames main config plus all the included files + * @param [out] defines the macro definitions + * @return 1 if there were errors, 0 otherwise. + */ + int preproc_parse_file(const char *filename, string_chain_t **filenames, + string_map_t **defines); + + int string_is_int(const char *str, size_t len); + int string_is_float(const char *str, size_t len); + int string_is_id(const char *str, size_t len); + int string_is_bstr(const char *str, size_t len); + int string_is_hstr(const char *str, size_t len); + int string_is_ostr(const char *str, size_t len); + int string_is_hostname(const char *str, size_t len); + +#endif /* _Common_config_preproc_H */ diff --git a/common/config_preproc_la.l b/common/config_preproc_la.l new file mode 100644 index 0000000..316b634 --- /dev/null +++ b/common/config_preproc_la.l @@ -0,0 +1,370 @@ +/****************************************************************************** + * 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 + ******************************************************************************/ + +%option noyywrap +%option never-interactive +%option nounput +%option prefix="config_preproc_yy" + +%{ + +#include +#include +#include + +#include +#include + +#include "Path2.hh" +#include "cfg_process_utils.hh" + +#include "config_preproc.h" +#include "path.h" +#include "config_preproc_p.tab.hh" + +//#include "dbgnew.hh" + +#define yylineno config_preproc_yylineno + +extern int add_include_file(const std::string&); + +/* If there are errors in the parsed define sections this value changes to 1. + flex and bison for preprocessing can set it to 1, sometimes without printing + the error message because strings and some other stuff is also parsed by the + actual configuration parser which prints errors */ +int preproc_error_flag; + +/* used to track the curly brackets in the define section */ +static int paren_stack = 0; + +static std::deque >* include_chain = NULL; + +std::string get_cfg_preproc_current_file() { + if (include_chain && !include_chain->empty()) { + return include_chain->back().get_full_path(); + } + return std::string(); +} + +%} + +WHITESPACE [ \t] +WS {WHITESPACE}* +NEWLINE \r|\n|\r\n +LINECOMMENT ("//"|"#")[^\r\n]*{NEWLINE} +NUMBER 0|([1-9][0-9]*) + +TTCN3IDENTIFIER [A-Za-z][A-Za-z0-9_]* + +HEX [0-9A-Fa-f] + +MACRORVALUE ([0-9A-Za-z._-]+)|{IPV6} +IPV6 [0-9A-Fa-f:.]+(%[0-9A-Za-z]+)? + +MACRO_REFERENCE \${TTCN3IDENTIFIER}|\$"{"{WS}{TTCN3IDENTIFIER}{WS}(","{WS}charstring{WS})?"}" +MACRO_REFERENCE_INT \$"{"{WS}{TTCN3IDENTIFIER}{WS}(","{WS}integer{WS})?"}" + + +%x SC_blockcomment SC_cstring +%s SC_include SC_define SC_define_structured SC_ordered_include +%s SC_module_parameters SC_testport_parameters + +%% + /* valid in states SC_blockcomment, SC_cstring */ + int caller_state = INITIAL; + /* valid in state SC_cstring */ + std::string cstring; + + preproc_error_flag = 0; + +"/*" { + caller_state = YY_START; + BEGIN(SC_blockcomment); +} + + +{ +"*/" { + BEGIN(caller_state); + if (YY_START==SC_define || YY_START==SC_define_structured) { + config_preproc_yylval.str_val = NULL; + return FillerStuff; + } +} + +{NEWLINE} yylineno++; + +. /* do nothing */ + +<> { + preproc_error_flag = 1; /* unterminated block comment, error msg. in parser */ + BEGIN(caller_state); +} +} /* SC_blockcomment */ + +{WHITESPACE} { + if (YY_START==SC_define || YY_START==SC_define_structured) { + config_preproc_yylval.str_val = mcopystrn(yytext, yyleng); return FillerStuff; + } +} + +{NEWLINE}|{LINECOMMENT} { + yylineno++; + if (YY_START==SC_define || YY_START==SC_define_structured) { + config_preproc_yylval.str_val = NULL; + return FillerStuff; + } +} + + /* Section delimiters */ + +"["{WS}INCLUDE{WS}"]" BEGIN(SC_include); + +"["{WS}ORDERED_INCLUDE{WS}"]" { + caller_state = YY_START; + BEGIN(SC_ordered_include); +} + +"["{WS}DEFINE{WS}"]" BEGIN(SC_define); + +"["{WS}MODULE_PARAMETERS{WS}"]" BEGIN(SC_module_parameters); +"["{WS}TESTPORT_PARAMETERS{WS}"]" BEGIN(SC_testport_parameters); + + +{ + "["{NUMBER}"]" ; + "["[^\r\n\[\]]*{MACRO_REFERENCE_INT}{WS}[^\r\n\[\]]*"]" ; +} + +"["{WS}LOGGING{WS}"]" BEGIN(INITIAL); +"["{WS}EXECUTE{WS}"]" BEGIN(INITIAL); +"["{WS}EXTERNAL_COMMANDS{WS}"]" BEGIN(INITIAL); +"["{WS}GROUPS{WS}"]" BEGIN(INITIAL); +"["{WS}COMPONENTS{WS}"]" BEGIN(INITIAL); +"["{WS}MAIN_CONTROLLER{WS}"]" BEGIN(INITIAL); + +"["[^\r\n\[\]]*"]" { + preproc_error_flag = 1; + config_preproc_error("Invalid section name `%s'", yytext); +} + +\" { + caller_state = YY_START; + BEGIN(SC_cstring); + cstring.clear(); + + if (caller_state == SC_define_structured) { + cstring += '"'; + } +} + + +{ +\"\" cstring += '"'; + +\" { + /* end of the string */ + BEGIN(caller_state); + switch (YY_START) { + case SC_define_structured: + cstring += '"'; + /* No break */ + case SC_define: + config_preproc_yylval.str_val = mcopystrn(cstring.c_str(), cstring.size()); + cstring.clear(); + return Cstring; + case SC_include: + if (add_include_file(cstring)) preproc_error_flag = 1; + cstring.clear(); + break; + case SC_ordered_include: + { + std::string error_msg = switch_lexer(include_chain, cstring, + YY_CURRENT_BUFFER, yy_create_buffer, yy_switch_to_buffer, yylineno, + YY_BUF_SIZE); + if (error_msg.empty()) { + BEGIN(INITIAL); + } else { + preproc_error_flag = 1; + config_preproc_error(error_msg.c_str()); + } + } + /* no break */ + default: + cstring.clear(); + } /* switch */ +} /* end of string */ + +\\[\\'"?] cstring += yytext[1]; /* backslash-quoted \ or " or ' or ? */ +\\{NEWLINE} yylineno++; +\\a cstring += '\a'; +\\b cstring += '\b'; +\\f cstring += '\f'; +\\n cstring += '\n'; +\\r cstring += '\r'; +\\t cstring += '\t'; +\\v cstring += '\v'; + +\\[0-7]{1,3} { + unsigned int c; + sscanf(yytext + 1, "%o", &c); + /* do not report error in case of invalid octal escape sequences */ + if (c <= 255) cstring += c; + else preproc_error_flag = 1; +} + +\\x{HEX}{1,2} { + unsigned int c; + sscanf(yytext + 2, "%x", &c); + cstring += c; +} + +\\(x[^\\\"]|.) preproc_error_flag = 1; + +{NEWLINE} { + cstring.append(yytext, yyleng); + yylineno++; +} + +. { cstring += yytext[0]; } + +<> { + preproc_error_flag = 1; /* unterminated string literal, error msg. in parser */ + cstring.clear(); + BEGIN(caller_state); + return EOF; +} +} /* SC_cstring */ + + + +{ + +{TTCN3IDENTIFIER} { + config_preproc_yylval.str_val = mcopystrn(yytext, yyleng); + return Identifier; +} + +":="|"=" { return AssignmentChar; } + +{MACRORVALUE} { + config_preproc_yylval.str_val = mcopystrn(yytext, yyleng); + return MacroRValue; +} + +{MACRO_REFERENCE} { + config_preproc_yylval.str_val = mcopystrn(yytext, yyleng); + return MacroReference; +} + +"{" { + ++paren_stack; + BEGIN(SC_define_structured); + return LCurly; +} +} /* SC_define */ + + +{ + +{MACRO_REFERENCE} { + config_preproc_yylval.str_val = mcopystrn(yytext, yyleng); + return MacroReference; +} + +"{" { + ++paren_stack; + return LCurly; +} + +"}" { + if (paren_stack == 0) { /* We don't have any opened curly brackets. */ + preproc_error_flag = 1; + config_preproc_error("Invalid structured definition."); + BEGIN(SC_define); + return RCurly; + } + + --paren_stack; + if (paren_stack == 0) { /* The end of a structured definition. */ + BEGIN(SC_define); + } + return RCurly; +} + +\\\" { /* \" is handled separately in the structured definitions */ + config_preproc_yylval.str_val = mcopystr("\""); + return FString; +} + +\\. { /* Handle escaped characters */ + config_preproc_yylval.str_val = mcopystrn(yytext, yyleng); + return FString; +} + +[^{}"\\$\n\r\t #/]+ { /* Anything except {,},\,$,#,/ and whitespace */ + config_preproc_yylval.str_val = mcopystrn(yytext, yyleng); + return FString; +} + +"/" { + config_preproc_yylval.str_val = mcopystrn(yytext, yyleng); + return FString; +} + +} /* SC_define_structured */ + +<> { + if (include_chain->size() > 1) { // The last fp is owned by the parser + yy_delete_buffer(YY_CURRENT_BUFFER); + fclose(include_chain->back().fp); + include_chain->pop_back(); + yy_switch_to_buffer(include_chain->back().buffer_state); + BEGIN(SC_ordered_include); + } else { + return EOF; + } +} + +. { + switch (YY_START) { + case SC_define: + case SC_define_structured: + preproc_error_flag = 1; + config_preproc_error("Invalid character in [DEFINE] section: '%c'.", yytext[0]); + break; + case SC_include: + case SC_ordered_include: + preproc_error_flag = 1; + config_preproc_error("Invalid character in [%s] section: '%c'.", + (YY_START==SC_include || YY_START==SC_ordered_include) ? "INCLUDE" : "ORDERED_INCLUDE", + yytext[0]); + default: + break; + } +} + + +%% + +void config_preproc_reset(const std::string& filename) { + if (!include_chain) { + include_chain = new std::deque >(); + } else { + include_chain->clear(); + } + + include_chain->push_back(IncludeElem( + filename, config_preproc_yyin)); +} + +void config_preproc_close() { + delete include_chain; + include_chain = NULL; +} + diff --git a/common/config_preproc_p.y b/common/config_preproc_p.y new file mode 100644 index 0000000..939e394 --- /dev/null +++ b/common/config_preproc_p.y @@ -0,0 +1,365 @@ +/****************************************************************************** + * Copyright (c) 2000-2014 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + ******************************************************************************/ + +%{ + +#include +#include +#include +#include +#include + +#include + +#include "config_preproc.h" +#include "path.h" + +#define YYERROR_VERBOSE + +extern FILE *config_preproc_yyin; +extern int config_preproc_lineno; +extern void config_preproc_reset(const std::string& filename); +extern void config_preproc_close(); +int config_preproc_yylex(void); +void config_preproc_yyrestart(FILE *new_file); +extern int preproc_error_flag; + +static void config_preproc_yyerror(const char *error_str); +static int config_preproc_yyparse(void); + +static string_chain_t *config_preproc_filenames; +static string_map_t *config_preproc_defines; + +static char* decode_secret_message(char* encoded); + +%} + +%name-prefix="config_preproc_yy" + +%union{ + char* str_val; /* the usual expstring_t */ + /* a structure to keep track if the last part of the concatenated macro value + was a literal, this is needed because of the stupid and artificial requirement + that two literals cannot follow each other */ + struct { + char* str_val; + int last_literal; + } macro_val; /* 0 or 1 */ +} + +%token FillerStuff "whitespace, newline or comment" +%token AssignmentChar ":= or =" +%token LCurly "{" +%token RCurly "}" +%token FString "sequence of characters" +%token Identifier +%token MacroRValue +%token MacroReference +%token Cstring "charstring value" + +%type FillerStuffConcat +%type MacroAssignmentValueList MacroAssignmentValue +%type StructuredDefinition +%type SimpleValue +%type StructuredValue +%type StructuredValueList +%type MacroRhs + +%destructor { Free($$); } +FillerStuff +Identifier +MacroRValue +MacroReference +Cstring +FillerStuffConcat +SimpleValue +StructuredDefinition +StructuredValue +StructuredValueList +FString +MacroRhs + +%destructor { Free($$.str_val); } +MacroAssignmentValueList +MacroAssignmentValue + +%% + +DefineSections: + optFillerStuffList +| optFillerStuffList MacroAssignments optFillerStuffList + +MacroAssignments: + MacroAssignment +| MacroAssignments FillerStuffList MacroAssignment +; + +MacroAssignment: + Identifier optFillerStuffList AssignmentChar optFillerStuffList MacroRhs { + if (string_map_add(config_preproc_defines, $1, $5, mstrlen($5)) != NULL) { + Free($1); + } +} +; + +MacroRhs: + MacroAssignmentValueList { + $$ = $1.str_val; + } +| + StructuredDefinition { + $$ = $1; +} +; + +StructuredDefinition: + LCurly StructuredValueList RCurly { + $$ = mcopystr("{"); + $$ = mputstr($$, $2); + $$ = mputstr($$, "}"); + Free($2); +} +; + +StructuredValueList: +optFillerStuffList +{ + $$ = mcopystr(""); +} +| StructuredValueList StructuredValue optFillerStuffList + { + $$ = NULL; + $$ = mputstr($$, $1); + $$ = mputstr($$, $2); + Free($1); + Free($2); +} +; + +StructuredValue: + SimpleValue { + $$ = $1; +} +| + LCurly StructuredValueList RCurly { + $$ = mcopystr("{"); + $$ = mputstr($$, $2); + $$ = mputstr($$,"}"); + Free($2); + } +; + +SimpleValue: + MacroReference { + char *macroname; + const char *macrovalue; + size_t macrolen; + if ($1[1] == '{') macroname = get_macro_id_from_ref($1); + else macroname = mcopystr($1 + 1); + macrovalue = string_map_get_bykey(config_preproc_defines, macroname, ¯olen); + if (macrovalue == NULL) { + preproc_error_flag = 1; + config_preproc_error("No macro or environmental variable defined with name `%s'", macroname); + $$ = memptystr(); + } else { + $$ = mcopystr(macrovalue); + } + Free(macroname); + Free($1); + } +| Cstring { $$ = $1;} +| FString { $$ = $1;} +; + +MacroAssignmentValueList: + MacroAssignmentValue { $$ = $1; } +| MacroAssignmentValueList MacroAssignmentValue { + if ($1.last_literal && $2.last_literal) { + preproc_error_flag = 1; + config_preproc_error("Literal `%s' cannot follow another literal", $2.str_val); + } + $$.str_val = mputstr($1.str_val, $2.str_val); + Free($2.str_val); + $$.last_literal = $2.last_literal; + } +; + +MacroAssignmentValue: + Identifier { $$.str_val = $1; $$.last_literal = 1; } +| MacroRValue { $$.str_val = $1; $$.last_literal = 1; } +| Cstring { $$.str_val = $1; $$.last_literal = 1; } +| MacroReference { + char *macroname; + const char *macrovalue; + size_t macrolen; + if ($1[1] == '{') macroname = get_macro_id_from_ref($1); + else macroname = mcopystr($1 + 1); + macrovalue = string_map_get_bykey(config_preproc_defines, macroname, ¯olen); + if (macrovalue == NULL) { + preproc_error_flag = 1; + config_preproc_error("No macro or environmental variable defined with name `%s'", macroname); + $$.str_val = memptystr(); + } else { + $$.str_val = mcopystr(macrovalue); + } + Free(macroname); + Free($1); + $$.last_literal = 0; + } +; + +optFillerStuffList: + /* empty */ +| FillerStuffList +; + +FillerStuffList: + FillerStuffConcat { + const char* magic_str = "TITAN"; + const size_t magic_str_len = 5; + if (mstrlen($1)>magic_str_len*8) { + char* decoded = decode_secret_message($1); + if (strncmp(decoded, magic_str, magic_str_len) == 0) { + printf("%s\n", decoded+magic_str_len); + } + Free(decoded); + } + Free($1); + } +; + +FillerStuffConcat: + FillerStuff { $$ = $1; } +| FillerStuffConcat FillerStuff { + $$ = mputstr($1, $2); + Free($2); + } +; + +%% + +/* BISON error reporting function */ +void config_preproc_yyerror(const char *error_str) +{ + config_preproc_error("%s", error_str); +} + +extern int add_include_file(const std::string& filename) +{ + int error_flag = 0; + if (strlen(filename.c_str()) == filename.size()) { + expstring_t currdirname, dirname, filenamepart, basedir; + currdirname = get_dir_from_path(get_cfg_preproc_current_file().c_str()); + dirname = get_dir_from_path(filename.c_str()); + basedir = get_absolute_dir(dirname, currdirname); + Free(currdirname); + Free(dirname); + filenamepart = get_file_from_path(filename.c_str()); + if (basedir != NULL) { + expstring_t absfilename = compose_path_name(basedir, filenamepart); + switch (get_path_status(absfilename)) { + case PS_FILE: + string_chain_add(&config_preproc_filenames, absfilename); + break; + case PS_DIRECTORY: + config_preproc_error("Included file `%s' is a directory.", absfilename); + error_flag = 1; + break; + case PS_NONEXISTENT: + config_preproc_error("Included file `%s' does not exist.", absfilename); + error_flag = 1; + } + if (error_flag) Free(absfilename); + } else error_flag = 1; + Free(filenamepart); + Free(basedir); + } else { + config_preproc_error("The name of the included file cannot contain NUL " + "character."); + error_flag = 1; + } + return error_flag; +} + +extern int preproc_parse_file(const char *filename, string_chain_t **filenames, + string_map_t **defines) +{ + int error_flag = 0; + config_preproc_filenames=NULL; + config_preproc_defines=string_map_new(); + { + expstring_t dirname=get_dir_from_path(filename); + expstring_t basedir=get_absolute_dir(dirname, NULL); + expstring_t filenamepart=get_file_from_path(filename); + Free(dirname); + if (basedir == NULL) { + error_flag = 1; + goto end; + } + string_chain_add(&config_preproc_filenames, compose_path_name(basedir, filenamepart)); + Free(basedir); + Free(filenamepart); + } + { + string_chain_t *i_chain=config_preproc_filenames; + string_chain_t *i_prev=NULL; + while(i_chain) { + config_preproc_yylineno=1; + config_preproc_yyin = fopen(i_chain->str, "r"); + if (config_preproc_yyin != NULL) { + config_preproc_yyrestart(config_preproc_yyin); + config_preproc_reset(std::string(i_chain->str)); + if (config_preproc_yyparse()) error_flag = 1; + if (preproc_error_flag) error_flag = 1; + fclose(config_preproc_yyin); + config_preproc_close(); + /* During parsing flex or libc may use some system calls (e.g. ioctl) + * that fail with an error status. Such error codes shall be ignored in + * future error messages. */ + errno = 0; + i_prev=i_chain; + i_chain=i_chain->next; + } else { + string_chain_t *i_tmp=i_chain; + config_preproc_error("Cannot open config file `%s': %s", + i_chain->str, + strerror(errno)); + error_flag = 1; + if(i_prev) { + i_prev->next=i_chain->next; + i_chain=i_chain->next; + } + else { + i_chain=i_chain->next; + config_preproc_filenames=i_chain; + } + Free(i_tmp->str); + Free(i_tmp); + } + } + } + + end: + *filenames=config_preproc_filenames; + *defines=config_preproc_defines; + return error_flag; +} + +static char* decode_secret_message(char* encoded) +{ + char* decoded = memptystr(); + size_t i, j, dec_len = mstrlen(encoded) / 8; + for (i=0; i + +#include "license.h" + +int main(void) +{ + printf("0x%08lx\n", gethostid()); + + return 0; +} diff --git a/common/license.c b/common/license.c new file mode 100644 index 0000000..9623f6e --- /dev/null +++ b/common/license.c @@ -0,0 +1,607 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef MINGW +# include +#endif +#include + +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +# include +# include +# ifdef MINGW +# include +# endif +# include +#endif + +#ifdef INTERIX +# include +# include +#endif + +#include "memory.h" +#include "license.h" +#include "version.h" + +#ifdef TTCN3_BUILDNUMBER + /* In pre-release builds: */ +#define TTCN3_VERSION_CHECK TTCN3_MAJOR * 1000000 + TTCN3_MINOR * 10000 + TTCN3_PATCHLEVEL * 100 + TTCN3_BUILDNUMBER +#else + /* In official releases: */ +#define TTCN3_VERSION_CHECK TTCN3_MAJOR * 10000 + TTCN3_MINOR * 100 + TTCN3_PATCHLEVEL +#endif + +#if TTCN3_VERSION_CHECK != TTCN3_VERSION +#error TTCN3_VERSION in version.h does not match the value computed from TTCN3_MAJOR,TTCN3_MINOR,TTCN3_PATCHLEVEL,TTCN3_BUILDNUMBER +/* for debugging: these would appear in the preprocessed file */ +static const int ttcn3_version = TTCN3_VERSION; +static const int ttcn3_version_check = TTCN3_VERSION_CHECK; +#endif + +static const unsigned char dsa_p[] = { 0x90, 0x63, 0x82, 0xae, 0x72, 0x71, 0xac, 0x14, 0xec, 0x9c, 0x71, 0x38, 0x9f, 0xda, 0x8d, 0x52, 0xbd, 0xb1, 0xa7, 0x1a, 0x19, 0xd4, 0x5f, 0xe7, 0x37, 0x3d, 0x44, 0xef, 0xce, 0xa1, 0x99, 0xfa, 0x85, 0xb6, 0x49, 0x77, 0xf1, 0x98, 0x39, 0x6b, 0x71, 0xce, 0x2, 0x42, 0x64, 0x4b, 0xd, 0xad, 0x83, 0xb0, 0x6b, 0x76, 0xba, 0xdc, 0x4f, 0xe0, 0x19, 0xf9, 0xc2, 0x79, 0x6e, 0xbb, 0xc, 0xab, 0x16, 0xae, 0xec, 0x56, 0x75, 0xff, 0x82, 0xb, 0x74, 0xd8, 0x96, 0x42, 0x23, 0x68, 0xf, 0xad, 0x27, 0xee, 0x4c, 0xbf, 0xf2, 0xd4, 0x49, 0x77, 0x8b, 0x1e, 0xf1, 0xdc, 0x5c, 0x4d, 0xfd, 0xa6, 0xd8, 0x5a, 0x70, 0x3f, 0x13, 0xd2, 0xed, 0x3f, 0x59, 0x9, 0x62, 0x2b, 0xb2, 0x8f, 0xcd, 0x7a, 0xa9, 0x3e, 0x6c, 0xb1, 0xe8, 0x80, 0x9d, 0xd2, 0x74, 0xc, 0xc8, 0xdf, 0xa, 0x40, 0xc9, 0xb3 }, + dsa_q[] = { 0xa3, 0xe2, 0x23, 0x73, 0xd3, 0x8a, 0x4b, 0x61, 0xd0, 0x60, 0x41, 0x21, 0x41, 0x6d, 0xc4, 0xf6, 0x8c, 0x5c, 0x89, 0x87 }, + dsa_g[] = { 0x40, 0x6d, 0xfb, 0x6d, 0xb6, 0x6, 0x32, 0xcc, 0xf0, 0xe9, 0x84, 0x16, 0x1e, 0xe1, 0x21, 0xcd, 0x34, 0xe7, 0xbb, 0x6c, 0x98, 0xff, 0xa9, 0xb9, 0xae, 0xe4, 0x6a, 0x61, 0x51, 0xf8, 0x66, 0x83, 0xa4, 0x34, 0x63, 0x81, 0xc4, 0x5f, 0xee, 0x85, 0x74, 0xee, 0x2a, 0x63, 0x9d, 0xcf, 0x97, 0x50, 0xb8, 0x9f, 0x76, 0xd9, 0xe, 0x58, 0xab, 0xac, 0x2e, 0x23, 0xac, 0x95, 0xc3, 0xb7, 0x14, 0xd6, 0x69, 0xff, 0x36, 0xef, 0xa4, 0xa9, 0xe1, 0xd6, 0x7a, 0xfd, 0x9d, 0x68, 0x91, 0xcf, 0x2d, 0xcd, 0x98, 0xc5, 0xe6, 0xf4, 0x1e, 0xde, 0xf8, 0x65, 0x6b, 0xeb, 0x80, 0x41, 0xab, 0xc7, 0x97, 0xcb, 0xbb, 0xc5, 0x5, 0x7, 0x22, 0x81, 0x58, 0x63, 0xf9, 0x67, 0xd4, 0x7c, 0xb6, 0x21, 0x17, 0xea, 0x62, 0xe3, 0xe8, 0x3f, 0x60, 0xb1, 0x51, 0x51, 0x4, 0xf2, 0x6f, 0x5c, 0x47, 0x69, 0x6b, 0xc1 }, + dsa_pub_key[] = { 0x76, 0xe, 0xf, 0x36, 0x77, 0x6, 0x9d, 0xb1, 0xf1, 0x4e, 0x9a, 0x95, 0xae, 0xc9, 0x39, 0xdf, 0x90, 0xd3, 0x94, 0x54, 0xf8, 0xf6, 0x89, 0xc8, 0x11, 0x8d, 0x2e, 0x92, 0x81, 0x6b, 0x2c, 0x37, 0x4, 0x9d, 0x97, 0x9a, 0x43, 0xa3, 0x2e, 0xed, 0x9a, 0x99, 0xb0, 0xcb, 0x9f, 0x4e, 0xea, 0x4f, 0xb7, 0xd5, 0x93, 0xc0, 0x86, 0x1b, 0xc7, 0x97, 0x5f, 0x5, 0xb4, 0xf1, 0xf9, 0xd6, 0x73, 0x97, 0x19, 0xe3, 0xc9, 0xda, 0xfc, 0x39, 0xe0, 0x37, 0xed, 0x7a, 0x62, 0xcb, 0xe3, 0x17, 0x9b, 0x64, 0x3c, 0x46, 0x86, 0x3f, 0x32, 0xec, 0x70, 0xab, 0x5b, 0x87, 0x5a, 0x6e, 0xc3, 0x37, 0xeb, 0x92, 0x58, 0x6c, 0x9e, 0x25, 0x1f, 0x37, 0x4b, 0xcd, 0xb5, 0x22, 0x62, 0x1d, 0x1b, 0x1c, 0xb1, 0x5d, 0xa1, 0xef, 0x50, 0xc3, 0x75, 0xff, 0x2, 0x24, 0x8c, 0xd7, 0x3b, 0x91, 0x77, 0xef, 0x94, 0x76 }; + +/** Big-endian decoding of a 4-byte integer */ +static unsigned int decode_int(const unsigned char *from) +{ + return (unsigned int)from[3] + | ((unsigned int)from[2] << 8) + | ((unsigned int)from[1] << 16) + | ((unsigned int)from[0] << 24); +} + +/** Extract a string from a fixed-length field. + * + * @param from the beginning of the field + * @param max_length the size of the field + * @return a newly allocated string. The caller is responsible for + * calling Free() + * + * Verifies that the unused portion of the field is properly zeroed out + * (no non-NUL characters after the first NUL character). Terminates + * the program with EXIT_FAILURE if there is trailing garbage + * after the end of the string. */ +static char *decode_string(const char *from, size_t max_length) +{ + size_t i, length; + char *ptr; + for (i = 0; i < max_length && from[i] != '\0'; i++); + length = i; + /* Verify that the tail is properly zeroed (no junk). */ + for (i++; i < max_length; i++) + if (from[i] != '\0') { + fputs("License file is corrupted: invalid string encoding\n", + stderr); + exit(EXIT_FAILURE); + } + ptr = (char*)Malloc(length + 1); + memcpy(ptr, from, length); + ptr[length] = '\0'; + return ptr; +} + +static void decode_license(license_struct *to, const license_raw *from) +{ + to->license_file = NULL; + to->unique_id = decode_int(from->unique_id); + to->licensee_name = decode_string(from->licensee_name, + sizeof(from->licensee_name)); + to->licensee_email = decode_string(from->licensee_email, + sizeof(from->licensee_email)); + to->licensee_company = decode_string(from->licensee_company, + sizeof(from->licensee_company)); + to->licensee_department = decode_string(from->licensee_department, + sizeof(from->licensee_department)); + to->valid_from = decode_int(from->valid_from); + to->valid_until = decode_int(from->valid_until); + to->host_id = decode_int(from->host_id); + to->login_name = decode_string(from->login_name, sizeof(from->login_name)); + to->from_major = decode_int(from->from_major); + to->from_minor = decode_int(from->from_minor); + to->from_patchlevel = decode_int(from->from_patchlevel); + to->to_major = decode_int(from->to_major); + to->to_minor = decode_int(from->to_minor); + to->to_patchlevel = decode_int(from->to_patchlevel); + to->feature_list = decode_int(from->feature_list); + + /* Borrow the PER bit for this year */ + /* 1262300400 is Fri Jan 1 00:00:00 2010 */ + if((to->feature_list & FEATURE_PER) && (time(NULL) < 1262300400)) { + to->feature_list |= FEATURE_XER; + } + + to->limitation_type = decode_int(from->limitation_type); + to->max_ptcs = decode_int(from->max_ptcs); +} + +static void check_license_signature(license_raw *lptr) +{ + unsigned char message_digest[SHA_DIGEST_LENGTH]; + SHA_CTX sha_ctx; + DSA *dsa = DSA_new(); + + SHA1_Init(&sha_ctx); + SHA1_Update(&sha_ctx, lptr, sizeof(*lptr) - sizeof(lptr->dsa_signature)); + SHA1_Final(message_digest, &sha_ctx); + + dsa->p = BN_bin2bn(dsa_p, sizeof(dsa_p), NULL); + dsa->q = BN_bin2bn(dsa_q, sizeof(dsa_q), NULL); + dsa->g = BN_bin2bn(dsa_g, sizeof(dsa_g), NULL); + dsa->pub_key = BN_bin2bn(dsa_pub_key, sizeof(dsa_pub_key), NULL); + + switch(DSA_verify(0, message_digest, sizeof(message_digest), + lptr->dsa_signature, sizeof(lptr->dsa_signature), dsa)) { + case 0: + fputs("License file is corrupted: invalid DSA signature.\n", stderr); + exit(EXIT_FAILURE); + case 1: + break; /* valid signature */ + default: + fprintf(stderr, "License signature verification failed: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + exit(EXIT_FAILURE); + } + + DSA_free(dsa); +} + +/** Read a PEM-encoded license from a file. + * + * @param [in] file_name string containing license file name + * @param [out] lptr filled with the decoded license information + * + * If the license information cannot be obtained (bad file name or wrong content), + * terminates the program with EXIT_FAILURE. */ +static void read_license(const char *file_name, license_raw *lptr) +{ + char *name = NULL; + char *header = NULL; + unsigned char *data = NULL; + long len = 0; + struct stat buf; + FILE *fp; + + if (stat(file_name, &buf) != 0) { + fprintf(stderr, "Cannot access license file `%s'. (%s)\n", + file_name, strerror(errno)); + exit(EXIT_FAILURE); + } + if (buf.st_mode & S_IFDIR) { + fprintf(stderr, "The environment variable TTCN3_LICENSE_FILE was set " + "to `%s', which is a directory. It must be set to the file that " + "contains the license key.\n", file_name); + exit(EXIT_FAILURE); + } + fp = fopen(file_name, "r"); + if (fp == NULL) { + fprintf(stderr, "Cannot open license file `%s' for reading. (%s)\n", + file_name, strerror(errno)); + exit(EXIT_FAILURE); + } + if (!PEM_read(fp, &name, &header, &data, &len)) { + fprintf(stderr, "License file is corrupted: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + exit(EXIT_FAILURE); + } + fclose(fp); + if (strcmp(name, "TTCN-3 LICENSE FILE") || strcmp(header, "")) { + fputs("License file is corrupted: invalid header.\n", stderr); + exit(EXIT_FAILURE); + } + if (len != sizeof(*lptr)) { + fputs("License file is corrupted: invalid length.\n", stderr); + exit(EXIT_FAILURE); + } + memcpy(lptr, data, sizeof(*lptr)); + OPENSSL_free(name); + OPENSSL_free(header); + OPENSSL_free(data); +} + +void load_license(license_struct *lptr) +{ + const char *file_name = getenv("TTCN3_LICENSE_FILE"); + if (file_name == NULL) { + fputs("TTCN3_LICENSE_FILE environment variable is not set.\n", + stderr); + exit(EXIT_FAILURE); + } + load_license_from_file(lptr, file_name); +} + +void load_license_from_file(license_struct *lptr, const char *file_name) +{ + license_raw lraw; + read_license(file_name, &lraw); + check_license_signature(&lraw); + decode_license(lptr, &lraw); + lptr->license_file = mcopystr(file_name); +} + +void free_license(license_struct *lptr) +{ + Free(lptr->license_file); + lptr->license_file = NULL; + Free(lptr->licensee_name); + lptr->licensee_name = NULL; + Free(lptr->licensee_email); + lptr->licensee_email = NULL; + Free(lptr->licensee_company); + lptr->licensee_company = NULL; + Free(lptr->licensee_department); + lptr->licensee_department = NULL; + Free(lptr->login_name); + lptr->login_name = NULL; +} + +int verify_license(const license_struct *lptr) +{ + time_t current_time = time(NULL); + int errflag = 0; + + if (current_time < lptr->valid_from) { + fputs("The license key is not yet valid.\n", stderr); + errflag = 1; + } + + if (current_time > lptr->valid_until) { + fputs("The license key has already expired.\n", stderr); + errflag = 1; + } + + if (lptr->limitation_type & LIMIT_HOST) { + /* broken libc call gethostid() performs sign extension on some 64-bit + * Linux platforms, thus only the lowest 32 bits are considered */ + unsigned long host_id = (unsigned long)gethostid() & 0xffffffffUL; + if (host_id != lptr->host_id) { + fprintf(stderr, "The license key is not valid for this host " + "(%08lx).\n", host_id); + errflag = 1; + } + } + + if (lptr->limitation_type & LIMIT_USER) { +#ifdef MINGW + TCHAR user_name[UNLEN + 1]; + DWORD buffer_size = sizeof(user_name); + if (GetUserName(user_name, &buffer_size)) { + if (strcmp(user_name, lptr->login_name)) { + fprintf(stderr, "The license key is not valid for this user " + "name (%s).\n", user_name); + errflag = 1; + } + } else { + fprintf(stderr, "Getting the current user name failed when " + "verifying the license key. Windows error code: %d.\n", + (int)GetLastError()); + errflag = 1; + } +#else + uid_t process_uid = getuid(); + struct passwd *p; + setpwent(); + p = getpwuid(process_uid); + if (p == NULL) { + fprintf(stderr, "The current user ID (%d) does not have login " + "name.\n", (int)process_uid); + errflag = 1; + } else if (strcmp(p->pw_name, lptr->login_name)) { + /* First making a backup copy of the current login name because + * the subsequent getpwnam() call will overwrite it. */ + char *login_name = mcopystr(p->pw_name); + /* Another chance: Trying to map the login name of the license key + * to a valid UID. Note that it is possible to associate several + * login names with the same UID. */ + p = getpwnam(lptr->login_name); + if (p == NULL || p->pw_uid != process_uid) { + fprintf(stderr, "The license key is not valid for this login " + "name (%s).\n", login_name); + errflag = 1; + } + Free(login_name); + } + endpwent(); +#endif + } + + if (TTCN3_MAJOR < lptr->from_major || + (TTCN3_MAJOR == lptr->from_major && (TTCN3_MINOR < lptr->from_minor || + (TTCN3_MINOR == lptr->from_minor && + TTCN3_PATCHLEVEL < lptr->from_patchlevel)))) { + /* Checking of to_{major,minor,patchlevel} removed when Titan moved + * to major version 2 (licenses were valid up to 1.99pl99 only) */ + fputs("The license key is not valid for this version.\n", stderr); + errflag = 1; + } + + if (errflag) { + return 0; + } + + if (lptr->valid_until - current_time < EXPIRY_WARNING * 86400) { + time_t expiry_days = (lptr->valid_until - current_time) / 86400 + 1; + fprintf(stderr, "Warning: The license key will expire within %ld " + "day%s.\n", (long)expiry_days, expiry_days > 1 ? "s" : ""); + } + /* setpwent and getpwuid calls may use some system calls that fail. + * We should ignore these error codes in future error messages. */ + errno = 0; + return 1; +} + +unsigned int check_feature(const license_struct *lptr, unsigned int feature) +{ + return (lptr->feature_list & feature) != 0; +} + +void print_license(const license_struct *lptr) +{ + fprintf(stderr, + "---------------------------------------------------------------\n" + "License file : %s\n" + "Unique ID : %d\n" + "Licensee : %s\n" + "E-mail : %s\n" + "Company : %s\n" + "Department : %s\n" + "Valid from : %s", + lptr->license_file != NULL ? lptr->license_file : "", + lptr->unique_id, + lptr->licensee_name, + lptr->licensee_email, + lptr->licensee_company, + lptr->licensee_department, + ctime(&lptr->valid_from)); + + fprintf(stderr, + "Valid until : %s" + "Limitation :%s%s\n" + "Host ID : %08lx\n" + "Login name : %s\n" + "Versions : from %d.%d.pl%d until %d.%d.pl%d\n" + "Languages :%s%s\n" + "Encoders :%s%s%s%s%s\n" + "Applications :%s%s%s%s%s%s\n" + "Max PTCs : %d\n" + "---------------------------------------------------------------\n", + ctime(&lptr->valid_until), + lptr->limitation_type & LIMIT_HOST ? " HOST" : "", + lptr->limitation_type & LIMIT_USER ? " USER" : "", + lptr->host_id, + lptr->login_name, + lptr->from_major, lptr->from_minor, lptr->from_patchlevel, + lptr->to_major, lptr->to_minor, lptr->to_patchlevel, + lptr->feature_list & FEATURE_TTCN3 ? " TTCN3" : "", + lptr->feature_list & FEATURE_ASN1 ? " ASN1" : "", + lptr->feature_list & FEATURE_RAW ? " RAW" : "", + lptr->feature_list & FEATURE_TEXT ? " TEXT" : "", + lptr->feature_list & FEATURE_BER ? " BER" : "", + lptr->feature_list & FEATURE_PER ? " PER" : "", + lptr->feature_list & FEATURE_XER ? " XER" : "", + lptr->feature_list & FEATURE_CODEGEN ? " CODEGEN" : "", + lptr->feature_list & FEATURE_TPGEN ? " TPGEN" : "", + lptr->feature_list & FEATURE_SINGLE ? " SINGLE" : "", + lptr->feature_list & FEATURE_MCTR ? " MCTR" : "", + lptr->feature_list & FEATURE_HC ? " HC" : "", + lptr->feature_list & FEATURE_LOGFORMAT ? " LOGFORMAT" : "", + lptr->max_ptcs); +} + +void print_license_info() +{ + license_struct lstr; + int license_valid; + fputs("License information:\n", stderr); + init_openssl(); + load_license(&lstr); + print_license(&lstr); + license_valid = verify_license(&lstr); + free_license(&lstr); + free_openssl(); + + if (!license_valid) { + exit(EXIT_FAILURE); + } + + fputs("The license key is valid.\n", stderr); +} + +void init_openssl() +{ + if (!RAND_status()) { + time_t time_sec = time(NULL); + if (time_sec == (time_t)-1) { + perror("time() system call failed"); + exit(EXIT_FAILURE); + } + RAND_seed(&time_sec, sizeof(time_sec)); + } + while (!RAND_status()) { +#ifdef MINGW + FILETIME filetime; + GetSystemTimeAsFileTime(&filetime); + RAND_seed(&filetime.dwLowDateTime, sizeof(filetime.dwLowDateTime)); +#else + struct timeval tv; + if (gettimeofday(&tv, NULL) == -1) { + perror("gettimeofday() system call failed"); + exit(EXIT_FAILURE); + } + RAND_seed(&tv.tv_usec, sizeof(tv.tv_usec)); +#endif + } + ERR_load_crypto_strings(); + /* Random seeding in OpenSSL may use some system calls that fail. + * We should ignore these error codes in future error messages. */ + errno = 0; +} + +void free_openssl() +{ + RAND_cleanup(); + ERR_free_strings(); +} + +const char * openssl_version_str(void) { + return SSLeay_version(SSLEAY_VERSION); +} + +#if defined(WIN32) || defined(INTERIX) + +#ifdef INTERIX +#define INTERIX_PREFIX "\\Registry\\Machine\\" +#else +#define INTERIX_PREFIX +#endif + +static const char * const keys[] = { + INTERIX_PREFIX "Software\\Microsoft\\Windows\\CurrentVersion\\", + INTERIX_PREFIX "Software\\Microsoft\\Windows NT\\CurrentVersion\\", + NULL +}; + +static const char * const values[] = { +/* Product specific info */ + "ProductName", + "Version", + "CurrentVersion", + "VersionNumber", + "CurrentBuildNumber", +/* Unique identifiers */ + "ProductKey", + "ProductId", + "DigitalProductId", +/* User specific info */ + "RegisteredOwner", + "RegisteredOrganization", +/* Installation specific info */ + "InstallDate", + "FirstInstallDateTime", + "SystemRoot", + NULL +}; +#endif + +#ifdef WIN32 + +long gethostid(void) +{ + const char * const *subKey; + MD5_CTX context; + unsigned char digest[MD5_DIGEST_LENGTH]; + long hostid = 0; + unsigned int i; + + MD5_Init(&context); + + for (subKey = keys; *subKey != NULL; subKey++) { + HKEY hKey; + const char * const *valueName; + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, *subKey, + 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) + continue; + + for (valueName = values; *valueName != NULL; valueName++) { + DWORD length = 0; + unsigned char *buffer; + + if (RegQueryValueEx(hKey, *valueName, NULL, NULL, NULL, &length) + != ERROR_SUCCESS) continue; + buffer = (unsigned char*)Malloc(length); + if (RegQueryValueEx(hKey, *valueName, NULL, NULL, buffer, &length) + == ERROR_SUCCESS) { + MD5_Update(&context, buffer, length); + } + Free(buffer); + } + RegCloseKey(hKey); + } + MD5_Final(digest, &context); + for (i = 0; i < sizeof(hostid); i++) hostid |= digest[i] << i * 8; + return hostid; +} + +#endif + +#ifdef INTERIX + +long gethostid(void) +{ + long hostid = 0; + const char * const *subKey; + size_t i; + MD5_CTX context; + unsigned char digest[MD5_DIGEST_LENGTH]; + + MD5_Init(&context); + + for (subKey = keys; *subKey != NULL; subKey++) { + const char * const *valueName; + for (valueName = values; *valueName != NULL; valueName++) { + int ret = -13, type = -42; + size_t size = 0; + unsigned char *buffer; + char * key = mcopystr(*subKey); + key = mputstr(key, *valueName); + + ret = getreg(key, &type, 0, &size); /* query the size; ret always -1 */ + if (size > 0) { + buffer = Malloc(size); + ret = getreg(key, &type, buffer, &size); + if (ret == 0) { + switch (type) { + case WIN_REG_SZ: + case WIN_REG_EXPAND_SZ: + case WIN_REG_MULTI_SZ: { + /* getreg gave use _wide_ strings. Make them narrow. + FIXME this assumes everybody is american and uses US-ASCII. + It would be more correct to use iconv() + but we don't know which codepage to convert to. + */ + const unsigned char *from = buffer, *end = buffer + size; + unsigned char *to = buffer; + for (; from < end; ++from) { /* Yes, from is incremented twice */ + *to++ = *from++; + } + size /= 2; + break; } + default: + break; + } + MD5_Update(&context, buffer, size); + } + Free(buffer); + } + Free(key); + } + } + + MD5_Final(digest, &context); + for (i = 0; i < sizeof(hostid); i++) hostid |= digest[i] << (i * 8); + return hostid; +} + +#endif diff --git a/common/license.h b/common/license.h new file mode 100644 index 0000000..560d1a0 --- /dev/null +++ b/common/license.h @@ -0,0 +1,155 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef LICENSE_H +#define LICENSE_H + +#include + +/* Initial features */ +#define FEATURE_TTCN3 0x1u +#define FEATURE_CODEGEN 0x2u +#define FEATURE_TPGEN 0x4u +#define FEATURE_SINGLE 0x8u +#define FEATURE_MCTR 0x10u +#define FEATURE_HC 0x20u +#define FEATURE_LOGFORMAT 0x40u +/* Added in 1.2.pl0 */ +#define FEATURE_ASN1 0x80u +#define FEATURE_RAW 0x100u +#define FEATURE_BER 0x200u +#define FEATURE_PER 0x400u +/* Added in 1.5.pl7 */ +#define FEATURE_GUI 0x800u // deprecated mctr GUI was removed +/* Added in 1.5.pl8 */ +#define FEATURE_TEXT 0x1000u +/* Added in 1.8.pl0 */ +#define FEATURE_XER 0x2000u + +/* Limitation types */ +#define LIMIT_HOST 0x1 +#define LIMIT_USER 0x2 + +/* Limit for expiration warning in days */ +#define EXPIRY_WARNING 14 + +/* Where to send the license. + * + * The values 1,2,3 work as either an enumeration or a bit field. */ +#define SENDTO_LICENSEE 1 +#define SENDTO_CONTACT 2 +#define SENDTO_BOTH 3 + +/** "Cooked" license information suitable for processing. */ +typedef struct { + char *license_file; + unsigned int unique_id; + char *licensee_name, *licensee_email, + *licensee_company, *licensee_department; + char *contact_name, *contact_email; + unsigned int send_to; + time_t valid_from, valid_until; + unsigned long int host_id; + char *login_name; + unsigned int from_major, from_minor, from_patchlevel, + to_major, to_minor, to_patchlevel; + unsigned int feature_list, limitation_type; + unsigned int max_ptcs; +} license_struct; + +/** Raw license information. + * + * The license file is a Base64-encode of a BER-encoded version of this structure. + * + * @note Modifying this structure will render it incompatible with + * previous versions of Titan (the size of the structure is checked) */ +typedef struct { + unsigned char unique_id[4]; + char licensee_name[48], licensee_email[48], + licensee_company[48], licensee_department[16]; + unsigned char valid_from[4], valid_until[4]; + unsigned char host_id[4]; + char login_name[8]; + unsigned char from_major[4], from_minor[4], from_patchlevel[4], + to_major[4], to_minor[4], to_patchlevel[4]; + unsigned char feature_list[4], limitation_type[4]; + unsigned char max_ptcs[4]; + unsigned char dsa_signature[48]; +} license_raw; + +#ifdef __cplusplus +extern "C" { +#endif + +/** Load license information. + * + * Loads license information from the file specified in the + * \c TTCN3_LICENSE_FILE environment variable. + * + * Calls \c load_license_from_file() + * + * @param [out] lptr pointer to license data */ +void load_license(license_struct *lptr); + +/** Load license information from a specified file. + * @param [out] lptr pointer to license data + * @param [in] file_name string containing the license file name */ +void load_license_from_file(license_struct *lptr, const char *file_name); + +/** Free resources + * @param [in] lptr pointer to license data */ +void free_license(license_struct *lptr); + +/** Check if the license allows the use of the product. + * + * Verifies that we are within the license period, that the host or user + * restriction is satisfied, and the program version is within the limits + * allowed by the license. + * + * If the license is about to expire in less than \c EXPIRY_WARNING days, + * a warning is printed. + * + * If a check fails, function returns 0. + * + * @param [in] lptr pointer to license information + * @return 1 if the license is valid, 0 if invalid. */ +int verify_license(const license_struct *lptr); + +/** Check if the license allows the use of a certain feature. + * + * @param lptr pointer to license information + * @param feature feature to check. It should be one of the FEATURE_ macros. + * @return nonzero if feature is enabled, 0 if disabled. */ +unsigned int check_feature(const license_struct *lptr, unsigned int feature); + +/** Print the details of the supplied license information + * + * @param [in] lptr pointer to license information */ +void print_license(const license_struct *lptr); + +/** Print information about the license used by the program. + * + * The license is loaded from the file specified by the \c TTCN3_LICENSE_FILE + * environment variable. + * + * This function terminates the program if the license is not valid. */ +void print_license_info(void); + +void init_openssl(void); +void free_openssl(void); + +const char * openssl_version_str(void); + +#if defined(WIN32) || defined(INTERIX) +long gethostid(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/common/memory.c b/common/memory.c new file mode 100644 index 0000000..11ceec8 --- /dev/null +++ b/common/memory.c @@ -0,0 +1,929 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "memory.h" + +#undef Malloc +#undef Realloc +#undef Free +#undef mprintf +#undef mprintf_va_list +#undef mputprintf +#undef mputprintf_va_list +#undef memptystr +#undef mcopystr +#undef mcopystrn +#undef mputstr +#undef mputc + + +#include +#include +#include +#include +#include +#include +#include + +/** @def va_copy + * work-around for missing va_copy() in GCC + */ +#if defined(__GNUC__) && !defined(va_copy) +# ifdef __va_copy +# define va_copy(dest, src) __va_copy(dest, src) +# else +# define va_copy(dest, src) (dest) = (src) +# endif +#endif + +/** Initial buffer size for mprintf */ +#define BUFSIZE 1024 + +/** @def MEMORY_DEBUG_ADDRESS + * + * If you want to catch memory management functions (malloc, realloc, + * free) which operate on a given address, define this macro and set + * memory_debug_address to the address you want to monitor. + * + * @note This macro has no effect if \c MEMORY_DEBUG is not defined + */ +#ifdef DOXYGEN_SPECIAL +/* Make the macro visible to Doxygen */ +#define MEMORY_DEBUG_ADDRESS +#endif + +#ifdef MEMORY_DEBUG_ADDRESS +/** @brief Memory checkpoint address. */ +void *memory_debug_address = NULL; + +/** @brief Memory checkpoint ordinal. */ +size_t memory_debug_ordinal = (size_t)-1; +#endif + +/** + * @name Number of memory allocations and frees performed. + * @{ + * @note These are tracked even without MEMORY_DEBUG. + */ +static size_t malloc_count = 0, free_count = 0; +/** @} */ + +/** + * If preprocessor symbol \c MEMORY_DEBUG is defined the memory + * management routines do some self-checks against improper use. This + * implies extra memory usage and significant performance penalty. + */ +#ifdef MEMORY_DEBUG + +#define FILENAME_FORMAT "%s:%d: " + +/* Currently allocated memory amount, peak, and number of allocations */ +static size_t allocated_size = 0, peak_size = 0; +static unsigned int alloc_count = 0; +/* Sum of all the allocated amounts */ +static unsigned long long total_allocated = 0; + +typedef struct memory_block_struct { + size_t size; + struct memory_block_struct *prev, *next; + const char *filename; /* pointer to string literal */ + int lineno; + unsigned int ordinal; /* The ordinal which uniquely identifies this allocation */ + void *magic; /* only to reserve some place for the magic guard */ + double begin; /* beginning of useful memory with proper alignment */ +} memory_block; + +static memory_block *list_head = NULL, *list_tail = NULL; + +static void add_to_list(memory_block *block_ptr) +{ + block_ptr->prev = list_tail; + block_ptr->next = NULL; + if (list_tail != NULL) list_tail->next = block_ptr; + else list_head = block_ptr; + list_tail = block_ptr; +} + +static void remove_from_list(memory_block *block_ptr) +{ + if (block_ptr->prev != NULL) + block_ptr->prev->next = block_ptr->next; + else list_head = block_ptr->next; + if (block_ptr->next != NULL) + block_ptr->next->prev = block_ptr->prev; + else list_tail = block_ptr->prev; +} + +/* Layout of memory (allocated in one chunk) + * +----------+ <--- block_ptr + * | size | + * +----------+ + * | prev | + * +----------+ + * | next | + * +----------+ + * | filename | + * +----------+ + * | ordinal | + * +----------+ + * | magic | + * +----------+ +-----------+ + * | begin | | user data | + * +----------+ | | + * ........... + * | | + * +-----------+ +-----------+ + * | end magic | + * +-----------+ + * + * + * The magic values initially contain the value of block_ptr. + * When the block is freed, a bit-flipped value is written instead. + * During realloc and free, the magic values are checked to match block_ptr. + * If they don't, the a memory overrun or underrun has occurred + * (except if the magic value happens to match the bit-flipped block_ptr, + * in which case it's likely a double-free). + */ + +static void set_magic_values(memory_block *block_ptr) +{ + unsigned char *ptr = (unsigned char*)&block_ptr->begin; + memcpy(&block_ptr->magic, &block_ptr, sizeof(block_ptr)); + memcpy(ptr + block_ptr->size, &block_ptr, sizeof(block_ptr)); +} + +static void check_magic_values(const char *filename, int line, + memory_block *block_ptr, int is_realloc) +{ + void *inv_ptr = (void*)(~(size_t)block_ptr); + unsigned char *ptr = (unsigned char*)&block_ptr->begin; + /* compare the magic */ + if (memcmp(&block_ptr->magic, &block_ptr, sizeof(block_ptr))) { + /* mismatch! */ + const char *err_str; + if (memcmp(&block_ptr->magic, &inv_ptr, sizeof(inv_ptr))) + err_str = "memory corruption"; + else err_str = "duplicate free/realloc"; + if (filename) { + fprintf(stderr, FILENAME_FORMAT, filename, line); + } + fprintf(stderr, "Fatal error: %s detected at block begin when %s " + "pointer %p.\n", err_str, is_realloc ? "reallocating" : "freeing", + ptr); + if (block_ptr->filename) fprintf(stderr, + FILENAME_FORMAT "Last freed here.\n", block_ptr->filename, block_ptr->lineno); + abort(); + } + memcpy(&block_ptr->magic, &inv_ptr, sizeof(inv_ptr));/*invert magic*/ + if (memcmp(ptr + block_ptr->size, &block_ptr, sizeof(block_ptr))) { + if (filename) { + fprintf(stderr, FILENAME_FORMAT, filename, line); + } + fprintf(stderr, "Fatal error: memory corruption detected " + "at block end when %s pointer %p.\n", + is_realloc ? "reallocating" : "freeing", ptr); + if (block_ptr->filename) fprintf(stderr, + FILENAME_FORMAT "Last freed here.\n", block_ptr->filename, block_ptr->lineno); + abort(); + } + memcpy(ptr + block_ptr->size, &inv_ptr, sizeof(inv_ptr)); + block_ptr->filename = filename; + block_ptr->lineno = line; +} + +/** @def MEMORY_DEBUG_FREE + * @brief Enable checking for uses of unallocated/deallocated memory areas. + * + * If preprocessor symbol \c MEMORY_DEBUG_FREE is defined the memory + * management routines can verify that unused and deallocated memory areas + * are not written accidentally by the program after calling \a Free(). + * This verification can be done using functions \a check_mem_leak() or + * \a check_mem_corrupt(). + * + * Note: This functionality can significantly increase the memory requirements + * of the program since the deallocated blocks cannot be recycled. They are + * not returned to the system using \a free() until the end of the program run. + */ +#ifdef DOXYGEN_SPECIAL +/* Make the macro visible to Doxygen */ +#define MEMORY_DEBUG_FREE +#endif + +#ifdef MEMORY_DEBUG_FREE + +static memory_block *free_list_head = NULL, *free_list_tail = NULL; + +static void add_to_free_list(memory_block *block_ptr) +{ + block_ptr->prev = free_list_tail; + block_ptr->next = NULL; + if (free_list_tail != NULL) free_list_tail->next = block_ptr; + else free_list_head = block_ptr; + free_list_tail = block_ptr; +} + +static void check_free_list(void) +{ + memory_block *block_ptr = free_list_head; + size_t counter = 0; + while (block_ptr != NULL) { + void *inv_ptr = (void*)(~(size_t)block_ptr); + unsigned char *ptr = (unsigned char*)&block_ptr->begin; + size_t i; + if (memcmp(&block_ptr->magic, &inv_ptr, sizeof(inv_ptr))) { + fprintf(stderr, "Fatal error: memory corruption detected in front " + "of freed pointer %p\n", ptr); + abort(); + } + for (i = 0; i < block_ptr->size; i++) { + if (ptr[i] != 0xAA) { + fprintf(stderr, "Fatal error: memory overwriting detected in " + "deallocated area: base pointer: %p, offset: %u, data " + "written: %02X\n", ptr, i, ptr[i]); + abort(); + } + } + if (memcmp(ptr + block_ptr->size, &inv_ptr, sizeof(inv_ptr))) { + fprintf(stderr, "Fatal error: memory corruption detected at the " + "end of freed pointer %p\n", ptr); + abort(); + } + block_ptr = block_ptr->next; + counter++; + } + fprintf(stderr, "%u deallocated memory block%s OK\n", counter, + counter > 1 ? "s are" : " is"); +} + +static void release_free_blocks(void) +{ + memory_block *block_ptr = free_list_head; + while (block_ptr != NULL) { + memory_block *next_ptr = block_ptr->next; + free(block_ptr); + block_ptr = next_ptr; + } + free_list_head = NULL; + free_list_tail = NULL; +} +#endif +/* MEMORY_DEBUG_FREE */ + +#ifdef MEMORY_DEBUG_ADDRESS +/** Check the address and the ordinal of the allocation against the checkpoints + * + * If the address or the ordinal matches, a line is printed to the standard + * error. Breakpoints can be set on the printf to trigger when the watched + * allocation happens. + * + * @param block_ptr pointer to a memory block structure which is being + * allocated/reallocated/freed + * @param oper the actual operation: 0=Malloc, 1=Realloc, 2=Free + */ +static void check_memory_address(memory_block *block_ptr, int oper) +{ + void *ptr = (unsigned char*)&block_ptr->begin; + if (ptr == memory_debug_address) + { + if (block_ptr->filename) { + fprintf(stderr, FILENAME_FORMAT, block_ptr->filename, block_ptr->lineno); + } + fprintf(stderr, "MEMDEBUG: returning pointer %p while %sing memory.\n", + ptr, oper==0?"allocat":oper==1?"reallocat":"free"); + } + if (block_ptr->ordinal == memory_debug_ordinal) { + if (block_ptr->filename) { + fprintf(stderr, FILENAME_FORMAT, block_ptr->filename, block_ptr->lineno); + } + fprintf(stderr, "MEMDEBUG: returning ordinal %lu while %sing memory.\n", + (unsigned long)block_ptr->ordinal, + oper==0 ? "allocat" : (oper==1 ? "reallocat" : "free")); + } +} +#endif +/* MEMORY_DEBUG_ADDRESS */ + +/*#define FATAL_ERROR_INTERNAL(f,l,s) fatal_error(f,l,s)*/ +#define MALLOC_INTERNAL(f,l,s) Malloc_dbg(f,l,s) +#define MEMPTYSTR_INTERNAL(f,l) memptystr_dbg(f,l) +#define MCOPYSTR_INTERNAL(f,l,s) mcopystr_dbg(f,l,s) +#define REALLOC_INTERNAL(f,l,p,s) Realloc_dbg(f,l,p,s) +#define FREE_INTERNAL(f,l,p) Free_dbg(f,l,p) +#define MPRINTF_VA_LIST_INTERNAL(f,l,s,p) mprintf_va_list_dbg(f,l,s,p) + +static const size_t offset = (unsigned char*)&(((memory_block*)NULL)->begin) + - (unsigned char*)NULL; + +static void extract_location(void *p, const char **fn, int *ln) +{ + memory_block *block_ptr = NULL; + block_ptr = (memory_block*)(void*)((unsigned char*)p - offset); + *fn = block_ptr->filename; + *ln = block_ptr->lineno; +} + +#else +/* not MEMORY_DEBUG */ + +#define FATAL_ERROR_INTERNAL(f,l,s) fatal_error(s) +#define MALLOC_INTERNAL(f,l,s) Malloc(s) +#define MEMPTYSTR_INTERNAL(f,l) memptystr() +#define MCOPYSTR_INTERNAL(f,l,s) mcopystr(s) +#define REALLOC_INTERNAL(f,l,p,s) Realloc(p,s) +#define FREE_INTERNAL(f,l,p) Free(p) +#define MPRINTF_VA_LIST_INTERNAL(f,l,s,p) mprintf_va_list(s,p) + +#define extract_location(p,f,l) ((void)p,(void)f,(void)l) +#endif + +/** Report a fatal error. + * + * @param size the number of bytes that could not be allocated + * + * This function does not return. + */ +__attribute__ ((__noreturn__)) +static void fatal_error( +#ifdef MEMORY_DEBUG + const char *filename, int line, +#endif + size_t size) +{ + const char *err_msg = strerror(errno); +#ifdef MEMORY_DEBUG + fprintf(stderr, FILENAME_FORMAT "Fatal error: cannot allocate %lu bytes" + " of memory after allocating %lu bytes: ", filename, line, + (unsigned long) size, (unsigned long) allocated_size); +#else + fprintf(stderr, "Fatal error: cannot allocate %lu bytes of memory: ", + (unsigned long) size); +#endif + if (err_msg != NULL) fprintf(stderr, "%s. Exiting.\n", err_msg); + else fprintf(stderr, "Unknown error (errno: %d). Exiting.\n", errno); + exit(EXIT_FAILURE); +} + +#ifdef MEMORY_DEBUG +void *Malloc(size_t size) +{ + return Malloc_dbg(0,0,size); +} + +void *Malloc_dbg(const char *filename, int line, size_t size) +#else +void *Malloc(size_t size) +#endif +{ + if (size > 0) { + void *ptr; +#ifdef MEMORY_DEBUG + memory_block *block_ptr; + block_ptr = (memory_block*)malloc(sizeof(*block_ptr) - + sizeof(block_ptr->begin) + size + sizeof(block_ptr)); + if (block_ptr == NULL) fatal_error(filename, line, size); + block_ptr->filename = filename; + block_ptr->lineno = line; + block_ptr->size = size; + add_to_list(block_ptr); + set_magic_values(block_ptr); + ptr = &block_ptr->begin; + total_allocated += size; + block_ptr->ordinal = alloc_count++; + allocated_size += size; +#ifdef MEMORY_DEBUG_ADDRESS + check_memory_address(block_ptr, 0); +#endif + if (peak_size < allocated_size) peak_size = allocated_size; +#else + ptr = malloc(size); + if (ptr == NULL) fatal_error(size); +#endif + malloc_count++; + return ptr; + } else return NULL; +} + +#ifdef MEMORY_DEBUG + +void *Realloc(void *ptr, size_t size) +{ + return Realloc_dbg(0,0,ptr,size); +} + +void *Realloc_dbg(const char *filename, int line, void *ptr, size_t size) +#else +void *Realloc(void *ptr, size_t size) +#endif +{ + if (ptr == NULL) return MALLOC_INTERNAL(filename, line, size); + else if (size == 0) { + FREE_INTERNAL(filename, line, ptr); + return NULL; + } else { + void *new_ptr; +#ifdef MEMORY_DEBUG + memory_block *block_ptr = NULL; + block_ptr = (memory_block*)(void*)((unsigned char*)ptr - offset); + check_magic_values(filename, line, block_ptr, 1); + remove_from_list(block_ptr); + allocated_size -= block_ptr->size; + if (size < block_ptr->size) + memset((unsigned char*)ptr + size, 0x55, block_ptr->size - size); + block_ptr = (memory_block*)realloc(block_ptr, sizeof(*block_ptr) - + sizeof(block_ptr->begin) + sizeof(block_ptr) + size); + if (block_ptr == NULL) fatal_error(filename, line, size); +#ifdef MEMORY_DEBUG_ADDRESS + check_memory_address(block_ptr, 1); +#endif + block_ptr->filename = filename; + block_ptr->lineno = line; + block_ptr->size = size; + add_to_list(block_ptr); + set_magic_values(block_ptr); + new_ptr = &block_ptr->begin; + total_allocated += size; + alloc_count++; + allocated_size += size; + if (peak_size < allocated_size) peak_size = allocated_size; +#else + new_ptr = realloc(ptr, size); + if (new_ptr == NULL) FATAL_ERROR_INTERNAL(filename, line, size); +#endif + return new_ptr; + } +} + +#ifdef MEMORY_DEBUG +void Free(void *ptr) +{ + Free_dbg(0,0,ptr); +} + +extern void Free_dbg(const char *filename, int line, void *ptr) +#else +void Free(void *ptr) +#endif +{ + if (ptr != NULL) { +#ifdef MEMORY_DEBUG + memory_block *block_ptr = NULL; + block_ptr = (memory_block*)(void*)((unsigned char*)ptr - offset); +#ifdef MEMORY_DEBUG_ADDRESS + check_memory_address(block_ptr, 2); +#endif + check_magic_values(filename, line, block_ptr, 0); + remove_from_list(block_ptr); + allocated_size -= block_ptr->size; + memset(ptr, 0xAA, block_ptr->size); +#ifdef MEMORY_DEBUG_FREE + add_to_free_list(block_ptr); +#else + free(block_ptr); +#endif +#else + free(ptr); +#endif + free_count++; + } +} + +static const size_t maxprint = 32; + +void check_mem_leak(const char *program_name) +{ +#ifdef MEMORY_DEBUG + fprintf(stderr, "%s(%d): memory usage statistics:\n" + "total allocations: %lu\n" + "malloc/new calls: %lu\n" + "free/delete calls: %lu\n" + "peak memory usage: %lu bytes\n" + "average block size: %g bytes\n", + program_name, (int)getpid(), + (unsigned long)alloc_count, (unsigned long)malloc_count, + (unsigned long) free_count, (unsigned long) peak_size, + (double)total_allocated / (double)alloc_count); + if (list_head != NULL) { + memory_block *block_ptr = list_head; + size_t counter = 0; + fprintf(stderr, "unallocated blocks:\n"); + do { + if (block_ptr->filename != 0) { + fprintf(stderr, FILENAME_FORMAT, + block_ptr->filename, block_ptr->lineno); + } + fprintf(stderr, "\tMemory leak at %p, size %lu, ord %lu: ", + (void*)&block_ptr->begin, (unsigned long)block_ptr->size, + (unsigned long)block_ptr->ordinal); + { + const unsigned char * mm = (const unsigned char*)&block_ptr->begin; + size_t x, limit = (block_ptr->size > maxprint) ? maxprint + : block_ptr->size; + for (x = 0; x < limit; ++x) { + fputc( isprint(mm[x]) ? mm[x] : '.', stderr ); + } + fputc(10, stderr); + } + block_ptr = block_ptr->next; + counter++; + } while (block_ptr != NULL); + fprintf(stderr, "total unallocated: %lu bytes in %lu blocks\n", + (unsigned long) allocated_size, (unsigned long) counter); + } +#ifdef MEMORY_DEBUG_FREE + check_free_list(); + release_free_blocks(); +#endif +#else + if (malloc_count != free_count) { + fprintf(stderr, "%s: warning: memory leakage detected.\n" + "Total malloc calls: %lu, free calls: %lu\n" + "Please submit a bug report including the current input file(s).\n", + program_name, + (unsigned long) malloc_count, (unsigned long) free_count); + } +#endif +} + +#ifdef MEMORY_DEBUG +void check_mem_corrupt(const char *program_name) +{ + size_t counter = 0; + memory_block *block_ptr; + fprintf(stderr, "%s: checking memory blocks for corruption\n", + program_name); + for (block_ptr = list_head; block_ptr != NULL; block_ptr = block_ptr->next) + { + unsigned char *ptr = (unsigned char*)&block_ptr->begin; + if (memcmp(ptr - sizeof(block_ptr), &block_ptr, sizeof(block_ptr))) { + fprintf(stderr, "Fatal error: memory corruption detected in front " + "of pointer %p\n", ptr); + abort(); + } + if (memcmp(ptr + block_ptr->size, &block_ptr, sizeof(block_ptr))) { + fprintf(stderr, "Fatal error: memory corruption detected at the " + "end of pointer %p\n", ptr); + abort(); + } + counter++; + } + fprintf(stderr, "%s: %lu memory block%s OK\n", program_name, + (unsigned long) counter, counter > 1 ? "s are" : " is"); +#ifdef MEMORY_DEBUG_FREE + check_free_list(); +#endif +} +#endif + +/** @brief Find the string length of an expstring_t + +Finds the length of the C string pointed at by \p str, using some assumptions +satisfied by an expstring_t. + +@pre There is an offset from the beginning of the string which is a power + of two, is within the buffer allocated for \p str and it contains '\\0' +@pre The allocated buffer is at most twice as long as strlen(str) +@pre \p bufsize is a valid pointer + +@param [in] str an expstring_t, must not be null +@param [out] bufsize pointer to a location where the minimum buffer size + (always a power of two) is deposited. +@return the length of \p str as a C string +*/ +static size_t fast_strlen(const expstring_t str, size_t *bufsize) +{ + size_t size, min, max; + /* Find the 0 byte at the end of the allocated buffer */ + for (size = 1; str[size - 1] != '\0'; size *= 2) {} + *bufsize = size; + if (size == 1) return 0; + /* Binary search the second half of the buffer */ + min = size / 2 - 1; + max = size - 1; + while (max - min > 1) { + size_t med = (min + max) / 2; + if (str[med] != '\0') min = med; + else max = med; + } + return max; +} + +/** @brief Find the first power of two which is greater than \p len + * + * @param len the desired length + * @return a power of 2 greater than \p len + * + * \p len is taken to be the number of characters needed. The returned value + * will always be greater than \p len to accommodate the null terminator. + */ +static size_t roundup_size(size_t len) +{ + size_t size; + for (size = 1; len >= size; size *= 2); + return size; +} + +#ifdef MEMORY_DEBUG +expstring_t mprintf_va_list(const char *fmt, va_list pvar) +{ + return mprintf_va_list_dbg(0,0,fmt,pvar); +} + +expstring_t mprintf_va_list_dbg(const char *filename, int line, const char *fmt, va_list pvar) +#else +expstring_t mprintf_va_list(const char *fmt, va_list pvar) +#endif +{ + char buf[BUFSIZE]; + expstring_t ptr; + int len; + size_t size, slen; + va_list pvar2; + va_copy(pvar2, pvar); + len = vsnprintf(buf, BUFSIZE, fmt, pvar2); + va_end(pvar2); + if (len < 0) { + /* The result does not fit in buf and we have no idea how many bytes + * are needed (only old versions of libc may return -1). + * Try to double the buffer size until it is large enough. */ + for (size = 2 * BUFSIZE; ; size *= 2) { + ptr = (expstring_t)MALLOC_INTERNAL(filename, line, size); + va_copy(pvar2, pvar); + len = vsnprintf(ptr, size, fmt, pvar2); + va_end(pvar2); + if (len >= 0 && (size_t)len < size) break; + FREE_INTERNAL(filename, line, ptr); + } + slen = (size_t)len; + } else if (len >= BUFSIZE) { + /* The result does not fit in buf, but we know how many bytes we need. + * Allocate a buffer that is large enough and repeat vsnprintf() */ + slen = (size_t)len; + size = roundup_size(slen); + ptr = (expstring_t)MALLOC_INTERNAL(filename, line, size); + /* use the original pvar since this is the last try */ + if (vsnprintf(ptr, size, fmt, pvar) != len) { + perror("Fatal error: unexpected vsnprintf() return value"); + exit(EXIT_FAILURE); + } + } else { + /* the complete result is in buf */ + slen = (size_t)len; + size = roundup_size(slen); + ptr = (expstring_t)MALLOC_INTERNAL(filename, line, size); + memcpy(ptr, buf, slen); + } + memset(ptr + slen, '\0', size - slen); + return ptr; +} + +#ifdef MEMORY_DEBUG +expstring_t mprintf_dbg(const char *filename, int line, const char *fmt, ...) +{ + expstring_t ptr; + va_list pvar; + va_start(pvar, fmt); + ptr = mprintf_va_list_dbg(filename, line, fmt, pvar); + va_end(pvar); + return ptr; +} +#endif + +expstring_t mprintf(const char *fmt, ...) +{ + expstring_t ptr; + va_list pvar; + va_start(pvar, fmt); + ptr = mprintf_va_list(fmt, pvar); + va_end(pvar); + return ptr; +} + +/* Tracking the origin: extracts the filename/line from the original allocation + * of the expstring_t. */ +expstring_t mputprintf_va_list(expstring_t str, const char *fmt, va_list pvar) +{ + const char *filename = NULL; + int line = 0; + if (str != NULL) { + size_t size; + size_t len = fast_strlen(str, &size); + size_t rest = size - len; + int len2; + va_list pvar2; + /* make a copy of pvar to allow re-use later */ + va_copy(pvar2, pvar); + len2 = vsnprintf(str + len, rest, fmt, pvar2); + va_end(pvar2); + extract_location(str, &filename, &line); + if (len2 < 0) { + /* the result does not fit in buf and we have no idea how many + * bytes are needed (only old versions of libc may return -1) + * try to double the buffer size until it is large enough */ + size_t newlen; + do { + size *= 2; + str = (expstring_t)REALLOC_INTERNAL(filename, line, str, size); + rest = size - len; + va_copy(pvar2, pvar); + len2 = vsnprintf(str + len, rest, fmt, pvar2); + va_end(pvar2); + } while (len2 < 0 || (size_t)len2 >= rest); + newlen = len + (size_t)len2; + memset(str + newlen, '\0', size - newlen); + } else if ((size_t)len2 >= rest) { + /* there isn't enough space in buffer, but we know how many bytes + * we need: reallocate the buffer to be large enough and repeat + * vsnprintf() */ + size_t newlen = len + (size_t)len2; + size = roundup_size(newlen); + str = (expstring_t)REALLOC_INTERNAL(filename, line, str, size); + /* use the original pvar since this is the last try */ + if (vsnprintf(str + len, size - len, fmt, pvar) != len2) { + perror("Fatal error: unexpected vsnprintf() return value"); + exit(EXIT_FAILURE); + } + memset(str + newlen, '\0', size - newlen); + } + } else str = MPRINTF_VA_LIST_INTERNAL(filename, line, fmt, pvar); + return str; +} + +expstring_t mputprintf(expstring_t str, const char *fmt, ...) +{ + va_list pvar; + va_start(pvar, fmt); + str = mputprintf_va_list(str, fmt, pvar); + va_end(pvar); + return str; +} + +#ifdef MEMORY_DEBUG +expstring_t memptystr(void) +{ + return memptystr_dbg(0,0); +} + +expstring_t memptystr_dbg(const char *filename, int line) +#else +expstring_t memptystr(void) +#endif +{ + expstring_t ptr = (expstring_t)MALLOC_INTERNAL(filename, line, 1); + ptr[0] = '\0'; + return ptr; +} + +#ifdef MEMORY_DEBUG +expstring_t mcopystr(const char *str) +{ + return mcopystr_dbg(0,0,str); +} + +expstring_t mcopystr_dbg(const char *filename, int line, const char *str) +#else +expstring_t mcopystr(const char *str) +#endif +{ + if (str != NULL) { + size_t len = strlen(str); + size_t size = roundup_size(len); + expstring_t ptr = (expstring_t)MALLOC_INTERNAL(filename, line, size); + memcpy(ptr, str, len); + memset(ptr + len, '\0', size - len); + return ptr; + } else return MEMPTYSTR_INTERNAL(filename, line); +} + +#ifdef MEMORY_DEBUG +expstring_t mcopystrn(const char *str, size_t len) +{ + return mcopystrn_dbg(0,0,str, len); +} + +expstring_t mcopystrn_dbg(const char *filename, int line, const char *str, + size_t len) +#else +expstring_t mcopystrn(const char *str, size_t len) +#endif +{ + if (len != 0 && str != NULL) { + size_t size = roundup_size(len); + expstring_t ptr = (expstring_t)MALLOC_INTERNAL(filename, line, size); + memcpy(ptr, str, len); + memset(ptr + len, '\0', size - len); + return ptr; + } else return MEMPTYSTR_INTERNAL(filename, line); +} + +/* Tracking the origin: extracts the filename/line from the original allocation + * of the expstring_t. */ +expstring_t mputstr(expstring_t str, const char *str2) +{ + const char *filename = NULL; + int line = 0; + if (str2 != NULL) { + if (str != NULL) { + size_t size; + size_t len = fast_strlen(str, &size); + size_t len2 = strlen(str2); + size_t newlen = len + len2; + if (size <= newlen) { + size_t newsize = roundup_size(newlen); + extract_location(str, &filename, &line); + str = (expstring_t)REALLOC_INTERNAL(filename, line, str, newsize); + memset(str + newlen, '\0', newsize - newlen); + } + memcpy(str + len, str2, len2); + } else str = MCOPYSTR_INTERNAL(filename, line, str2); + } + return str; +} + +/* Tracking the origin: extracts the filename/line from the original allocation + * of the expstring_t. */ +expstring_t mputstrn(expstring_t str, const char *str2, size_t len2) +{ + const char *filename = NULL; + int line = 0; + if (len2 != 0 && str2 != NULL) { + if (str != NULL) { + size_t size; + size_t len = fast_strlen(str, &size); + size_t newlen = len + len2; + if (size <= newlen) { + size_t newsize = roundup_size(newlen); + extract_location(str, &filename, &line); + str = (expstring_t)REALLOC_INTERNAL(filename, line, str, newsize); + memset(str + newlen, '\0', newsize - newlen); + } + memcpy(str + len, str2, len2); + } else str = MCOPYSTR_INTERNAL(filename, line, str2); + } + return str; +} + +/* Tracking the origin: extracts the filename/line from the original allocation + * of the expstring_t. */ +expstring_t mputc(expstring_t str, char c) +{ + const char *filename = NULL; + int line = 0; + if (str != NULL) { + if (c != '\0') { + size_t size; + size_t len = fast_strlen(str, &size); + if (size <= len + 1) { + extract_location(str, &filename, &line); + str = (expstring_t)REALLOC_INTERNAL(filename, line, str, 2 * size); + memset(str + size, '\0', size); + } + str[len] = c; + } + } else { + if (c != '\0') { + str = (expstring_t)MALLOC_INTERNAL(filename, line, 2); + str[0] = c; + str[1] = '\0'; + } else str = MEMPTYSTR_INTERNAL(filename, line); + } + return str; +} + +/* Tracking the origin: extracts the filename/line from the original allocation + * of the expstring_t. */ +expstring_t mtruncstr(expstring_t str, size_t newlen) +{ + const char *filename = NULL; + int line = 0; + if (str != NULL) { + size_t size; + size_t len = fast_strlen(str, &size); + if (newlen < len) { + size_t newsize = roundup_size(newlen); + if (newsize < size) { + extract_location(str, &filename, &line); + str = (expstring_t)REALLOC_INTERNAL(filename, line, str, newsize); + } + memset(str + newlen, '\0', newsize - newlen); + } + } + return str; +} + +size_t mstrlen(const expstring_t str) +{ + if (str != NULL) { + size_t size; + return fast_strlen(str, &size); + } else return 0; +} + +char * buildstr(int b) { + if (b < 0 || b > 99) return NULL; /* invalid */ + if (b == 99) return memptystr(); /* empty string for full version */ + return mprintf("%02d", b); +} diff --git a/common/memory.h b/common/memory.h new file mode 100644 index 0000000..b048423 --- /dev/null +++ b/common/memory.h @@ -0,0 +1,291 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Common_memory_H +#define _Common_memory_H + +#include +#include + +#ifndef __GNUC__ +/** If a C compiler other than GCC is used the macro below will substitute all + * GCC-specific non-standard attributes with an empty string. */ +#ifndef __attribute__ +#define __attribute__(arg) +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * \defgroup mem Memory management and expstring functions + * \brief Functions for memory management and string handling. + * \author Janos Zoltan Szabo + * + * Primarily used in the TTCN-3 Test Executor (TTCN-3, ASN.1 compilers and + * runtime environment). + * @{ + */ + + /** + * Same as the standard \c malloc(), but it never returns NULL. + * It increases a malloc counter. If there is not enough memory, + * it calls \c fatal_error(), which exits the application. + * + * @param size number of bytes to allocate + * @return pointer to the beginning of the allocated memory, or + * NULL if and only if \c size is 0 + */ + extern void *Malloc(size_t size); +#ifdef MEMORY_DEBUG + extern void *Malloc_dbg(const char *filename, int line, size_t size); +#define Malloc(s) Malloc_dbg(__FILE__, __LINE__, s) +#endif + + /** + * Same as the standard \c realloc(), but it never returns NULL if \a size is + * positive. It updates the malloc or free counters if necessary. + * Exits if there is not enough memory. + * + * @param ptr pointer to a memory block allocated by Malloc(). If \p ptr + * is NULL, calls Malloc(size) + * @param size new size for the memory block. If \p size is 0, it calls + * Free(ptr) and returns NULL. + * @return pointer to the beginning of the re-allocated memory. + * Will only be NULL if size==0. + */ + extern void *Realloc(void *ptr, size_t size); +#ifdef MEMORY_DEBUG + extern void *Realloc_dbg(const char *filename, int line, void *ptr, size_t size); +#define Realloc(p,s) Realloc_dbg(__FILE__, __LINE__, p, s) +#endif + + /** + * Same as the standard \c free(). It increases the free counter if \a ptr + * is not NULL. + * + * @param ptr pointer to a memory block allocated by Malloc(). If \p ptr + * is NULL, this function does nothing. + */ + extern void Free(void *ptr); +#ifdef MEMORY_DEBUG + extern void Free_dbg(const char *filename, int line, void *ptr); +#define Free(p) Free_dbg(__FILE__, __LINE__, p) +#endif + + /** + * Prints a warning message to stderr if the malloc and free counters + * are not equals. It shall be called immediately before the end of + * program run. + */ + extern void check_mem_leak(const char *program_name); + +#ifdef MEMORY_DEBUG + /** + * Checks all allocated blocks of the program. Prints an error message and + * aborts if memory over-indexing is detected. + */ + extern void check_mem_corrupt(const char *program_name); + +#ifdef MEMORY_DEBUG_ADDRESS + /** @brief Memory allocation checkpoint. + + If this variable is set to a nonzero value, allocations starting + at that address will be logged to stderr. + + This can be used in conjunction with the output of check_mem_leak(). + */ + extern void * memory_debug_address; +#endif +#endif + + /** + * Character string type with exponential buffer allocation. The size of + * allocated buffer is always a power of 2. The terminating '\\0' character + * is always present and the remaining bytes in the buffer are also set to + * zero. This allows binary search for the end of string, which is + * significantly faster than the linear one especially for long strings. + * The spare bytes at the end make appending of small chunks very efficient. + * + * \warning If a function takes expstring_t as argument + * you should not pass a regular string (or a static string literal) + * to it. This may result in an unpredictable behaviour. You can + * convert any regular string to expstring_t using mcopystr: + * myexpstring = mcopystr(myregularstring); + */ + typedef char *expstring_t; + + /** + * mprintf() takes its arguments like \c printf() and prints according + * to the format string \a fmt into a string buffer. It allocates + * enough memory for the resulting string and returns the pointer + * to the result string. The result string is an exponential string. + * mprintf() never returns NULL. + */ + extern expstring_t mprintf(const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); +#ifdef MEMORY_DEBUG + extern expstring_t mprintf_dbg(const char *filename, int line, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +#if defined(__GNUC__) && __GNUC__ < 3 +# define mprintf(f, args...) mprintf_dbg(__FILE__, __LINE__, f, ## args) +#else +# define mprintf(f,...) mprintf_dbg(__FILE__, __LINE__, f, __VA_ARGS__) +#endif +#endif + + /** + * The same as \a mprintf(), but it takes the arguments as va_list. + * It is useful in wrapper functions with printf style argument strings. + */ + extern expstring_t mprintf_va_list(const char *fmt, va_list pvar); +#ifdef MEMORY_DEBUG + extern expstring_t mprintf_va_list_dbg(const char *filename, int line, + const char *fmt, va_list pvar); +#define mprintf_va_list(f,v) mprintf_va_list_dbg(__FILE__, __LINE__, f, v) +#endif + + /** + * mputprintf() prints its additional arguments according to the + * format string \a fmt at the end of \a str. The buffer of \a str is + * increased if the appended bytes do not fit in it. The result + * string, which is also an expstring, is returned. + * mputprintf() never returns NULL. + * \note If str is NULL it is equivalent to \a mprintf(). + * \warning The first argument must be an exponential string, + * otherwise its behaviour may be unpredictable. + */ + extern expstring_t mputprintf(expstring_t str, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); + + /** + * The same as \a mputprintf(), but it takes the arguments as va_list. + * It is useful in wrapper functions with printf style argument strings. + */ + extern expstring_t mputprintf_va_list(expstring_t str, const char *fmt, + va_list pvar); + + /** + * memptystr() creates and returns a new empty exponential string. + * The returned value is never NULL, + * it shall be deallocated using \a Free(). + */ + extern expstring_t memptystr(void); +#ifdef MEMORY_DEBUG + extern expstring_t memptystr_dbg(const char *filename, int line); +#define memptystr() memptystr_dbg(__FILE__, __LINE__) +#endif + + + /** + * mcopystr() creates a new exponential string and copies the contents of + * \a str into it. The resulting expstring is returned. + * The regular string \a str will not be deallocated and it may be + * a static string literal. + * If \a str is NULL an empty exponential string is returned. + * mcopystr() never returns NULL. + */ + extern expstring_t mcopystr(const char *str); +#ifdef MEMORY_DEBUG + extern expstring_t mcopystr_dbg(const char *filename, int line, const char *str); +#define mcopystr(s) mcopystr_dbg(__FILE__, __LINE__, s) +#endif + + /** + * Create a new exponential string when the length is known. + * Works exactly like mcopystr(), except the length is not measured; + * the given length is used instead. + * + * @param str pointer to the original string; does not need to be 0-terminated + * @param len number of characters to copy + * @return the newly constructed string (it needs to be Free()-d) + */ + extern expstring_t mcopystrn(const char *str, size_t len); +#ifdef MEMORY_DEBUG + extern expstring_t mcopystrn_dbg(const char *filename, int line, const char *str, + size_t len); +#define mcopystrn(s, len) mcopystrn_dbg(__FILE__, __LINE__, s, len) +#endif + + /** + * mputstr() appends the regular string \a str2 to the end of + * expstring \a str. The resulting expstring is returned. + * The buffer of \a str is increased if necessary. + * If \a str is NULL then \a str2 is copied into a new exponential string + * (i.e. mputstr(NULL, str) is identical to mcopystr(str)). + * If \a str2 is NULL then \a str is returned and remains unchanged + * (i.e. mputstr(str, NULL) is identical to str, + * mputstr(NULL, NULL) always returns NULL). + * \warning The first argument must be an exponential string, + * otherwise its behaviour may be unpredictable. + */ + extern expstring_t mputstr(expstring_t str, const char *str2); + + /** Appends \a len2 characters from the regular string \a str2 to the end of + * expstring \a str. The resulting expstring is returned. @see mputstr() + * @param str destination string + * @param str2 pointer to characters; does not need to be 0-terminated + * @param len2 number of characters to copy + * @return the (possibly reallocated) str + */ + extern expstring_t mputstrn(expstring_t str, const char *str2, size_t len2); + + /** + * mputc() appends the single character \a c to the end of + * expstring \a str. The buffer of \a str is increased if necessary. + * The resulting expstring is returned. + * If \a str is NULL then \a c is converted to a new exponential string. + * If \a c is '\\0' then \a str is returned. + * mputc() never returns NULL. + * \warning The first argument must be an exponential string, + * otherwise its behaviour may be unpredictable. + */ + extern expstring_t mputc(expstring_t str, char c); + + /** + * mtruncstr() truncates the expstring \a str by keeping only the first + * \a newlen characters and returns the resulting string. + * If the string is shorter than \a newlen it remains unchanged. + * mtruncstr() may perform memory reallocation if necessary. + * If \a str is NULL then a NULL pointer is returned. + * If \a str is not an exponential string the behaviour of mtruncstr() may + * be unpredictable. + */ + extern expstring_t mtruncstr(expstring_t str, size_t newlen); + + /** + * mstrlen() returns the length of expstring \a str or zero if \a str is + * NULL. If \a str is not NULL the function has identical result as libc's + * strlen(), but operates significantly faster. The behaviour may be + * unpredictable if \a str is not an exponential string. + */ + extern size_t mstrlen(const expstring_t str); + + /** @} end of mem group */ + + /** Return the string for the build number. + * + * @param b build number. + * @return a string which must be Free()-d by the caller + * @pre b > 0 and b <= 99, or else NULL is returned + */ + char * buildstr(int b); + +#ifdef __cplusplus + /** Convert a patch level to the "Ericsson letter" */ + inline char eri(unsigned int p) { /* p stands for patch level */ + char i = (char)('A' + p); /* i stands for "if only it was that simple" */ + return i + (i >= 'I') + 4 * (i >= 'N') + (i >= 'R'); + } + +} /* extern "C" */ + +#endif + +#endif /* _Common_memory_H */ diff --git a/common/new.cc b/common/new.cc new file mode 100644 index 0000000..7506718 --- /dev/null +++ b/common/new.cc @@ -0,0 +1,86 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "dbgnew.hh" +#include + +#undef new + +static void *dummy = NULL; + +void *operator new(size_t size) throw () +{ + return Malloc(size); +} + +void *operator new[](size_t size) throw () +{ + if (size == 0) return &dummy; + else return Malloc(size); +} + +void operator delete(void *ptr) throw() +{ + Free(ptr); +} + +void operator delete[](void *ptr) throw() +{ + if (ptr != (void*)&dummy) Free(ptr); +} + +/**************************************************************************/ + +#ifdef MEMORY_DEBUG + +// overloads for memory debug +void* operator new(size_t size, const char* file, int line) +{ + return Malloc_dbg(file, line, size); +} + +void* operator new[](size_t size, const char* file, int line) +{ + if (size == 0) return &dummy; + else return Malloc_dbg(file, line, size); +} + +int debug_new_counter_t::count = 0; // initial value + +#if defined(__CYGWIN__) || defined(INTERIX) + +extern char**__argv; + +#else + +const char * __argv [] __attribute__((weak)) = +{ + "program" +}; + +#endif + +const char * debug_new_counter_t::progname = __argv[0]; + +debug_new_counter_t::debug_new_counter_t() +{ + ++count; +} + +debug_new_counter_t::~debug_new_counter_t() +{ + if (--count == 0) { + check_mem_leak(progname); + } +} + +void debug_new_counter_t::set_program_name(const char * pgn) +{ + progname = pgn; +} + +#endif // MEMORY_DEBUG diff --git a/common/path.c b/common/path.c new file mode 100644 index 0000000..59765c2 --- /dev/null +++ b/common/path.c @@ -0,0 +1,232 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +#include "memory.h" +#include "path.h" + +/* Initial buffer size for getcwd */ +#define BUFSIZE 1024 + +expstring_t get_working_dir(void) +{ + expstring_t ret_val = NULL; + char buf[BUFSIZE]; + const char *buf_ptr; + buf_ptr = getcwd(buf, sizeof(buf)); + if (buf_ptr != NULL) ret_val = mcopystr(buf_ptr); + else if (errno == ERANGE) { + /* the initial buffer size is not enough */ + size_t size; + for (size = 2 * BUFSIZE; ; size *= 2) { + char *tmp = (char*)Malloc(size); + buf_ptr = getcwd(tmp, size); + if (buf_ptr != NULL) ret_val = mcopystr(buf_ptr); + Free(tmp); + if (buf_ptr != NULL || errno != ERANGE) break; + } + } + if (ret_val == NULL) { + /* an error occurred */ + path_error("Getting the current working directory failed: %s", + strerror(errno)); + } + /* clear the possible error codes */ + errno = 0; + return ret_val; +} + +int set_working_dir(const char *new_dir) +{ + if (new_dir == NULL) { + /* invalid argument */ + return 1; + } else if (chdir(new_dir)) { + /* an error occurred */ + path_error("Setting the current working directory to `%s' failed: %s", + new_dir, strerror(errno)); + errno = 0; + return 1; + } else { + /* everything is OK */ + return 0; + } +} + +enum path_status_t get_path_status(const char *path_name) +{ + struct stat buf; + if (stat(path_name, &buf)) { + if (errno != ENOENT) { + path_error("system call stat() failed on `%s': %s", path_name, + strerror(errno)); + } + errno = 0; + return PS_NONEXISTENT; + } + if (S_ISDIR(buf.st_mode)) return PS_DIRECTORY; + else return PS_FILE; +} + +expstring_t get_dir_from_path(const char *path_name) +{ + size_t last_slash_index = (size_t)-1; + size_t i; + for (i = 0; path_name[i] != '\0'; i++) + if (path_name[i] == '/') last_slash_index = i; + if (last_slash_index == (size_t)-1) { + /* path_name does not contain any slash */ + return NULL; + } else if (last_slash_index == 0) { + /* path_name has the format "/filename": return "/" */ + return mcopystr("/"); + } else { + /* path_name has the format "/filename": + return "" */ + expstring_t ret_val = mcopystr(path_name); + ret_val = mtruncstr(ret_val, last_slash_index); + return ret_val; + } +} + +expstring_t get_file_from_path(const char *path_name) +{ + size_t last_slash_index = (size_t)-1; + size_t i; + for (i = 0; path_name[i] != '\0'; i++) + if (path_name[i] == '/') last_slash_index = i; + if (last_slash_index == (size_t)-1) { + /* path_name does not contain any slash: return the entire input */ + return mcopystr(path_name); + } else { + /* path_name has the format "/filename": return "filename" */ + return mcopystr(path_name + last_slash_index + 1); + } +} + +expstring_t compose_path_name(const char *dir_name, + const char *file_name) +{ + if (dir_name != NULL && dir_name[0] != '\0') { + expstring_t ret_val = mcopystr(dir_name); + if (file_name != NULL && file_name[0] != '\0') { + /* neither dir_name nor file_name are empty */ + size_t dir_name_len = strlen(dir_name); + /* do not add the separator slash if dir_name ends with a slash */ + if (dir_name[dir_name_len - 1] != '/') + ret_val = mputc(ret_val, '/'); + ret_val = mputstr(ret_val, file_name); + } + return ret_val; + } else return mcopystr(file_name); +} + +expstring_t get_absolute_dir(const char *dir_name, const char *base_dir) +{ + expstring_t ret_val; + /* save the working directory */ + expstring_t initial_dir = get_working_dir(); + if (base_dir != NULL && (dir_name == NULL || dir_name[0] != '/')) { + /* go to base_dir first if it is given and dir_name is not an + absolute path */ + if (set_working_dir(base_dir)) { + Free(initial_dir); + return NULL; + } + } + if (dir_name != NULL && set_working_dir(dir_name)) { + /* there was an error: go back to initial_dir */ + set_working_dir(initial_dir); + Free(initial_dir); + return NULL; + } + ret_val = get_working_dir(); + /* restore the working directory */ + set_working_dir(initial_dir); + Free(initial_dir); + if (ret_val != NULL && +#if defined WIN32 && defined MINGW + /* On native Windows the absolute path name shall begin with + * a drive letter, colon and backslash */ + (((ret_val[0] < 'A' || ret_val[0] > 'Z') && + (ret_val[0] < 'a' || ret_val[0] > 'z')) || + ret_val[1] != ':' || ret_val[2] != '\\') +#else + /* On UNIX-like systems the absolute path name shall begin with + * a slash */ + ret_val[0] != '/' +#endif + ) + path_error("Internal error: `%s' is not a valid absolute pathname.", + ret_val); + return ret_val; +} + +expstring_t get_relative_dir(const char *dir_name, const char *base_dir) +{ + expstring_t ret_val = NULL; + /* canonize dir_name and the base directory */ + expstring_t canonized_dir_name = get_absolute_dir(dir_name, base_dir); + expstring_t canonized_base_dir = base_dir != NULL ? + get_absolute_dir(base_dir, NULL) : get_working_dir(); + size_t i, last_slash = 0; + if (canonized_dir_name == NULL || canonized_base_dir == NULL) { + /* an error occurred */ + Free(canonized_dir_name); + Free(canonized_base_dir); + return NULL; + } + /* skip over the common leading directory part of canonized_dir_name and + canonized_base_dir */ + for (i = 1; ; i++) { + char dir_c = canonized_dir_name[i]; + char base_c = canonized_base_dir[i]; + if (dir_c == '\0') { + /* we must update last_slash if dir_name is a parent of base_dir */ + if (base_c == '/') last_slash = i; + /* we must stop anyway */ + break; + } else if (dir_c == '/') { + if (base_c == '/' || base_c == '\0') last_slash = i; + if (base_c != '/') break; + } else { + if (dir_c != base_c) break; + } + } + if (canonized_dir_name[i] == '\0' && canonized_base_dir[i] == '\0') { + /* canonized_dir_name and canonized_base_dir are the same */ + ret_val = mcopystr("."); + } else { + if (canonized_base_dir[last_slash] == '/' && + canonized_base_dir[last_slash + 1] != '\0') { + /* canonized_base_dir has some own additional components + (i.e. it is not the parent of canonized_dir_name) */ + for (i = last_slash; canonized_base_dir[i] != '\0'; i++) { + if (canonized_base_dir[i] == '/') { + /* go up one level in the relative path */ + if (ret_val != NULL) ret_val = mputc(ret_val, '/'); + ret_val = mputstr(ret_val, ".."); + } + } + } + if (canonized_dir_name[last_slash] == '/' && + canonized_dir_name[last_slash + 1] != '\0') { + /* canonized_dir_name has some own additional components + (i.e. it is not the parent of canonized_base_dir) */ + /* append the remaining parts of canonized_dir_name to the result */ + if (ret_val != NULL) ret_val = mputc(ret_val, '/'); + ret_val = mputstr(ret_val, canonized_dir_name + last_slash + 1); + } + } + Free(canonized_dir_name); + Free(canonized_base_dir); + return ret_val; +} diff --git a/common/path.h b/common/path.h new file mode 100644 index 0000000..b1594cb --- /dev/null +++ b/common/path.h @@ -0,0 +1,86 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Common_path_H +#define _Common_path_H + +#include "memory.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Error handling function that shall be provided by the application + * that uses this library. The meaning of argument(s) is the same as in + * \c printf() */ +extern void path_error(const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); + +/** Returns the current working directory of the process in canonical form. + * The string returned shall be deallocated by the caller using \a Free(). */ +extern expstring_t get_working_dir(void); + +/** Sets the current working directory of the process to \a new_dir. + * Returns 0 on success, function \a path_error() is called and non-zero value + * is returned in case of any error. If \a new_dir is NULL the unsuccessful + * status code is simply returned, \a path_error() is not called. */ +extern int set_working_dir(const char *new_dir); + +enum path_status_t { + PS_FILE, /**< the pathname is a file */ + PS_DIRECTORY, /**< the pathname is a directory */ + PS_NONEXISTENT /**< the pathname does not exist */ +}; + +/** Returns the status of \a path_name. Symbolic links are followed. + * In case of any problem other than non-existent file or directory + * function \a path_error() is called. */ +extern enum path_status_t get_path_status(const char *path_name); + +/** Returns the directory part of \a path_name. It is assumed that the + * argument points to a file. NULL pointer is returned if \a path_name is a + * simple file name without any slash. The string returned shall be + * deallocated by the caller using \a Free(). */ +extern expstring_t get_dir_from_path(const char *path_name); + +/** Returns the file name part of \a path_name. It is assumed that the + * argument points to a file. NULL pointer is returned if \a path_name ends + * with a slash. The string returned shall be deallocated by the caller using + * \a Free(). */ +extern expstring_t get_file_from_path(const char *path_name); + +/** Concatenates the given directory \a dir_name and file name \a file_name + * to get a path name. If either \a dir_name or \a file_name is NULL or empty + * string the resulting path name will contain only the other component. The + * slash is inserted between \a dir_name and \a file_name only when necessary. + * The string returned shall be deallocated by the caller using \a Free(). */ +extern expstring_t compose_path_name(const char *dir_name, + const char *file_name); + +/** Converts \a dir_name, which is relative to \a base_dir, to an absolute + * directory path. If \a base_dir is NULL the current working directory of + * the process is used. It is assumed that both \a dir_name and \a base_dir + * are existing directories. The returned directory name is in canonical form + * (i.e. symlinks in it are resolved). NULL pointer returned in case of error. + * The string returned shall be deallocated by the caller using \a Free(). + * Note: The working directory of the current process might change during the + * function call, but it is restored before the function returns. */ +extern expstring_t get_absolute_dir(const char *dir_name, const char *base_dir); + +/** Converts \a dir_name to a relative path name based on \a working_dir. If + * \a working_dir is NULL the current working directory of the process is used. + * It is assumed that both \a dir_name and \a working_dir are existing + * directories. NULL pointer is returned in case of any error. + * The string returned shall be deallocated by the caller using \a Free().*/ +extern expstring_t get_relative_dir(const char *dir_name, + const char *working_dir); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _Common_path_H */ diff --git a/common/pattern.hh b/common/pattern.hh new file mode 100644 index 0000000..f5db171 --- /dev/null +++ b/common/pattern.hh @@ -0,0 +1,36 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _common_pattern_HH +#define _common_pattern_HH + +#ifndef __GNUC__ +/** If a C compiler other than GCC is used the macro below will substitute all + * GCC-specific non-standard attributes with an empty string. */ +#ifndef __attribute__ +#define __attribute__(arg) +#endif +#endif + +/** This is the interface for pattern. This function converts a TTCN-3 + * charstring pattern to a POSIX Extended Regular Expression (ERE). + * If error occurs, returns a NULL-pointer. It uses the + * TTCN_pattern_error() and TTCN_pattern_warning() functions to + * report errors/warnings. */ +extern char* TTCN_pattern_to_regexp(const char* p_pattern); + +extern char* TTCN_pattern_to_regexp_uni(const char* p_pattern, + int** groups = 0); + +/* defined elsewhere (can be different in compiler/runtime) */ + +extern void TTCN_pattern_error(const char *fmt_str, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); +extern void TTCN_pattern_warning(const char *fmt_str, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); + +#endif /* _common_pattern_HH */ diff --git a/common/pattern_la.l b/common/pattern_la.l new file mode 100644 index 0000000..29e3d16 --- /dev/null +++ b/common/pattern_la.l @@ -0,0 +1,277 @@ +/****************************************************************************** + * 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 + ******************************************************************************/ + +/** + * Lexical analyzer for TTCN-3 character patterns. + * + * \author Matyas Forstner (Matyas.Forstner@eth.ericsson.se) + * + * 20031121 + */ + +%option nostack +%option noyylineno +%option noyywrap +%option nounput +%option never-interactive +%option prefix="pattern_yy" + +%{ /* ****************** C declarations ***************** */ + +#include +#include +#include "pattern.hh" +#include "pattern_p.hh" + + /* Access the semantic value of the bison parser. Usually this is done by + * #defining yylval to the appropriate symbol whose name depends on the + * %name-prefix of the parser, e.g. pattern_yylval or pattern_unilval. + * + * Because we need to be able to access either one or the other, + * we keep a pointer which is set by the parser when it calls + * init_pattern_yylex() */ +static YYSTYPE *yylval_ptr; +#define yylval (*yylval_ptr) + +static unsigned int nof_parentheses = 0; +static bool meta = false; + +%} /* ***************** definitions ***************** */ + +NUMBER 0|([1-9][0-9]*) + +/* start conditions */ +%x SC_Set SC_Hash SC_HashParen SC_Quadruple SC_Quadruple_Set + +%% /* ***************** rules ************************* */ + + /* drop whitespaces */ +[ \t\r\n\v\f]+ + + +{ + +"]" { + BEGIN(INITIAL); + return KW_Set_End; +} + +"-]" { + BEGIN(INITIAL); + return KW_Set_Dash_End; +} + +"-" return '-'; + +} /* SC_Set */ + + +{ + +[0-9] { + BEGIN(INITIAL); + yylval.u = yytext[0] - '0'; + return TOK_Digit; +} + +"(" { + BEGIN(SC_HashParen); + return '('; +} + +} /* SC_Hash */ + + +{ + +{NUMBER} { + errno = 0; + yylval.u = strtoul(yytext, NULL, 10); + if (errno != 0) TTCN_pattern_error("Number `%s' is too large to be " + "represented in memory. (%s)", yytext, strerror(errno)); + return TOK_Number; +} + +"," return ','; + +} /* SC_HashParen,SC_Quadruple,SC_Quadruple_Set */ + +")" { + BEGIN(INITIAL); + return ')'; +} + + +{ + +"{" return '{'; + +"}" { + if (YY_START == SC_Quadruple) BEGIN(INITIAL); + else BEGIN(SC_Set); + return '}'; +} + +} /* SC_Quadruple,SC_Quadruple_Set */ + +"*" { meta = true; return '*'; } +"+" { meta = true; return '+'; } +"?" { meta = true; return '?'; } +"|" { meta = true; return '|'; } + +"(" { + nof_parentheses++; + meta = true; + return KW_Group_Begin; +} + +")" { + if (nof_parentheses > 0) { + nof_parentheses--; + return KW_Group_End; + } else { + TTCN_pattern_error("Unmatched `)'."); + yylval.c = ')'; + return TOK_Char; + } +} + +"[" { + BEGIN(SC_Set); + meta = true; + return KW_Set_Begin; +} + +"[^" { + BEGIN(SC_Set); + meta = true; + return KW_Set_Begin_Neg; +} + +"[]" { + BEGIN(SC_Set); + meta = true; + return KW_Set_Begin_Rsbrkt; +} + +"[^]" { + BEGIN(SC_Set); + meta = true; + return KW_Set_Begin_Neg_Rsbrkt; +} + +"]" { + TTCN_pattern_error("Unmatched `]'."); + yylval.c = ']'; + return TOK_Char; +} + +"#" { + BEGIN(SC_Hash); + meta = true; + return '#'; +} + + +{ + + /* \metacharacters */ +"\\d" { meta = true; return KW_BS_d; } +"\\w" { meta = true; return KW_BS_w; } +"\\t" { meta = true; return KW_BS_t; } +"\\n" { meta = true; return KW_BS_n; } +"\\r" { meta = true; return KW_BS_r; } +"\\s" { meta = true; return KW_BS_s; } +"\\b" { meta = true; return KW_BS_b; } + +"\\q" { + meta = true; + if (YY_START == INITIAL) BEGIN(SC_Quadruple); + else BEGIN(SC_Quadruple_Set); + return KW_BS_q; +} + + /* escaped special characters: ? * \ [ ] - ^ | ( ) # + { } */ +\\[][?*\\^|()#+{}-] { + yylval.c = yytext[1]; + return TOK_Char; /* not meta */ +} + + /* invalid escape sequences */ +"\\"(.|"\n") { + if (isprint((unsigned char)yytext[1])) + TTCN_pattern_warning("Use of unrecognized escape sequence `\\%c' is " + "deprecated.", yytext[1]); + else TTCN_pattern_warning("Use of unrecognized escape sequence `\\' + " + "character code %u (0x%02X) is deprecated.", (unsigned char)yytext[1], + (unsigned char)yytext[1]); + yylval.c = yytext[1]; + return TOK_Char; +} + + /* single backslash (at the end) */ +\\ { + TTCN_pattern_error("Invalid single backslash (`\\') character at the end " + "of the pattern."); +} + +.|"\n" { + yylval.c = yytext[0]; + return TOK_Char; +} + +} /* INITIAL, SC_Set */ + + /* erroneous characters */ + +.|\n { + if (isprint((unsigned char)yytext[0])) + TTCN_pattern_error("A digit or `(' was expected after `#' instead of " + "character `%c'.", yytext[0]); + else TTCN_pattern_error("A digit or `(' was expected after `#' instead of " + "character with code %u (0x%02X).", (unsigned char)yytext[0], + (unsigned char)yytext[0]); +} + +. { + if (isprint((unsigned char)yytext[0])) + TTCN_pattern_error("A number, `,' or `)' was expected after `#(' instead " + "of character `%c'.", yytext[0]); + else TTCN_pattern_error("A number, `,' or `)' was expected after `#(' " + "instead of character with code %u (0x%02X).", (unsigned char)yytext[0], + (unsigned char)yytext[0]); +} + +. { + if (isprint((unsigned char)yytext[0])) + TTCN_pattern_error("A number, `,' or `}' was expected after `\\q{' " + "instead of character `%c'.", yytext[0]); + else TTCN_pattern_error("A number, `,' or `}' was expected after `\\q{' " + "instead of character with code %u (0x%02X).", (unsigned char)yytext[0], + (unsigned char)yytext[0]); +} + +%% + +unsigned int get_nof_parentheses() +{ + return nof_parentheses; +} + +bool has_meta() +{ + return meta; +} + +void init_pattern_yylex(YYSTYPE *sema_val) +{ + BEGIN(INITIAL); + yylval_ptr = sema_val; + nof_parentheses = 0; + meta = false; +} diff --git a/common/pattern_p.y b/common/pattern_p.y new file mode 100644 index 0000000..8d01c5c --- /dev/null +++ b/common/pattern_p.y @@ -0,0 +1,966 @@ +/****************************************************************************** + * 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 + ******************************************************************************/ + +/** + * Parser for TTCN-3 character patterns. + * + * \author Matyas Forstner (Matyas.Forstner@eth.ericsson.se) + * + * 20031121 + */ + +%{ + +/********************************************************************* + * C(++) declarations + *********************************************************************/ + +#include +#include +#include +#if defined(__CYGWIN__) && defined(__clang__) +/* Cygwin's clang 3.0 has its own limits.h, which does not bring in + the system's limits.h unless we define this macro: */ +#define __STDC_HOSTED__ 1 +#define _GCC_NEXT_LIMITS_H +#endif +#include + +#include +#if !defined(RE_DUP_MAX) +/* RE_DUP_MAX is defined in limits.h or regex.h, except on Cygwin 1.5 */ +# include +#endif + +#include "memory.h" +#include "pattern.hh" + +/* defined in lexer c-file: */ + + union YYSTYPE; + extern int pattern_yylex(); + extern void init_pattern_yylex(YYSTYPE *p); + struct yy_buffer_state; + extern yy_buffer_state* pattern_yy_scan_string(const char*); + extern int pattern_yylex_destroy(); + extern unsigned int get_nof_parentheses(); + +/* defined in this file: */ + + /** The converted regexp. */ + static char *ret_val; + /** The parser error reporting function. */ + static void pattern_yyerror(const char *error_str); + /** Creates the POSIX equivalent of literal character \a c using the + * appropriate escape sequence when needed. */ + static char *translate_character(char c); + /** Returns the printable equivalent of character \a c */ + static char *print_character(char c); + /** Returns the printable equivalent of range \a lower .. \a upper */ + static char *print_range(char lower, char upper); + /** structure for manipulating character sets */ + struct character_set; + /** allocates, initializes and returns a new empty set */ + static character_set *set_init(); + /** allocates and returns a copy of \a set */ + static character_set *set_copy(const character_set *set); + /** deallocates set \a set */ + static void set_free(character_set *set); + /** returns whether set \a set is empty */ + static int set_is_empty(const character_set *set); + /** returns whether set \a set contains all characters in range 1..127 */ + static int set_is_full(const character_set *set); + /** returns whether set \a set contains the character \a c */ + static int set_has_char(const character_set *set, char c); + /** adds character \a c to set \a set */ + static void set_add_char(character_set *set, char c); + /** removes character \a c to set \a set */ + static void set_remove_char(character_set *set, char c); + /** returns whether set \a set contains at least one character in the range + * \a lower .. \a upper */ + static int set_has_range(const character_set *set, char lower, char upper); + /** adds range \a lower .. \a upper to set \a set */ + static void set_add_range(character_set *set, char lower, char upper); + /** returns whether set \a set1 and \a set2 has non-empty intersect */ + static int set_has_intersect(const character_set *set1, + const character_set *set2); + /** joins sets \a dst and \a src into \a dst */ + static void set_join(character_set *dst, const character_set *src); + /** negates the set \a set */ + static void set_negate(character_set *set); + /** reports the duplicate occurrences of characters and ranges in \a set1 + * and \a set2 */ + static void set_report_duplicates(const character_set *set1, + const character_set *set2); + /** generates the POSIX equivalent of \a set */ + static char *set_generate_posix(const character_set *set); + +#define YYERROR_VERBOSE + +static void yyprint(FILE *file, int type, const YYSTYPE& value); +#define YYPRINT(f,t,v) yyprint(f,t,v) + +%} + +/********************************************************************* + * Bison declarations + *********************************************************************/ + +%name-prefix="pattern_yy" +%output="pattern_p.cc" +%defines +%verbose +%expect 0 +%start Pattern +%debug + +/********************************************************************* + * The union-type + * Must be kept in sync with the one in pattern_uni.y ! + *********************************************************************/ + +%union { + int b; /* boolean */ + char c; /* single character */ + char *s; /* character string */ + unsigned long int u; /* unsigned integer */ + struct character_set *set; // used by nonterminals in pattern_p.y + + union { + unsigned int value; +#if defined(__sparc__) || defined(__sparc) + struct { + unsigned char group; + unsigned char plane; + unsigned char row; + unsigned char cell; + } comp; +#else + struct { + unsigned char cell; + unsigned char row; + unsigned char plane; + unsigned char group; + } comp; +#endif + } q; // single universal char, used by nonterminals in pattern_uni.y + class QuadSet* qset; // used by nonterminals in pattern_uni.y +} + +/********************************************************************* + * Tokens + *********************************************************************/ + +%token TOK_Char "" +%token TOK_Number "" +%token TOK_Digit "" + +/********************************************************************* + * Keywords + *********************************************************************/ + +%token KW_BS_q "\\q" +%token KW_BS_d "\\d" +%token KW_BS_w "\\w" +%token KW_BS_t "\\t" +%token KW_BS_n "\\n" +%token KW_BS_r "\\r" +%token KW_BS_s "\\s" +%token KW_BS_b "\\b" + +%token KW_Group_Begin "(" +%token KW_Group_End ")" +%token KW_Set_Begin "[" +%token KW_Set_Begin_Neg "[^" +%token KW_Set_Begin_Rsbrkt "[]" +%token KW_Set_Begin_Neg_Rsbrkt "[^]" +%token KW_Set_End "]" +%token KW_Set_Dash_End "-]" + +/********************************************************************* + * semantic types of nonterminals + *********************************************************************/ + +%type RE_Set_Begin RE_Set_Begin_Rsbrkt RE_Set_End +%type RE_Set_Range_Char RE_Quadruple +%type RE_Body RE_Elems RE_Alter_Elem RE_Concat_Elem + RE_Multiply_Elem RE_Multiply_Statement RE_Group + RE_OneCharPos +%type RE_Set RE_Set_Body RE_Set_Elem RE_Set_NoRange_Char + +/********************************************************************* + * Destructors + *********************************************************************/ + +%destructor { Free($$); } +RE_Alter_Elem +RE_Body +RE_Concat_Elem +RE_Elems +RE_Group +RE_Multiply_Elem +RE_Multiply_Statement +RE_OneCharPos + +%destructor { set_free($$); } +RE_Set +RE_Set_Body +RE_Set_Elem +RE_Set_NoRange_Char + +%% + +/********************************************************************* + * Grammar + *********************************************************************/ + +Pattern: + RE_Body {ret_val=$1;} +; + +RE_Body: + /* empty */ + { + $$ = mcopystr("^$"); + } +| RE_Elems + { + if ($1 != NULL) { + $$ = mprintf("^%s$", $1); + Free($1); + } else $$ = mcopystr("^$"); + } +; + +RE_Elems: + RE_Alter_Elem { $$ = $1; } +| RE_Elems '|' RE_Alter_Elem + { + unsigned int nof_pars = get_nof_parentheses() + (yychar==KW_Group_End ? 1 : 0); + if ($3 != NULL) { + if ($1 != NULL) $$ = mputprintf($1, nof_pars ? "|%s" : "$|^%s", $3); + else $$ = mprintf( nof_pars ? "()|%s" : "()$|^%s" , $3); + Free($3); + } else { + if ($1 != NULL) $$ = mputstr($1, nof_pars ? "|()" : "$|^()"); + else $$ = NULL; + } + } +; + +RE_Alter_Elem: + RE_Concat_Elem { $$ = $1; } +| RE_Alter_Elem RE_Concat_Elem + { + $$ = mputstr($1, $2); + Free($2); + } +; + +RE_Concat_Elem: + RE_Multiply_Elem {$$=$1;} +| RE_Multiply_Elem RE_Multiply_Statement + { + if ($1 != NULL && $2 != NULL) { + $$ = mputstr($1, $2); + Free($2); + } else { + Free($1); + Free($2); + $$ = NULL; + } + } +| '*' {$$=mcopystr(".*");} +; + +RE_Multiply_Elem: + RE_Group {$$=$1;} +| RE_OneCharPos {$$=$1;} +; + +RE_Group: + KW_Group_Begin KW_Group_End + { + $$ = mcopystr("()"); + } +| KW_Group_Begin RE_Elems KW_Group_End + { + if ($2 != NULL) { + $$ = mprintf("(%s)", $2); + Free($2); + } else { + $$ = mcopystr("()"); + } + } +; + +RE_Multiply_Statement: + '+' + { + $$ = mcopystr("+"); + } +| '#' '(' ',' ')' + { + $$ = mcopystr("*"); + } +| '#' TOK_Digit + { + if ($2 == 0) { + TTCN_pattern_warning("The number of repetitions is zero: `#0'."); + $$ = NULL; + } else if ($2 == 1) $$ = memptystr(); + else { + if ($2 > 9) TTCN_pattern_warning("Internal error: Invalid number of " + "repetitions: `#%lu'.", $2); + $$ = mprintf("{%lu}", $2); + } + } +| '#' '(' TOK_Number ')' + { + if ($3 == 0) { + TTCN_pattern_warning("The number of repetitions is zero: `#(0)'."); + $$ = NULL; + } else if ($3 == 1) $$ = memptystr(); + else { +#ifdef RE_DUP_MAX + if ($3 > RE_DUP_MAX) TTCN_pattern_warning("The number of repetitions in " + "`#(%lu)' exceeds the limit allowed by this system (%d).", $3, + RE_DUP_MAX); +#endif + $$ = mprintf("{%lu}", $3); + } + } +| '#' '(' TOK_Number ',' TOK_Number ')' + { +#ifdef RE_DUP_MAX + if ($3 > RE_DUP_MAX) TTCN_pattern_warning("The minimum number of " + "repetitions in `#(%lu,%lu)' exceeds the limit allowed by this system " + "(%d).", $3, $5, RE_DUP_MAX); + if ($5 > RE_DUP_MAX) TTCN_pattern_warning("The maximum number of " + "repetitions in `#(%lu,%lu)' exceeds the limit allowed by this system " + "(%d).", $3, $5, RE_DUP_MAX); +#endif + if ($3 > $5) TTCN_pattern_error("The lower bound is higher than the upper " + "bound in the number of repetitions: `#(%lu,%lu)'.", $3, $5); + if ($3 == $5) { + if ($3 == 0) { + TTCN_pattern_warning("The number of repetitions is zero: `#(0,0)'."); + $$ = NULL; + } else if ($3 == 1) $$ = memptystr(); + else { + $$ = mprintf("{%lu}", $3); + } + } else { + if ($3 == 0 && $5 == 1) $$ = mcopystr("?"); + else $$ = mprintf("{%lu,%lu}", $3, $5); + } + } +| '#' '(' ',' TOK_Number ')' + { + if ($4 == 0) { + TTCN_pattern_warning("The number of repetitions is zero: `#(,0)'."); + $$ = NULL; + } else { +#ifdef RE_DUP_MAX + if ($4 > RE_DUP_MAX) TTCN_pattern_warning("The maximum number of " + "repetitions in `#(,%lu)' exceeds the limit allowed by this system " + "(%d).", $4, RE_DUP_MAX); +#endif + if ($4 == 1) $$ = mcopystr("?"); + else $$ = mprintf("{0,%lu}", $4); + } + } +| '#' '(' TOK_Number ',' ')' + { + if ($3 == 0) $$ = mcopystr("*"); + else { +#ifdef RE_DUP_MAX + if ($3 > RE_DUP_MAX) TTCN_pattern_warning("The minimum number of " + "repetitions in `#(%lu,)' exceeds the limit allowed by this system " + "(%d).", $3, RE_DUP_MAX); +#endif + if ($3 == 1) $$ = mcopystr("+"); + else $$ = mprintf("{%lu,}", $3); + } + } +; + +RE_OneCharPos: + '?' {$$=mcopystr(".");} +| KW_BS_d {$$=mcopystr("[0-9]");} +| KW_BS_w {$$=mcopystr("[0-9A-Za-z]");} +| KW_BS_t {$$=mcopystr("\t");} +| KW_BS_n {$$=mcopystr("[\n-\r]");} +| KW_BS_r {$$=mcopystr("\r");} +| KW_BS_s {$$=mcopystr("[\t-\r ]");} +| KW_BS_b + { + TTCN_pattern_warning("Metacharacter `\\b' is not supported yet."); + $$ = NULL; + } +| TOK_Char + { + unsigned char c = $1; + if (c == 0 || c > 127) TTCN_pattern_error("Character with code %u " + "(0x%02x) cannot be used in a pattern for type charstring.", c, c); + $$ = translate_character($1); + } +| RE_Quadruple + { + $$ = translate_character($1); + } +| RE_Set + { + if (set_is_empty($1)) { + TTCN_pattern_error("Empty character set."); + $$ = NULL; + } else $$ = set_generate_posix($1); + set_free($1); + } +; + +RE_Set: + /* RE_Set_Begin is 1 for "[^", 0 for "[" + * RE_Set_Begin_Rsbrkt is 1 for "[^]", 0 for "[]" + * RE_Set_End is 1 for "-]", 0 for "]" + */ + RE_Set_Begin RE_Set_Body RE_Set_End + { + if ($2 != NULL) $$ = $2; + else $$ = set_init(); + if ($3) { + if (set_has_char($$, '-')) + TTCN_pattern_warning("Duplicate character `-' in the character set."); + else set_add_char($$, '-'); + } + if ($1) set_negate($$); + } +| RE_Set_Begin '-' RE_Set_Body RE_Set_End + { + if ($3 != NULL) $$ = $3; + else $$ = set_init(); + if (set_has_char($$, '-')) + TTCN_pattern_warning("Duplicate character `-' in the character set."); + else set_add_char($$, '-'); + if ($4) { + if (set_has_char($$, '-')) + TTCN_pattern_warning("Duplicate character `-' in the character set."); + else set_add_char($$, '-'); + } + if ($1) set_negate($$); + } +| RE_Set_Begin_Rsbrkt RE_Set_Body RE_Set_End + { + if ($2 != NULL) $$ = $2; + else $$ = set_init(); + if (set_has_char($$, ']')) + TTCN_pattern_warning("Duplicate character `]' in the character set."); + else set_add_char($$, ']'); + if ($3) { + if (set_has_char($$, '-')) + TTCN_pattern_warning("Duplicate character `-' in the character set."); + else set_add_char($$, '-'); + } + if ($1) set_negate($$); + } +| RE_Set_Begin_Rsbrkt '-' RE_Set_Range_Char RE_Set_Body RE_Set_End + { + if ($4 != NULL) $$ = $4; + else $$ = set_init(); + char *range_str = print_range(']', $3); + if (']' > $3) { + TTCN_pattern_error("Invalid range `%s' in the character set: the " + "character code of the lower bound (%u) is higher than that of the " + "upper bound (%u).", range_str, ']', (unsigned char)$3); + } else { + if (set_has_range($$, ']', $3)) { + character_set *tmpset = set_init(); + set_add_range(tmpset, ']', $3); + set_report_duplicates($$, tmpset); + set_free(tmpset); + } + } + set_add_range($$, ']', $3); + Free(range_str); + if ($5) { + if (set_has_char($$, '-')) + TTCN_pattern_warning("Duplicate character `-' in the character set."); + else set_add_char($$, '-'); + } + if ($1) set_negate($$); + } +; + +RE_Set_Begin: + KW_Set_Begin { $$ = 0; } +| KW_Set_Begin_Neg { $$ = 1; } +; + +RE_Set_Begin_Rsbrkt: + KW_Set_Begin_Rsbrkt { $$ = 0; } +| KW_Set_Begin_Neg_Rsbrkt { $$ = 1; } +; + +RE_Set_End: + KW_Set_End { $$ = 0; } +| KW_Set_Dash_End { $$ = 1; } +; + +RE_Set_Body: + /* empty */ { $$ = NULL; } +| RE_Set_Body RE_Set_Elem + { + if ($1 != NULL) { + $$ = $1; + if (set_has_intersect($$, $2)) set_report_duplicates($$, $2); + set_join($$, $2); + set_free($2); + } else $$ = $2; + } +; + +RE_Set_Elem: + RE_Set_Range_Char + { + $$ = set_init(); + set_add_char($$, $1); + } +| RE_Set_NoRange_Char { $$ = $1; } +| RE_Set_Range_Char '-' RE_Set_Range_Char + { + if ($1 > $3) { + char *range_str = print_range($1, $3); + TTCN_pattern_error("Invalid range `%s' in the character set: the " + "character code of the lower bound (%u) is higher than that of the " + "upper bound (%u).", range_str, (unsigned char)$1, (unsigned char)$3); + Free(range_str); + } + $$ = set_init(); + set_add_range($$, $1, $3); + } +; + +RE_Set_Range_Char: + KW_BS_t { $$ = '\t'; } +| KW_BS_r { $$ = '\r'; } +| TOK_Char + { + unsigned char c = $1; + if (c == 0 || c > 127) TTCN_pattern_error("Character with code %u " + "(0x%02x) cannot be used in a pattern for type charstring.", c, c); + $$ = $1; + } +| RE_Quadruple { $$ = $1; } +; + +RE_Set_NoRange_Char: + KW_BS_d + { + $$ = set_init(); + set_add_range($$, '0', '9'); + } +| KW_BS_w + { + $$ = set_init(); + set_add_range($$, '0', '9'); + set_add_range($$, 'A', 'Z'); + set_add_range($$, 'a', 'z'); + } +| KW_BS_n + { + $$ = set_init(); + set_add_range($$, '\n', '\r'); + } +| KW_BS_s + { + $$ = set_init(); + set_add_range($$, '\t', '\r'); + set_add_char($$, ' '); + } +| KW_BS_b + { + TTCN_pattern_error("Metacharacter `\\b' does not make any sense in a " + "character set."); + $$ = set_init(); + } +; + +RE_Quadruple: + KW_BS_q '{' TOK_Number ',' TOK_Number ',' TOK_Number ',' TOK_Number '}' + { + if ($3 > 127) TTCN_pattern_error("The first number (group) of quadruple " + "`\\q{%lu,%lu,%lu,%lu}' is too large. It should be in the range 0..127 " + "instead of %lu.", $3, $5, $7, $9, $3); + if ($5 > 255) TTCN_pattern_error("The second number (plane) of quadruple " + "`\\q{%lu,%lu,%lu,%lu}' is too large. It should be in the range 0..255 " + "instead of %lu.", $3, $5, $7, $9, $5); + if ($7 > 255) TTCN_pattern_error("The third number (row) of quadruple " + "`\\q{%lu,%lu,%lu,%lu}' is too large. It should be in the range 0..255 " + "instead of %lu.", $3, $5, $7, $9, $7); + if ($9 > 255) TTCN_pattern_error("The fourth number (cell) of quadruple " + "`\\q{%lu,%lu,%lu,%lu}' is too large. It should be in the range 0..255 " + "instead of %lu.", $3, $5, $7, $9, $9); + if ($3 > 0 || $5 > 0 || $7 > 0 || $9 > 127) TTCN_pattern_error("Quadruple " + "`\\q{%lu,%lu,%lu,%lu}' is not valid in a pattern for type charstring.", + $3, $5, $7, $9); + if ($3 == 0 && $5 == 0 && $7 == 0 && $9 == 0) TTCN_pattern_error("Zero " + "character (i.e. quadruple `\\q{0,0,0,0}') is not supported in a " + "pattern for type charstring."); + $$ = $9; + } +; + +%% + +/********************************************************************* + * Interface + *********************************************************************/ + +char* TTCN_pattern_to_regexp(const char* p_pattern) +{ + /* if you want to debug */ + //pattern_yydebug=1; + + ret_val=NULL; + + yy_buffer_state *flex_buffer = pattern_yy_scan_string(p_pattern); + if(flex_buffer == NULL) { + TTCN_pattern_error("Flex buffer creation failed."); + return NULL; + } + init_pattern_yylex(&yylval); + if(pattern_yyparse()) { + Free(ret_val); + ret_val=NULL; + } + pattern_yylex_destroy(); + return ret_val; +} + +// Backwards compatibility shim +char* TTCN_pattern_to_regexp(const char* p_pattern, int ere) +{ + TTCN_pattern_warning( + "TTCN_pattern_to_regexp(const char* p_pattern, int ere) is deprecated"); + if (ere != 1) TTCN_pattern_error( + "BRE is not supported for TTCN_pattern_to_regexp"); + return TTCN_pattern_to_regexp(p_pattern); +} + +/********************************************************************* + * Static functions + *********************************************************************/ + +/// Error reporting function +void pattern_yyerror(const char *error_str) +{ + TTCN_pattern_error("%s", error_str); +} + +/** Escape plain characters which would be metacharacters in a regex. + * + * @param c plain character + * @return a newly allocated string which must be Free() 'd + */ +char *translate_character(char c) +{ + int escape_needed = 0; + switch (c) { + case '|': + case '+': + case '?': + case '{': + case '}': + case '(': + case ')': + case '.': + case '^': + case '$': + case '[': + case '*': + case '\\': + escape_needed = 1; + break; + } + if (escape_needed) return mprintf("\\%c", c); + else return mputc(NULL, c); +} + +char *print_character(char c) +{ + switch (c) { + case '\t': + return mcopystr("\\t"); + case '\r': + return mcopystr("\\r"); + default: + if (isprint((unsigned char)c)) return mprintf("%c", c); + else return mprintf("\\q{0,0,0,%u}", (unsigned char)c); + } +} + +char *print_range(char lower, char upper) +{ + char *range_str = print_character(lower); + range_str = mputc(range_str, '-'); + char *upper_str = print_character(upper); + range_str = mputstr(range_str, upper_str); + Free(upper_str); + return range_str; +} + +#define CS_BITS_PER_ELEM (8 * sizeof(unsigned long)) +#define CS_NOF_ELEMS ((128 + CS_BITS_PER_ELEM - 1) / CS_BITS_PER_ELEM) + +struct character_set { + unsigned long set_members[CS_NOF_ELEMS]; +}; + +character_set *set_init() +{ + character_set *set = (character_set*)Malloc(sizeof(*set)); + memset(set->set_members, 0, sizeof(set->set_members)); + return set; +} + +character_set *set_copy(const character_set *set) +{ + character_set *set2 = (character_set*)Malloc(sizeof(*set2)); + memcpy(set2, set, sizeof(*set2)); + return set2; +} + +void set_free(character_set *set) +{ + Free(set); +} + +int set_is_empty(const character_set *set) +{ + if ((set->set_members[0] & ~1UL) != 0) return 0; + for (size_t i = 1; i < CS_NOF_ELEMS; i++) + if (set->set_members[i] != 0) return 0; + return 1; +} + +int set_is_full(const character_set *set) +{ + if (~(set->set_members[0] | 1UL) != 0) return 0; + for (size_t i = 1; i < CS_NOF_ELEMS; i++) + if (~set->set_members[i] != 0) return 0; + return 1; +} + +int set_has_char(const character_set *set, char c) +{ + if (set->set_members[c / CS_BITS_PER_ELEM] & 1UL << c % CS_BITS_PER_ELEM) + return 1; + else return 0; +} + +void set_add_char(character_set *set, char c) +{ + set->set_members[c / CS_BITS_PER_ELEM] |= 1UL << c % CS_BITS_PER_ELEM; +} + +void set_remove_char(character_set *set, char c) +{ + set->set_members[c / CS_BITS_PER_ELEM] &= ~(1UL << c % CS_BITS_PER_ELEM); +} + +int set_has_range(const character_set *set, char lower, char upper) +{ + for (size_t i = lower; i <= (unsigned char)upper; i++) + if (set->set_members[i / CS_BITS_PER_ELEM] & 1UL << i % CS_BITS_PER_ELEM) + return 1; + return 0; +} + +void set_add_range(character_set *set, char lower, char upper) +{ + for (size_t i = lower; i <= (unsigned char)upper; i++) + set->set_members[i / CS_BITS_PER_ELEM] |= 1UL << i % CS_BITS_PER_ELEM; +} + +int set_has_intersect(const character_set *set1, const character_set *set2) +{ + for (size_t i = 0; i < CS_NOF_ELEMS; i++) + if (set1->set_members[i] & set2->set_members[i]) return 1; + return 0; +} + +void set_join(character_set *dst, const character_set *src) +{ + for (size_t i = 0; i < CS_NOF_ELEMS; i++) + dst->set_members[i] |= src->set_members[i]; +} + +void set_negate(character_set *set) +{ + for (size_t i = 0; i < CS_NOF_ELEMS; i++) + set->set_members[i] = ~set->set_members[i]; +} + +void set_report_duplicates(const character_set *set1, + const character_set *set2) +{ + for (unsigned char i = 0; i <= 127; ) { + for (i++; i <= 127; i++) + if (set_has_char(set2, i) && set_has_char(set1, i)) break; + if (i > 127) break; + char lower = i; + for (i++; i <= 127; i++) + if (!set_has_char(set2, i) || !set_has_char(set1, i)) break; + char upper = i - 1; + if (lower < upper) { + char *range_str = print_range(lower, upper); + TTCN_pattern_warning("Duplicate range `%s' in the character set.", + range_str); + Free(range_str); + } else { + char *char_str = print_character(lower); + if(lower == '\r' ){ + TTCN_pattern_warning("Duplicate character `%s' in the character " + "set. Please note the \\n includes the \\r implicitly. " + "Use \\q{0,0,0,10} if you would like to match the LF only.", char_str); + } else { + TTCN_pattern_warning("Duplicate character `%s' in the character " + "set.", char_str); + } + Free(char_str); + } + } +} + +static char *append_posix_body(char *set_body, const character_set *set) +{ + for (unsigned char i = 0; i <= 127; ) { + for (i++; i <= 127; i++) if (set_has_char(set, i)) break; + if (i > 127) break; + char lower = i; + set_body = mputc(set_body, lower); + for (i++; i <= 127; i++) if (!set_has_char(set, i)) break; + char upper = i - 1; + if (lower < upper) { + if (lower + 1 < upper) set_body = mputc(set_body, '-'); + set_body = mputc(set_body, upper); + } + } + return set_body; +} + +static char *generate_posix_body(character_set *set) +{ + int has_caret; + if (set_has_char(set, '^') && !(set_has_char(set, '^' - 1) && + set_has_char(set, '^' + 1))) { + set_remove_char(set, '^'); + has_caret = 1; + } else has_caret = 0; + int has_dash; + if (set_has_char(set, '-') && !(set_has_char(set, '-' - 1) && + set_has_char(set, '-' + 1))) { + set_remove_char(set, '-'); + has_dash = 1; + } else has_dash = 0; + int has_rsbrkt; + if (set_has_char(set, ']') && !(set_has_char(set, ']' - 1) && + set_has_char(set, ']' + 1))) { + set_remove_char(set, ']'); + has_rsbrkt = 1; + } else has_rsbrkt = 0; + char *set_body = memptystr(); + if (set_is_empty(set) && !has_rsbrkt) { + /* the `-' must precede the `^' */ + if (has_dash) set_body = mputc(set_body, '-'); + if (has_caret) set_body = mputc(set_body, '^'); + } else { + /* order: ']', others, '^', '-' */ + if (has_rsbrkt) set_body = mputc(set_body, ']'); + set_body = append_posix_body(set_body, set); + if (has_caret) set_body = mputc(set_body, '^'); + if (has_dash) set_body = mputc(set_body, '-'); + } + return set_body; +} + +static char *generate_posix_body_compl(character_set *set) +{ + set_negate(set); + int has_dash; + if (set_has_char(set, '-') && !(set_has_char(set, '-' - 1) && + set_has_char(set, '-' + 1))) { + set_remove_char(set, '-'); + has_dash = 1; + } else has_dash = 0; + int has_rsbrkt; + if (set_has_char(set, ']') && !(set_has_char(set, ']' - 1) && + set_has_char(set, ']' + 1))) { + set_remove_char(set, ']'); + has_rsbrkt = 1; + } else has_rsbrkt = 0; + char *set_body = mcopystr("^"); + /* order: ']', others, '-' */ + if (has_rsbrkt) set_body = mputc(set_body, ']'); + set_body = append_posix_body(set_body, set); + if (has_dash) set_body = mputc(set_body, '-'); + return set_body; +} + +char *set_generate_posix(const character_set *set) +{ + /* a full set can only be represented in this way: */ + if (set_is_full(set)) return mcopystr("."); + character_set *tempset = set_copy(set); + char *set_body = generate_posix_body(tempset); + set_free(tempset); + char *posix_str; + if (set_body[0] == '\0') { + Free(set_body); + TTCN_pattern_error("Internal error: empty POSIX set."); + return NULL; + } + /* do not use the set notation in POSIX if the set contains only one + * character */ + if (set_body[1] == '\0') posix_str = translate_character(set_body[0]); + else { + /* create the complemented version of the same set */ + tempset = set_copy(set); + char *compl_body = generate_posix_body_compl(tempset); + set_free(tempset); + if (compl_body[0] == '\0') { + Free(set_body); + Free(compl_body); + TTCN_pattern_error("Internal error: empty complemented POSIX set."); + return NULL; + } + /* use the complemented form in the POSIX equivalent if it is the shorter + * one */ + if (mstrlen(compl_body) < mstrlen(set_body)) + posix_str = mprintf("[%s]", compl_body); + else posix_str = mprintf("[%s]", set_body); + Free(compl_body); + } + Free(set_body); + return posix_str; +} + +void yyprint(FILE *file, int type, const YYSTYPE& value) +{ + switch (type) { + case TOK_Char: + fprintf(file, "'%c'", value.c); + break; + case TOK_Digit: case TOK_Number: + fprintf(file, "'%lu'", value.u); + break; + default: + break; + } +} + diff --git a/common/pattern_uni.y b/common/pattern_uni.y new file mode 100644 index 0000000..1d33ad7 --- /dev/null +++ b/common/pattern_uni.y @@ -0,0 +1,653 @@ +/****************************************************************************** + * 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 + ******************************************************************************/ + +/** + * Based on pattern_p.y + */ + +%{ + +/********************************************************************* + * C(++) declarations + *********************************************************************/ + +#include +#include +#include + +#if defined(__CYGWIN__) && defined(__clang__) +/* Cygwin's clang 3.0 has its own limits.h, which does not bring in + the system's limits.h unless we define this macro: */ +#define __STDC_HOSTED__ 1 +#define _GCC_NEXT_LIMITS_H +#endif +#include + +#include +#if !defined(RE_DUP_MAX) +/* RE_DUP_MAX is defined in limits.h or regex.h, except on Cygwin 1.5 */ +# include +#endif + +#include "memory.h" +#include "pattern.hh" + +#include "Quadruple.hh" + + union YYSTYPE; +/* defined in lexer c-file: */ + + extern int pattern_yylex(); + inline int pattern_unilex() { return pattern_yylex(); } + extern void init_pattern_yylex(YYSTYPE*); + struct yy_buffer_state; + extern yy_buffer_state* pattern_yy_scan_string(const char*); + extern void pattern_yy_delete_buffer(yy_buffer_state*); + extern unsigned int get_nof_parentheses(); + +/* defined in this file: */ + + /** The converted regexp. */ + static char *ret_val; + /** The parser error reporting function. */ + static void pattern_unierror(const char *error_str); + + static int user_groups; + +#define YYERROR_VERBOSE + +static void yyprint(FILE *file, int type, const YYSTYPE& value); +#define YYPRINT(f,t,v) yyprint(f,t,v) + +%} + +/********************************************************************* + * Bison declarations + *********************************************************************/ + +%name-prefix="pattern_uni" +%output="pattern_uni.cc" +%defines +%verbose +%expect 0 +%start Pattern +%debug + +/********************************************************************* + * The union-type + * Must be kept in sync with the one in pattern_p.y ! + *********************************************************************/ + +%union { + int b; /* boolean */ + char c; /* single character */ + char *s; /* character string */ + unsigned long int u; /* unsigned integer */ + struct character_set *set; // used by nonterminals in pattern_p.y + + union { + unsigned int value; +#if defined(__sparc__) || defined(__sparc) + struct { + unsigned char group; + unsigned char plane; + unsigned char row; + unsigned char cell; + } comp; +#else + struct { + unsigned char cell; + unsigned char row; + unsigned char plane; + unsigned char group; + } comp; +#endif + } q; // single universal char, used by nonterminals in pattern_uni.y + class QuadSet* qset; // used by nonterminals in pattern_uni.y +} + +/********************************************************************* + * Tokens + *********************************************************************/ + +%token TOK_Char "" +%token TOK_Number "" +%token TOK_Digit "" + +/********************************************************************* + * Keywords + *********************************************************************/ + +%token KW_BS_q "\\q" +%token KW_BS_d "\\d" +%token KW_BS_w "\\w" +%token KW_BS_t "\\t" +%token KW_BS_n "\\n" +%token KW_BS_r "\\r" +%token KW_BS_s "\\s" +%token KW_BS_b "\\b" + +%token KW_Group_Begin "(" +%token KW_Group_End ")" +%token KW_Set_Begin "[" +%token KW_Set_Begin_Neg "[^" +%token KW_Set_Begin_Rsbrkt "[]" +%token KW_Set_Begin_Neg_Rsbrkt "[^]" +%token KW_Set_End "]" +%token KW_Set_Dash_End "-]" + +/********************************************************************* + * semantic types of nonterminals + *********************************************************************/ + +%type RE_Set_Begin RE_Set_Begin_Rsbrkt RE_Set_End +%type RE_Set_Range_Char RE_Quadruple +%type RE_Body RE_Elems RE_Alter_Elem RE_Concat_Elem + RE_Multiply_Elem RE_Multiply_Statement RE_Group + RE_OneCharPos +%type RE_Set RE_Set_Body RE_Set_Elem RE_Set_NoRange_Char + +/********************************************************************* + * Destructors + *********************************************************************/ + +%destructor { Free($$); } +RE_Alter_Elem +RE_Body +RE_Concat_Elem +RE_Elems +RE_Group +RE_Multiply_Elem +RE_Multiply_Statement +RE_OneCharPos + +%destructor { delete $$; } +RE_Set +RE_Set_Body +RE_Set_Elem +RE_Set_NoRange_Char + +%% + +/********************************************************************* + * Grammar + *********************************************************************/ + +Pattern: + RE_Body {ret_val=$1;} +; + +RE_Body: + /* empty */ + { + $$ = mcopystr("^$"); + } +| RE_Elems + { + if ($1 != NULL) { + $$ = mprintf("^%s$", $1); + Free($1); + } else $$ = mcopystr("^$"); + } +; + +RE_Elems: + RE_Alter_Elem { $$ = $1; } +| RE_Elems '|' RE_Alter_Elem + { + unsigned int nof_pars = get_nof_parentheses() + (yychar==KW_Group_End ? 1 : 0); + if ($3 != NULL) { + if ($1 != NULL) $$ = mputprintf($1, nof_pars ? "|%s" : "$|^%s", $3); + else $$ = mprintf( nof_pars ? "()|%s" : "()$|^%s" , $3); + Free($3); + } else { + if ($1 != NULL) $$ = mputstr($1, nof_pars ? "|()" : "$|^()"); + else $$ = NULL; + } + } +; + +RE_Alter_Elem: + RE_Concat_Elem { $$ = $1; } +| RE_Alter_Elem RE_Concat_Elem + { + $$ = mputstr($1, $2); + Free($2); + } +; + +RE_Concat_Elem: + RE_Multiply_Elem {$$=$1;} +| RE_Multiply_Elem RE_Multiply_Statement + { + if ($1 != NULL && $2 != NULL) { + $$ = mputstr($1, $2); + Free($2); + } else { + Free($1); + Free($2); + $$ = NULL; + } + } +| '*' {$$=mcopystr("(........)*");} +; + +RE_Multiply_Elem: + RE_Group {$$=$1;} +| RE_OneCharPos {$$=$1;} +; + +RE_Group: + KW_Group_Begin KW_Group_End + { + user_groups++; + $$ = mcopystr("<)"); + } +| KW_Group_Begin RE_Elems KW_Group_End + { + user_groups++; + if ($2 != NULL) { + $$ = mprintf("<%s)", $2); + Free($2); + } else { + $$ = mcopystr("<)"); + } + } +; + +RE_Multiply_Statement: + '+' + { + $$ = mcopystr("+"); + } +| '#' '(' ',' ')' + { + $$ = mcopystr("*"); + } +| '#' TOK_Digit + { + if ($2 == 0) { + TTCN_pattern_warning("The number of repetitions is zero: `#0'."); + $$ = NULL; + } else if ($2 == 1) $$ = memptystr(); + else { + if ($2 > 9) TTCN_pattern_warning("Internal error: Invalid number of " + "repetitions: `#%lu'.", $2); + $$ = mprintf("{%lu}", $2); + } + } +| '#' '(' TOK_Number ')' + { + if ($3 == 0) { + TTCN_pattern_warning("The number of repetitions is zero: `#(0)'."); + $$ = NULL; + } else if ($3 == 1) $$ = memptystr(); + else { +#ifdef RE_DUP_MAX + if ($3 > RE_DUP_MAX) TTCN_pattern_warning("The number of repetitions in " + "`#(%lu)' exceeds the limit allowed by this system (%d).", $3, + RE_DUP_MAX); +#endif + $$ = mprintf("{%lu}", $3); + } + } +| '#' '(' TOK_Number ',' TOK_Number ')' + { +#ifdef RE_DUP_MAX + if ($3 > RE_DUP_MAX) TTCN_pattern_warning("The minimum number of " + "repetitions in `#(%lu,%lu)' exceeds the limit allowed by this system " + "(%d).", $3, $5, RE_DUP_MAX); + if ($5 > RE_DUP_MAX) TTCN_pattern_warning("The maximum number of " + "repetitions in `#(%lu,%lu)' exceeds the limit allowed by this system " + "(%d).", $3, $5, RE_DUP_MAX); +#endif + if ($3 > $5) TTCN_pattern_error("The lower bound is higher than the upper " + "bound in the number of repetitions: `#(%lu,%lu)'.", $3, $5); + if ($3 == $5) { + if ($3 == 0) { + TTCN_pattern_warning("The number of repetitions is zero: `#(0,0)'."); + $$ = NULL; + } else if ($3 == 1) $$ = memptystr(); + else { + $$ = mprintf("{%lu}", $3); + } + } else { + + if ($3 == 0 && $5 == 1) $$ = mcopystr("?"); + else $$ = mprintf("{%lu,%lu}", $3, $5); + + } + } +| '#' '(' ',' TOK_Number ')' + { + if ($4 == 0) { + TTCN_pattern_warning("The number of repetitions is zero: `#(,0)'."); + $$ = NULL; + } else { +#ifdef RE_DUP_MAX + if ($4 > RE_DUP_MAX) TTCN_pattern_warning("The maximum number of " + "repetitions in `#(,%lu)' exceeds the limit allowed by this system " + "(%d).", $4, RE_DUP_MAX); +#endif + + if ($4 == 1) $$ = mcopystr("?"); + else $$ = mprintf("{0,%lu}", $4); + + } + } +| '#' '(' TOK_Number ',' ')' + { + if ($3 == 0) $$ = mcopystr("*"); + else { +#ifdef RE_DUP_MAX + if ($3 > RE_DUP_MAX) TTCN_pattern_warning("The minimum number of " + "repetitions in `#(%lu,)' exceeds the limit allowed by this system " + "(%d).", $3, RE_DUP_MAX); +#endif + + if ($3 == 1) $$ = mcopystr("+"); + else $$ = mprintf("{%lu,}", $3); + + } + } +; + +RE_OneCharPos: + '?' {$$=mcopystr("(........)");} +| KW_BS_d {$$=mcopystr("(AAAAAAD[A-J])");} +| KW_BS_w {$$=mcopystr("(AAAAAAD[A-J]|AAAAAA(E[B-P]|F[A-K])|AAAAAA(G[B-P]|H[A-K]))");} +| KW_BS_t {$$=mcopystr("AAAAAAAJ");} +| KW_BS_n {$$=mcopystr("(AAAAAAA[K-N])");} +| KW_BS_r {$$=mcopystr("AAAAAAAN");} +| KW_BS_s {$$=mcopystr("(AAAAAAA[J-N]|AAAAAACA)");} +| KW_BS_b + { + TTCN_pattern_warning("Metacharacter `\\b' is not supported yet."); + $$ = NULL; + } +| TOK_Char + { + unsigned char c = $1; + if ($1 <= 0) TTCN_pattern_error("Character with code %u " + "(0x%02x) cannot be used in a pattern for type charstring.", $1, $1); + $$ = Quad::get_hexrepr(c); + } +| RE_Quadruple + { + $$ = Quad::get_hexrepr($1.value); + } +| RE_Set + { + if ($1->is_empty()) { + TTCN_pattern_error("Empty character set."); + $$ = NULL; + } else + $$ = $1->generate_posix(); + delete $1; + } +; + +RE_Set: + /* RE_Set_Begin is 1 for "[^", 0 for "[" + * RE_Set_Begin_Rsbrkt is 1 for "[^]", 0 for "[]" + * RE_Set_End is 1 for "-]", 0 for "]" + */ + RE_Set_Begin RE_Set_Body RE_Set_End + { + if ($2 != NULL) + $$ = $2; + else + $$ = new QuadSet(); + if ($3 && !$$->add(new Quad('-'))) + TTCN_pattern_warning("Duplicate character `-' in the character set."); + if ($1) + $$->set_negate(true); + } +| RE_Set_Begin '-' RE_Set_Body RE_Set_End + { + if ($3 != NULL) + $$ = $3; + else + $$ = new QuadSet(); + if (!$$->add(new Quad('-'))) + TTCN_pattern_warning("Duplicate character `-' in the character set."); + if ($1) + $$->set_negate(true); + } +| RE_Set_Begin_Rsbrkt RE_Set_Body RE_Set_End + { + if ($2 != NULL) + $$ = $2; + else + $$ = new QuadSet(); + if (!$$->add(new Quad(']'))) + TTCN_pattern_warning("Duplicate character `]' in the character set."); + if ($3 && !$$->add(new Quad('-'))) + TTCN_pattern_warning("Duplicate character `-' in the character set."); + if ($1) + $$->set_negate(true); + } +| RE_Set_Begin_Rsbrkt '-' RE_Set_Range_Char RE_Set_Body RE_Set_End + { + if ($4 != NULL) + $$ = $4; + else + $$ = new QuadSet(); + if ((unsigned int)']' > $3.value) { + TTCN_pattern_error("Invalid range in the character set: the " + "character code of the lower bound (%u) is higher than that of the " + "upper bound (%u).", ']', (unsigned int)$3.value); + } + $$->add(new QuadInterval(Quad(']'), Quad($3.value))); + if ($5) { + if (!$$->add(new Quad('-'))) + TTCN_pattern_warning("Duplicate character `-' in the character set."); + } + if ($1) + $$->set_negate(true); + } +; + +RE_Set_Begin: + KW_Set_Begin { $$ = 0; } +| KW_Set_Begin_Neg { $$ = 1; } +; + +RE_Set_Begin_Rsbrkt: + KW_Set_Begin_Rsbrkt { $$ = 0; } +| KW_Set_Begin_Neg_Rsbrkt { $$ = 1; } +; + +RE_Set_End: + KW_Set_End { $$ = 0; } +| KW_Set_Dash_End { $$ = 1; } +; + +RE_Set_Body: + /* empty */ { $$ = NULL; } +| RE_Set_Body RE_Set_Elem + { + if ($1 != NULL) { + $$ = $1; + $$->join($2); + delete($2); + } else + $$ = $2; + } +; + +RE_Set_Elem: + RE_Set_Range_Char + { + $$ = new QuadSet(); + $$->add(new Quad($1.value)); + } +| RE_Set_NoRange_Char { $$ = $1; } +| RE_Set_Range_Char '-' RE_Set_Range_Char + { + if ($1.value > $3.value) { + TTCN_pattern_error("Invalid range in the character set: the " + "character code of the lower bound (%u) is higher than that of the " + "upper bound (%u).", (unsigned int)$1.value, (unsigned int)$3.value); + } + $$ = new QuadSet(); + $$->add(new QuadInterval(Quad($1.value), Quad($3.value))); + } +; + +RE_Set_Range_Char: + KW_BS_t { $$.value = '\t'; } +| KW_BS_r { $$.value = '\r'; } +| TOK_Char + { + if ($1 <= 0) TTCN_pattern_error("Character with code %u " + "(0x%02x) cannot be used in a pattern for type charstring.", $1, $1); + $$.value = $1; + } +| RE_Quadruple { $$.value = $1.value; } +; + +RE_Set_NoRange_Char: + KW_BS_d + { + $$ = new QuadSet(); + $$->add(new QuadInterval(Quad('0'), Quad('9'))); + } +| KW_BS_w + { + $$ = new QuadSet(); + $$->add(new QuadInterval(Quad('0'), Quad('9'))); + $$->add(new QuadInterval(Quad('A'), Quad('Z'))); + $$->add(new QuadInterval(Quad('a'), Quad('z'))); + } +| KW_BS_n + { + $$ = new QuadSet(); + $$->add(new QuadInterval(Quad('\n'), Quad('\r'))); + } +| KW_BS_s + { + $$ = new QuadSet(); + $$->add(new QuadInterval(Quad('\t'), Quad('\r'))); + $$->add(new Quad(' ')); + } +| KW_BS_b + { + $$ = new QuadSet(); + TTCN_pattern_error("Metacharacter `\\b' does not make any sense in a " + "character set."); + } +; + +RE_Quadruple: + KW_BS_q '{' TOK_Number ',' TOK_Number ',' TOK_Number ',' TOK_Number '}' + { + if ($3 > 127) TTCN_pattern_error("The first number (group) of quadruple " + "`\\q{%lu,%lu,%lu,%lu}' is too large. It should be in the range 0..127 " + "instead of %lu.", $3, $5, $7, $9, $3); + if ($5 > 255) TTCN_pattern_error("The second number (plane) of quadruple " + "`\\q{%lu,%lu,%lu,%lu}' is too large. It should be in the range 0..255 " + "instead of %lu.", $3, $5, $7, $9, $5); + if ($7 > 255) TTCN_pattern_error("The third number (row) of quadruple " + "`\\q{%lu,%lu,%lu,%lu}' is too large. It should be in the range 0..255 " + "instead of %lu.", $3, $5, $7, $9, $7); + if ($9 > 255) TTCN_pattern_error("The fourth number (cell) of quadruple " + "`\\q{%lu,%lu,%lu,%lu}' is too large. It should be in the range 0..255 " + "instead of %lu.", $3, $5, $7, $9, $9); + if ($3 == 0 && $5 == 0 && $7 == 0 && $9 == 0) TTCN_pattern_error("Zero " + "character (i.e. quadruple `\\q{0,0,0,0}') is not supported in a " + "pattern for type universal charstring."); + $$.comp.group = $3; + $$.comp.plane = $5; + $$.comp.row = $7; + $$.comp.cell = $9; + } +; + +%% + +/********************************************************************* + * Interface + *********************************************************************/ + +char* TTCN_pattern_to_regexp_uni(const char* p_pattern, int** groups) +{ + /* if you want to debug */ + //pattern_unidebug=1; + + ret_val=NULL; + user_groups = 0; + + yy_buffer_state *flex_buffer = pattern_yy_scan_string(p_pattern); + if(flex_buffer == NULL) { + TTCN_pattern_error("Flex buffer creation failed."); + return NULL; + } + init_pattern_yylex(&yylval); + if(pattern_uniparse()) { + Free(ret_val); + ret_val=NULL; + } + pattern_yy_delete_buffer(flex_buffer); + + // needed by regexp to find user specified groups + if (user_groups && groups) { + *groups = (int*)Malloc(sizeof(int) * (user_groups + 1)); + (*groups)[0] = user_groups; + + int par = -1, index = 1; + for (size_t i = 0; i < strlen(ret_val); i++) { + if (ret_val[i] == '(') { + par++; + } + if (ret_val[i] == '<') { + ret_val[i] = '('; + par++; + (*groups)[index++] = par; + } + } + } else if (groups) + *groups = (int*)0; + + return ret_val; +} + +// Backwards compatibility shim +char* TTCN_pattern_to_regexp_uni(const char* p_pattern, int ere, int** /*groups*/) +{ + TTCN_pattern_warning("TTCN_pattern_to_regexp_uni" + "(const char* p_pattern, int ere, int** groups) is deprecated"); + if (ere != 1) TTCN_pattern_error( + "BRE is not supported for TTCN_pattern_to_regexp_uni"); + return TTCN_pattern_to_regexp(p_pattern); +} + + +/********************************************************************* + * Static functions + *********************************************************************/ + +void pattern_unierror(const char *error_str) +{ + TTCN_pattern_error("%s", error_str); +} + +void yyprint(FILE *file, int type, const YYSTYPE& value) +{ + switch (type) { + case TOK_Char: + fprintf(file, "'%c'", value.c); + break; + case TOK_Digit: case TOK_Number: + fprintf(file, "'%lu'", value.u); + break; + default: + break; + } +} + diff --git a/common/platform.h b/common/platform.h new file mode 100644 index 0000000..cc016fe --- /dev/null +++ b/common/platform.h @@ -0,0 +1,30 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef PLATFORM_H_ +#define PLATFORM_H_ + +#include + +/* Create a unified alias for socklen_t */ + +#if defined(SOLARIS) +/* Has no socklen_t at all, man page claims to use size_t. However, size_t + * 1. is slightly broken, see + * http://portabilityblog.com/blog/archives/7-socklen_t-confusion.html + * 2. is used _only_ if _XPG4_2 is defined. + * Since TITAN does not define _XPG4_2, the correct socklen_type is int. */ +typedef int socklen_type; +#elif defined(WIN32) +/* Cygwin has socklen_t which is a typedef to int */ +typedef socklen_t socklen_type; +#else +/* Modern socklen_t is typedef unsigned int32 */ +typedef socklen_t socklen_type; +#endif /* defined... */ + +#endif /* PLATFORM_H_ */ diff --git a/common/static_check.h b/common/static_check.h new file mode 100644 index 0000000..40b8117 --- /dev/null +++ b/common/static_check.h @@ -0,0 +1,26 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef STATIC_CHECK_HH +#define STATIC_CHECK_HH + +#ifdef __cplusplus + +template struct CompileTimeError; +template<> struct CompileTimeError {}; // false never defined + +#define STATIC_ASSERT(expr) CompileTimeError<(expr) != 0>() + +#else + +#define STATIC_ASSERT(x) do { enum { assert_static_ = 1/(x) }; } while(0) + +#endif + +#define ENSURE_EQUAL(x, y) STATIC_ASSERT((int)(x) == (int)(y)); + +#endif diff --git a/common/ttcn3float.hh b/common/ttcn3float.hh new file mode 100644 index 0000000..9e8f560 --- /dev/null +++ b/common/ttcn3float.hh @@ -0,0 +1,132 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef TTCN3FLOAT_HH_ +#define TTCN3FLOAT_HH_ + +#include + +#ifndef signbit +// Probably Solaris. +// Thankfully, IEEE Std 1003.1, 2004 Edition says that signbit is a macro, +// hence it's safe to use ifdef. + +#ifdef __sparc +// Big endian + +inline int signbitfunc(double d) +{ + return *((unsigned char*)&d) & 0x80; +} + +#else +// Probably Intel, assume little endian +inline int signbitfunc(double d) +{ + return ((unsigned char*)&d)[sizeof(double)-1] & 0x80; +} + +#endif + +#define signbit(d) signbitfunc(d) + +#endif // def signbit + +/** A class which behaves almost, but not quite, entirely unlike + * a floating-point value. + * + * It is used as a member of a union (in Value.hh); + * it MUST NOT have a constructor. + */ +struct ttcn3float { + /// Implicit conversion + operator double() const { return value; } + + /// Assignment from a proper double + const ttcn3float& operator=(double d) { + value = d; + return *this; + } + + /// Address-of, for scanf + double* operator&() { return &value; } + + const ttcn3float& operator+=(double d) { + value += d; + return *this; + } + + const ttcn3float& operator-=(double d) { + value -= d; + return *this; + } + + const ttcn3float& operator*=(double d) { + value *= d; + return *this; + } + + const ttcn3float& operator/=(double d) { + value /= d; + return *this; + } + + bool operator<(double d) const { + if (isnan(value)) { + return false; // TTCN-3 special: NaN is bigger than anything except NaN + } + else if (isnan(d)) { + return true; // TTCN-3 special: NaN is bigger than anything except NaN + } + else if (value==0.0 && d==0.0) { // does not distinguish -0.0 + return signbit(value) && !signbit(d); // value negative, d positive + } + else { // finally, the sensible behavior + return value < d; + } + } + + bool operator>(double d) const { + if (isnan(value)) { + return true; // TTCN-3 special: NaN is bigger than anything except NaN + } + else if (isnan(d)) { + return false; // TTCN-3 special: NaN is bigger than anything except NaN + } + else if (value==0.0 && d==0.0) { // does not distinguish -0.0 + return !signbit(value) && signbit(d); // value positive, d negative + } + else { // finally, the sensible behavior + return value > d; + } + } + + bool operator==(double d) const { + if (isnan(value)) { + return !!isnan(d); // TTCN-3 special: NaN is bigger than anything except NaN + } + else if (isnan(d)) { + return false; + } + else if (value==0.0 && d==0.0) { // does not distinguish -0.0 + return signbit(value) == signbit(d); + } + else { // finally, the sensible behavior + return value == d; + } + } +public: + double value; +}; + +/** Replacement for a user-defined constructor that ttcn3float can't have */ +inline ttcn3float make_ttcn3float(double f) { + ttcn3float retval = { f }; + return retval; +} + +#endif /* TTCN3FLOAT_HH_ */ diff --git a/common/usage_stats.cc b/common/usage_stats.cc new file mode 100644 index 0000000..c195d84 --- /dev/null +++ b/common/usage_stats.cc @@ -0,0 +1,306 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "usage_stats.hh" + +#ifdef MINGW +# include +# include +#else +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SA struct sockaddr +#define MAXLINE 4096 +#define MAXSUB 2000 + +#define LISTENQ 1024 + +std::string UsageData::id; +std::string UsageData::host; +std::string UsageData::platform; + +#ifdef sun +extern int gethostname( char *name, int namelen ); +#endif + +static int countDots (const char *name ) +{ + int n; + for (n=0; *name; ++name) if (*name=='.') ++n; + return(n); +} + +std::string gethostnameFullyQualified ( void ) +{ + char host[774]; + struct hostent *hp; + char *fqname=NULL; + int nd; + host[0] = 0; + + if (-1 == gethostname(host, sizeof(host))) { + //perror("warning - getting local hostname"); + strcpy(host,"localhost"); + } + fqname = host; + nd = countDots(fqname); + + hp = gethostbyname(host); + if (!hp) { + //fprintf(stderr, "warning - can't gethostbyname(%s): %s\n",host, hstrerror(h_errno)); + } + else { + char **nm; + if (nd <= countDots(hp->h_name)) { + fqname = const_cast(hp->h_name); + nd = countDots(fqname); + } + + for (nm = hp->h_aliases; *nm; ++nm) { + int d = countDots(*nm); + if (d > nd) {fqname = *nm; nd=d;} + } + } + + if (2 > nd) { + /* still need to find a domain, look through the usual suspects: + * LOCALDOMAIN env variable + * domain defn from /etc/resolv.conf + * /etc/defaultdomain (sun only?) + */ + FILE *fp = NULL; + char domain[1024]; + char *e = getenv("LOCALDOMAIN"); + if (e) strcpy(domain, e); + else domain[0] = 0; + + if( !domain[0] && NULL != (fp=fopen("/etc/resolv.conf","r")) ) { + nd = 0; + while( fgets(domain, sizeof(domain), fp) ) { + if( 0==strncmp("domain ",domain,7) ) { + nd = strlen(domain) - 7; + memmove(domain, domain+7, nd); + } + } + domain[nd] = 0; /* nul terminate (or reset empty) */ + fclose(fp); + } + + if( !domain[0] && NULL != (fp=fopen("/etc/defaultdomain","r")) ) { + fgets(domain, sizeof(domain), fp); + fclose(fp); + } + + if( domain[0] ) { + /* trim blanks */ + int first = 0; + nd = strlen(domain) - 1; + while (first <= nd && isspace(domain[first])) ++first; + while (nd > first && isspace(domain[nd])) domain[nd--] = 0; + + if (domain[first]) { + if (fqname != host) strcpy(host,fqname); + if ('.'!=domain[first]) strcat(host,"."); + strcat(host,domain+first); + fqname = host; + } + } + } + return(std::string(fqname)); +} + +UsageData::UsageData() { + +#ifdef MINGW + TCHAR user_name[UNLEN + 1], computer_name[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD buffer_size = sizeof(user_name); + if (GetUserName(user_name, &buffer_size)) id=user_name; + else id="unknown"; + + buffer_size = sizeof(computer_name); + if (GetComputerName(computer_name, &buffer_size)) + host=computer_name; + else host="unknown"; +#else + struct passwd *p; + setpwent(); + p = getpwuid(getuid()); + if (p != NULL) + id = p->pw_name; + else + id="unknown"; + endpwent(); + + host = gethostnameFullyQualified(); + + struct utsname name; + + int result = uname(&name); + if (result >= 0) + platform= std::string(name.sysname) + " " + std::string(name.release) + " " + std::string(name.machine); + else + platform="unknown"; + +#ifdef LINUX + std::string dist; + FILE *fp; + char path[128]; + + fp = popen("lsb_release -a 2>/dev/null", "r"); + if (fp != NULL) { + while (fgets(path, sizeof(path), fp) != NULL) + if (strncmp ("Description",path,11) == 0) dist.append(path); + //printf("\n'%s'\n", dist.c_str()); + pclose(fp); + } + dist.erase(0,12); + platform.append(dist); +#endif + +#endif +} + +UsageData::~UsageData() { + +} + +struct thread_data { + std::string msg; + Sender* sndr; +}; + +void UsageData::sendDataThreaded(std::string msg, Sender* sender) { + thread_data* data = new thread_data; // will be deleted by sendData + data->msg = "id="+ id + "&host=" + host + "&platform=" + platform + "&gccv=" + C_COMPILER_VERSION + "&titanv=" + PRODUCT_NUMBER + "&msg="+ msg + "\r"; + data->sndr = sender; + + pthread_t thread; + pthread_create(&thread, NULL, sendData, data); +} + +void* UsageData::sendData(void* m) { + thread_data* my_data; + my_data = (thread_data*)m; + + if(my_data->sndr) { + my_data->sndr->send(my_data->msg.c_str()); + delete my_data->sndr; + } + + // delete the data after use + delete my_data; + + return NULL; +} + + +//**************** HttpSender ******************* + +ssize_t process_http(int sockfd, const char *host, const char *page, const char *poststr) +{ + char sendline[MAXLINE + 1];//, recvline[MAXLINE + 1]; + ssize_t n = 0; + //printf("\n ##### \n%s\n ##### \n", poststr); + snprintf(sendline, MAXSUB, + "POST %s HTTP/1.0\r\n" + "Host: %s\r\n" + "Content-type: application/x-www-form-urlencoded\r\n" + "Content-length: %lu\r\n\r\n" + "%s", page, host, (unsigned long)strlen(poststr), poststr); + + write(sockfd, sendline, strlen(sendline)); + /*while ((n = read(sockfd, recvline, MAXLINE)) > 0) { + recvline[n] = '\0'; + printf("%s", recvline); + }*/ + return n; +} + +// msg must be in the right format to process! +// id=x&host=y&platform=z&gccv=v&titanv=t&msg=m\r +void HttpSender::send(const char* msg) { + int sockfd; + struct sockaddr_in servaddr, clientaddr; + + char **pptr; + const char *hname = "ttcn.ericsson.se"; + const char *page = "/download/usage_stats/usage_stats.php"; + const char *poststr = msg;//.c_str(); + //******************************************************* + + char str[50]; + struct hostent *hptr; + if ((hptr = gethostbyname(hname)) == NULL) { + /*fprintf(stderr, " gethostbyname error for host: %s: %s", + hname, hstrerror(h_errno));*/ + return; + } + //printf("hostname: %s\n", hptr->h_name); + if (hptr->h_addrtype == AF_INET + && (pptr = hptr->h_addr_list) != NULL) { + //printf("address: %s\n", + inet_ntop(hptr->h_addrtype, *pptr, str,sizeof(str)); + } else { + //fprintf(stderr, "Error call inet_ntop \n"); + return; + } + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + memset(&clientaddr, 0, sizeof(clientaddr)); + clientaddr.sin_family = AF_INET; + clientaddr.sin_port = htons(49555); + inet_pton(AF_INET, "0.0.0.0", &clientaddr.sin_addr); + if (bind(sockfd, (SA *) & clientaddr, sizeof(clientaddr)) < 0) { + clientaddr.sin_port = htons(59555); + if (bind(sockfd, (SA *) & clientaddr, sizeof(clientaddr)) < 0) { + clientaddr.sin_port = htons(61555); + if (bind(sockfd, (SA *) & clientaddr, sizeof(clientaddr)) < 0) { + // last ditch effort, use an automatically generated port + clientaddr.sin_port = htons(0); + bind(sockfd, (SA *) & clientaddr, sizeof(clientaddr)); + } + } + } + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(80); + inet_pton(AF_INET, str, &servaddr.sin_addr); + + connect(sockfd, (SA *) & servaddr, sizeof(servaddr)); + + process_http(sockfd, hname, page, poststr); + close(sockfd); +} + +//**************** DNSSender ******************* + +DNSSender::DNSSender() : nameserver("172.31.21.9"), domain("domain.net") { } + +void DNSSender::send(const char* /* msg */) { + //send_over_dns(msg, "TXT", "pass", nameserver, domain); +} + diff --git a/common/usage_stats.hh b/common/usage_stats.hh new file mode 100644 index 0000000..632508b --- /dev/null +++ b/common/usage_stats.hh @@ -0,0 +1,81 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef USAGE_STATS_H_ +#define USAGE_STATS_H_ + +/***************************************************** +// Usage: +// include usage_stats.hh before dbgnew.hh!! +// XYSender sender; // XYSender is a subclass of Sender +// int timeout = 200; // timeout in msec for the data sender thread +// UsageData::getInstance().sendDataThreaded("info", timeout, &sender); + +// Lib requirement: +// for Solaris -lnsl -lsocket -lresolv +// for Linux -lpthread -lrt + +// iodine: use iodine as a library from /etc/dns/iodine/lib/libiodine.a +// or via pipe as an outside process +// uncomment this and the DNSSender::send function +//#include "../etc/dns/iodine/src/iodine.h" +*****************************************************/ + +#include + +#include "version_internal.h" + +class Sender { +public: + Sender() {}; + virtual ~Sender() {}; + virtual void send(const char*) = 0; +}; + +class DNSSender: public Sender { +public: + DNSSender(); + ~DNSSender() {}; + void send(const char*); + +private: + const char* nameserver; + const char* domain; +}; + +class HttpSender: public Sender { +public: + HttpSender() {}; + ~HttpSender() {}; + void send(const char*); +}; + + +class UsageData { +public: + static UsageData& getInstance() + { + static UsageData instance; // Guaranteed to be destroyed. + return instance; // Instantiated on first use. + } + static void sendDataThreaded(std::string msg, Sender* sender); + +private: + + UsageData(); + ~UsageData(); + UsageData(UsageData const&); // Don't Implement + void operator=(UsageData const&); // Don't implement + + static void* sendData(void*); + + static std::string id; + static std::string host; + static std::string platform; +}; + +#endif /* USAGE_STATS_H_ */ diff --git a/common/userinfo.c b/common/userinfo.c new file mode 100644 index 0000000..66db4b9 --- /dev/null +++ b/common/userinfo.c @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include +#include +#ifdef MINGW +# include +# include +#else +# include +#endif + +#include "memory.h" +#include "userinfo.h" + +char *get_user_info(void) +{ + char *ret_val; + time_t t; + const char *current_time; +#ifdef MINGW + TCHAR user_name[UNLEN + 1], computer_name[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD buffer_size = sizeof(user_name); + if (GetUserName(user_name, &buffer_size)) ret_val = mcopystr(user_name); + else ret_val = mcopystr("unknown"); + ret_val = mputc(ret_val, '@'); + buffer_size = sizeof(computer_name); + if (GetComputerName(computer_name, &buffer_size)) + ret_val = mputstr(ret_val, computer_name); + else ret_val = mputstr(ret_val, "unknown"); +#else + struct passwd *p; + char host_name[256]; + setpwent(); + p = getpwuid(getuid()); + if (p != NULL) { + size_t i; + for (i = 0; p->pw_gecos[i] != '\0'; i++) { + if (p->pw_gecos[i] == ',') { + /* Truncating additional info (e.g. phone number) after the full name */ + p->pw_gecos[i] = '\0'; + break; + } + } + ret_val = mprintf("%s (%s", p->pw_gecos, p->pw_name); + } else ret_val = mcopystr("Unknown User (unknown"); + endpwent(); + if (gethostname(host_name, sizeof(host_name))) + ret_val = mputstr(ret_val, "@unknown)"); + else { + host_name[sizeof(host_name) - 1] = '\0'; + ret_val = mputprintf(ret_val, "@%s)", host_name); + } +#endif + t = time(NULL); + current_time = ctime(&t); + ret_val = mputprintf(ret_val, " on %s", current_time); + return ret_val; +} diff --git a/common/userinfo.h b/common/userinfo.h new file mode 100644 index 0000000..80ac1ba --- /dev/null +++ b/common/userinfo.h @@ -0,0 +1,21 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef USERINFO_H +#define USERINFO_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern char *get_user_info(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/common/version.h b/common/version.h new file mode 100644 index 0000000..b6472c0 --- /dev/null +++ b/common/version.h @@ -0,0 +1,149 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef VERSION_H +#define VERSION_H + +/* Version numbers */ +#define TTCN3_MAJOR 5 +#define TTCN3_MINOR 1 +#define TTCN3_PATCHLEVEL 0 +//#define TTCN3_BUILDNUMBER 0 + +/* The aggregated version number must be set manually since some stupid + * 'makedepend' programs cannot calculate arithmetic expressions. + * In official releases: + * TTCN3_VERSION = TTCN3_MAJOR * 10000 + TTCN3_MINOR * 100 + TTCN3_PATCHLEVEL + * In pre-release builds: + * TTCN3_VERSION = TTCN3_MAJOR * 1000000 + TTCN3_MINOR * 10000 + + * TTCN3_PATCHLEVEL * 100 + TTCN3_BUILDNUMBER + */ +#define TTCN3_VERSION 50100 + +/* A monotonically increasing version number. + * An official release is deemed to have the highest possible build number (99) + */ +#ifdef TTCN3_BUILDNUMBER +#define TTCN3_VERSION_MONOTONE TTCN3_VERSION +#else +#define TTCN3_VERSION_MONOTONE (TTCN3_VERSION * 100 + 99) +#endif + + +#if defined (SOLARIS) + #define PLATFORM_STRING "SOLARIS" +#elif defined (SOLARIS8) + #define PLATFORM_STRING "SOLARIS8" +#elif defined (LINUX) + #define PLATFORM_STRING "LINUX" +#elif defined (WIN32) + /* MINGW is defined only if CYGWIN is defined */ + #if defined (MINGW) + #define PLATFORM_STRING "MINGW" + #else + #define PLATFORM_STRING "WIN32" + #endif +#elif defined (FREEBSD) + #define PLATFORM_STRING "FREEBSD" +#elif defined (INTERIX) + #define PLATFORM_STRING "INTERIX" +/* TODO more */ +#endif + + +#ifndef PLATFORM_STRING +/* Just to suppress error later */ + #define PLATFORM_STRING "UNKNOWN" + #error "No supported platform has been defined in the Makefile. The supported ones: SOLARIS, SOLARIS8, LINUX, WIN32" +#endif + +#define STRINGIFY(x) #x +#define STR(x) STRINGIFY(x) + +#if defined(__GNUC__) + + #ifdef __GNUC_PATCHLEVEL__ + #define GCC_PATCHLEVEL_STRING "." STR(__GNUC_PATCHLEVEL__) + #else + /* __GNUC_PATCHLEVEL__ appeared in gcc 3.0 */ + #define GCC_PATCHLEVEL_STRING + #endif + +#ifdef __clang__ + #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100) +#else + #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) +#endif + /* Ignore __GNUC_PATCHLEVEL__ */ +#define COMPILER_VERSION_STRING " GCC: (GNU) " STR(__GNUC__) "." STR(__GNUC_MINOR__) GCC_PATCHLEVEL_STRING + + + static const char titan_[] __attribute__ ((section (".titan"))) = \ + "TITAN: " STR(TTCN3_VERSION) " PLATFORM: " PLATFORM_STRING COMPILER_VERSION_STRING; + +#ifdef __cplusplus + struct reffer { + reffer(const char *); + }; + + /* Prevents the version string from being optimized away */ + static const reffer ref_ver(titan_); +#endif + +#else /* not a GNU compiler */ + +#ifndef __attribute__ +#define __attribute__(arg) +#endif + +#if defined(__SUNPRO_C) + +#define COMPILER_VERSION_STRING " SunPro: " STR(__SUNPRO_C) + +#elif defined(__SUNPRO_CC) + +#define COMPILER_VERSION_STRING " SunPro: " STR(__SUNPRO_CC) + +#pragma ident "TITAN: " STR(TTCN3_VERSION) " PLATFORM: " PLATFORM_STRING COMPILER_VERSION_STRING; + +#else +/* Luft! unknown compiler */ +#endif /* not SunPro */ + +#endif +/* __SUNPRO_CC is an all-in-one value */ + + +#define FN(f,x) requires_ ## f ## _ ## x +#define FIELD_NAME(f,x) FN(f,x) + +#ifdef TITAN_RUNTIME_2 +#define TITAN_RUNTIME_NR 2 +#else +#define TITAN_RUNTIME_NR 1 +#endif + +struct runtime_version { + int FIELD_NAME(major_version, TTCN3_MAJOR); + int FIELD_NAME(minor_version, TTCN3_MINOR); + int FIELD_NAME(patch_level, TTCN3_PATCHLEVEL); + int FIELD_NAME(runtime, TITAN_RUNTIME_NR); +}; + +extern const struct runtime_version current_runtime_version; + +#ifdef __cplusplus +class RuntimeVersionChecker { +public: + RuntimeVersionChecker(int ver_major, int ver_minor, int patch_level, int rt); +}; +#endif + +#undef FIELD_NAME +#undef FN + +#endif diff --git a/common/version.py b/common/version.py new file mode 100644 index 0000000..cc43468 --- /dev/null +++ b/common/version.py @@ -0,0 +1,61 @@ +############################################################################### +# 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 +############################################################################### +import datetime + +from tempfile import mkstemp +from shutil import move +from os import remove, close + +from subprocess import call +from sys import exit + +def getnumberfromfileline(line): + lineasstring = str(line); + numberfromfile = lineasstring[-3:]; + number = int(numberfromfile) + 1; + print number; + if number >= 99: + print 'Number is over the limit: >=99. File is not modified!' + exit(); + return number + + +def replace(file_path): + #Create temp file + fh, abs_path = mkstemp() + new_file = open(abs_path,'w') + old_file = open(file_path) + for line in old_file: + if '#define TTCN3_PATCHLEVEL' in line: + newline = str('#define TTCN3_PATCHLEVEL ') + str(getnumberfromfileline(line)) + str('\n'); + new_file.write(newline); + elif '#define TTCN3_VERSION 30' in line: + number = getnumberfromfileline(line); + if number <= 9: + newline = str('#define TTCN3_VERSION 302') +'0' + str(number) + str('\n'); + else: + newline = str('#define TTCN3_VERSION 302') + str(number) + str('\n'); + new_file.write(newline); + else: + new_file.write(line) + #close temp file + new_file.close() + close(fh) + old_file.close() + #Remove original file + remove(file_path) + #Move new file + move(abs_path, file_path) + +#( d.isoweekday() in range(1, 6) +#d = datetime.datetime.now(); +#if d.isoweekday() == 2 or d.isoweekday() == 4 : +replace ("version.h"); +#call(["git", "commit", "-m 'TTCN3_PATCHLEVEL update'" ,"version.h"]); +# call(["git", "push"]); + diff --git a/common/version_internal.h b/common/version_internal.h new file mode 100644 index 0000000..bc8da1b --- /dev/null +++ b/common/version_internal.h @@ -0,0 +1,257 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef VERSION_INTERNAL_H +#define VERSION_INTERNAL_H + +#include "version.h" + +/* This file contains the macro settings that are not delivered to the user + * in the binary package. */ + +/* Symbolic version string */ +#ifdef TTCN3_BUILDNUMBER +/* pre-release, e.g. "1.6.pre4 build 1" */ +# define GEN_VER2(major, minor, patchlevel, buildnumber) \ + #major "." #minor ".pre" #patchlevel " build " #buildnumber +# define GEN_VER(major, minor, patchlevel, buildnumber) \ + GEN_VER2(major, minor, patchlevel, buildnumber) +# define VERSION_STRING GEN_VER(TTCN3_MAJOR, TTCN3_MINOR, TTCN3_PATCHLEVEL, \ + TTCN3_BUILDNUMBER) +#else +/* stable release, e.g. "1.4.pl3" */ +# define GEN_VER2(major, minor, patchlevel) #major "." #minor ".pl" #patchlevel +# define GEN_VER(major, minor, patchlevel) GEN_VER2(major, minor, patchlevel) +# define VERSION_STRING GEN_VER(TTCN3_MAJOR, TTCN3_MINOR, TTCN3_PATCHLEVEL) +#endif + +/* Product number */ +#define PRODNR_EXECUTOR "CRL 113 200" + +/* Ericsson revision: /m Rnx + * m = TTCN3_MAJOR + * n = TTCN3_MINOR + * x = 'A' + TTCN3_PATCHLEVEL + * Example: 1.4.pl3 = R4D */ + +#define GEN_ERICSSON_SUFFIX2(num) #num +#define GEN_ERICSSON_SUFFIX(num) GEN_ERICSSON_SUFFIX2(num) +#define ERICSSON_SUFFIX GEN_ERICSSON_SUFFIX(TTCN3_MAJOR) + +#define GEN_ERICSSON_NUMBER2(num) #num +#define GEN_ERICSSON_NUMBER(num) GEN_ERICSSON_NUMBER2(num) +#define ERICSSON_NUMBER GEN_ERICSSON_NUMBER(TTCN3_MINOR) + +#if TTCN3_PATCHLEVEL == 0 +#define ERICSSON_LETTER "A" +#elif TTCN3_PATCHLEVEL == 1 +#define ERICSSON_LETTER "B" +#elif TTCN3_PATCHLEVEL == 2 +#define ERICSSON_LETTER "C" +#elif TTCN3_PATCHLEVEL == 3 +#define ERICSSON_LETTER "D" +#elif TTCN3_PATCHLEVEL == 4 +#define ERICSSON_LETTER "E" +#elif TTCN3_PATCHLEVEL == 5 +#define ERICSSON_LETTER "F" +#elif TTCN3_PATCHLEVEL == 6 +#define ERICSSON_LETTER "G" +#elif TTCN3_PATCHLEVEL == 7 +#define ERICSSON_LETTER "H" +#elif TTCN3_PATCHLEVEL == 8 +/* I: forbidden */ +#define ERICSSON_LETTER "J" +#elif TTCN3_PATCHLEVEL == 9 +#define ERICSSON_LETTER "K" +#elif TTCN3_PATCHLEVEL == 10 +#define ERICSSON_LETTER "L" +#elif TTCN3_PATCHLEVEL == 11 +#define ERICSSON_LETTER "M" +#elif TTCN3_PATCHLEVEL == 12 +#define ERICSSON_LETTER "N" +/* O, P, Q, R: forbidden */ +#elif TTCN3_PATCHLEVEL == 13 +#define ERICSSON_LETTER "S" +#elif TTCN3_PATCHLEVEL == 14 +#define ERICSSON_LETTER "T" +#elif TTCN3_PATCHLEVEL == 15 +#define ERICSSON_LETTER "U" +#elif TTCN3_PATCHLEVEL == 16 +#define ERICSSON_LETTER "V" +#elif TTCN3_PATCHLEVEL == 17 +/* W: forbidden */ +#define ERICSSON_LETTER "X" +#elif TTCN3_PATCHLEVEL == 18 +#define ERICSSON_LETTER "Y" +#elif TTCN3_PATCHLEVEL == 19 +#define ERICSSON_LETTER "Z" +#else +#error "Ericsson revision letter is not defined." +#endif + +#ifdef TTCN3_BUILDNUMBER +/* The Ericsson version is suffixed with the build number (at least 2 digits) + * in preliminary releases (like this: "R6E01") */ +# if TTCN3_BUILDNUMBER < 10 +# define ERICSSON_BUILDNUMBER "0" GEN_ERICSSON_NUMBER(TTCN3_BUILDNUMBER) +# else +# define ERICSSON_BUILDNUMBER GEN_ERICSSON_NUMBER(TTCN3_BUILDNUMBER) +# endif +#else +# define ERICSSON_BUILDNUMBER +#endif + +#define ERICSSON_VERSION "/" ERICSSON_SUFFIX " R" ERICSSON_NUMBER ERICSSON_LETTER \ + ERICSSON_BUILDNUMBER + +#define PRODUCT_NUMBER PRODNR_EXECUTOR ERICSSON_VERSION + +/* Version of the C/C++ compiler */ + +#if defined(__GNUC__) + /* the code is compiled with GCC */ +# ifdef __GNUC_PATCHLEVEL__ + /* the patch number is known (version 3.0 or later) */ +# define GEN_COMP_VER2(major, minor, patchlevel) "GCC " #major "." #minor "." #patchlevel +# define GEN_COMP_VER(major, minor, patchlevel) GEN_COMP_VER2(major, minor, patchlevel) +# define C_COMPILER_VERSION GEN_COMP_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +# else + /* the patch number is unknown (version 2.x.?) */ +# define GEN_COMP_VER2(major, minor) "GCC " #major "." #minor ".?" +# define GEN_COMP_VER(major, minor) GEN_COMP_VER2(major, minor) +# define C_COMPILER_VERSION GEN_COMP_VER(__GNUC__, __GNUC_MINOR__) +# endif +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) + /* the code is compiled with Sun Workshop C/C++ compiler */ +# ifdef __SUNPRO_C +# define __SUNPRO_VERSION __SUNPRO_C +# else +# define __SUNPRO_VERSION __SUNPRO_CC +# endif +# if __SUNPRO_VERSION <= 0xfff + /* the version number is in format 0xVRP */ + /* version number (V) */ +# if (__SUNPRO_VERSION & 0xf00) == 0x000 +# define SUNPRO_V "0" +# elif (__SUNPRO_VERSION & 0xf00) == 0x100 +# define SUNPRO_V "1" +# elif (__SUNPRO_VERSION & 0xf00) == 0x200 +# define SUNPRO_V "2" +# elif (__SUNPRO_VERSION & 0xf00) == 0x300 +# define SUNPRO_V "3" +# elif (__SUNPRO_VERSION & 0xf00) == 0x400 +# define SUNPRO_V "4" +# elif (__SUNPRO_VERSION & 0xf00) == 0x500 +# define SUNPRO_V "5" +# elif (__SUNPRO_VERSION & 0xf00) == 0x600 +# define SUNPRO_V "6" +# elif (__SUNPRO_VERSION & 0xf00) == 0x700 +# define SUNPRO_V "7" +# elif (__SUNPRO_VERSION & 0xf00) == 0x800 +# define SUNPRO_V "8" +# elif (__SUNPRO_VERSION & 0xf00) == 0x900 +# define SUNPRO_V "9" +# elif (__SUNPRO_VERSION & 0xf00) == 0xa00 +# define SUNPRO_V "10" +# elif (__SUNPRO_VERSION & 0xf00) == 0xb00 +# define SUNPRO_V "11" +# elif (__SUNPRO_VERSION & 0xf00) == 0xc00 +# define SUNPRO_V "12" +# elif (__SUNPRO_VERSION & 0xf00) == 0xd00 +# define SUNPRO_V "13" +# elif (__SUNPRO_VERSION & 0xf00) == 0xe00 +# define SUNPRO_V "14" +# else +# define SUNPRO_V "15" +# endif + /* release number (R) */ +# if (__SUNPRO_VERSION & 0xf0) == 0x00 +# define SUNPRO_R "0" +# elif (__SUNPRO_VERSION & 0xf0) == 0x10 +# define SUNPRO_R "1" +# elif (__SUNPRO_VERSION & 0xf0) == 0x20 +# define SUNPRO_R "2" +# elif (__SUNPRO_VERSION & 0xf0) == 0x30 +# define SUNPRO_R "3" +# elif (__SUNPRO_VERSION & 0xf0) == 0x40 +# define SUNPRO_R "4" +# elif (__SUNPRO_VERSION & 0xf0) == 0x50 +# define SUNPRO_R "5" +# elif (__SUNPRO_VERSION & 0xf0) == 0x60 +# define SUNPRO_R "6" +# elif (__SUNPRO_VERSION & 0xf0) == 0x70 +# define SUNPRO_R "7" +# elif (__SUNPRO_VERSION & 0xf0) == 0x80 +# define SUNPRO_R "8" +# elif (__SUNPRO_VERSION & 0xf0) == 0x90 +# define SUNPRO_R "9" +# elif (__SUNPRO_VERSION & 0xf0) == 0xa0 +# define SUNPRO_R "10" +# elif (__SUNPRO_VERSION & 0xf0) == 0xb0 +# define SUNPRO_R "11" +# elif (__SUNPRO_VERSION & 0xf0) == 0xc0 +# define SUNPRO_R "12" +# elif (__SUNPRO_VERSION & 0xf0) == 0xd0 +# define SUNPRO_R "13" +# elif (__SUNPRO_VERSION & 0xf0) == 0xe0 +# define SUNPRO_R "14" +# else +# define SUNPRO_R "15" +# endif + /* patch number (P) */ +# if (__SUNPRO_VERSION & 0xf) == 0x0 +# define SUNPRO_P "0" +# elif (__SUNPRO_VERSION & 0xf) == 0x1 +# define SUNPRO_P "1" +# elif (__SUNPRO_VERSION & 0xf) == 0x2 +# define SUNPRO_P "2" +# elif (__SUNPRO_VERSION & 0xf) == 0x3 +# define SUNPRO_P "3" +# elif (__SUNPRO_VERSION & 0xf) == 0x4 +# define SUNPRO_P "4" +# elif (__SUNPRO_VERSION & 0xf) == 0x5 +# define SUNPRO_P "5" +# elif (__SUNPRO_VERSION & 0xf) == 0x6 +# define SUNPRO_P "6" +# elif (__SUNPRO_VERSION & 0xf) == 0x7 +# define SUNPRO_P "7" +# elif (__SUNPRO_VERSION & 0xf) == 0x8 +# define SUNPRO_P "8" +# elif (__SUNPRO_VERSION & 0xf) == 0x9 +# define SUNPRO_P "9" +# elif (__SUNPRO_VERSION & 0xf) == 0xa +# define SUNPRO_P "10" +# elif (__SUNPRO_VERSION & 0xf) == 0xb +# define SUNPRO_P "11" +# elif (__SUNPRO_VERSION & 0xf) == 0xc +# define SUNPRO_P "12" +# elif (__SUNPRO_VERSION & 0xf) == 0xd +# define SUNPRO_P "13" +# elif (__SUNPRO_VERSION & 0xf) == 0xe +# define SUNPRO_P "14" +# else +# define SUNPRO_P "15" +# endif + /* the macro is defined in such an ugly way because the C preprocessor + * cannot stringify the result of an arithmetic expression */ +# define C_COMPILER_VERSION "Sun Workshop Pro " SUNPRO_V "." SUNPRO_R "." SUNPRO_P +# else + /* the version number is in unknown format */ +# define C_COMPILER_VERSION "Sun Workshop Pro unknown version" +# endif +#else + /* the C/C++ compiler is unknown */ +# define C_COMPILER_VERSION "unknown C/C++ compiler" +#endif + +/* Copyright message */ +#define COPYRIGHT_STRING COMMENT_PREFIX "Copyright Ericsson Telecom AB 2000-2014" + +/* For prefixing the above messages. Default value: empty string. */ +#define COMMENT_PREFIX + +#endif diff --git a/compiler2/.gitignore b/compiler2/.gitignore new file mode 100644 index 0000000..93f3d6a --- /dev/null +++ b/compiler2/.gitignore @@ -0,0 +1,9 @@ +*.d +compiler +compiler.exe +ttcn3_makefilegen +ttcn3_makefilegen.exe +tcov2lcov +tcov2lcov.exe +*.a +*.so diff --git a/compiler2/AST.cc b/compiler2/AST.cc new file mode 100644 index 0000000..3f45141 --- /dev/null +++ b/compiler2/AST.cc @@ -0,0 +1,1785 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include +#include +#include + +#include "../common/dbgnew.hh" +#include "AST.hh" +#include "asn1/AST_asn1.hh" +#include "Identifier.hh" +#include "Type.hh" +#include "TypeCompat.hh" +#include "Value.hh" +#include "ustring.hh" +#include "main.hh" +#include "asn1/Object0.hh" +#include "PredefFunc.hh" +#include "../common/version.h" +#include "CodeGenHelper.hh" +#include + +reffer::reffer(const char*) {} + +namespace Common { + + // ================================= + // ===== Modules + // ================================= + + Modules::Modules() + : Node(), mods_v(), mods_m() + { + set_fullname(string('@')); + } + + Modules::~Modules() + { + for(size_t i = 0; i < mods_v.size(); i++) delete mods_v[i]; + mods_v.clear(); + mods_m.clear(); + } + + Modules *Modules::clone() const + { + FATAL_ERROR("Modules::clone()"); + return 0; + } + + void Modules::add_mod(Module *p_mod) + { + if (!p_mod) FATAL_ERROR("NULL parameter: Common::Modules::add_mod()"); + p_mod->set_fullname("@"+p_mod->get_modid().get_dispname()); + p_mod->set_scope_name(p_mod->get_modid().get_dispname()); + mods_v.add(p_mod); + } + + bool Modules::has_mod_withId(const Identifier& p_modid) + { + return mods_m.has_key(p_modid.get_name()); + } + + Module* Modules::get_mod_byId(const Identifier& p_modid) + { + const string& name = p_modid.get_name(); + return mods_m.has_key(name)?mods_m[name]:0; + } + + Assignment* Modules::get_ass_bySRef(Ref_simple *p_ref) + { + if(!p_ref) + FATAL_ERROR("NULL parameter: Common::Modules::get_ass_bySRef()"); + const Identifier *modid=p_ref->get_modid(); + if(modid) { + if(has_mod_withId(*modid)) + return get_mod_byId(*modid)->get_ass_bySRef(p_ref); + else { + p_ref->error("There is no module with identifier `%s'", + modid->get_dispname().c_str()); + return 0; + } + } + else { + p_ref->error("`%s' entity not found in global scope", + p_ref->get_dispname().c_str()); + return 0; + } + } + + void Modules::chk_uniq() + { + for(size_t i = 0; i < mods_v.size(); i++) { + Module *m = mods_v[i]; + const Identifier& id = m->get_modid(); + const string& name = id.get_name(); + if (mods_m.has_key(name)) { + Module *m2 = mods_m[name]; + m->error("A module with identifier `%s' already exists", + id.get_dispname().c_str()); + m2->error("This is the first module with the same name"); + if (m->get_moduletype() == m2->get_moduletype() && + !strcmp(m->get_filename(), m2->get_filename())) { + // the same file was given twice -> drop the entire module + delete m; + mods_v.replace(i, 1); + i--; + } + } else mods_m.add(name, m); + } + } + + void Modules::chk() + { + // first check the uniqueness of module names + chk_uniq(); + // check the import chains + size_t nof_mods = mods_v.size(); + for (size_t i = 0; i < nof_mods; i++) { + Module *m = mods_v[i]; + ReferenceChain refch(m, "While checking import chains"); + vector modules; + m->chk_imp(refch, modules); + modules.clear(); + //clear the reference chain, get a fresh start + refch.reset(); + } + // check the modules + Module::module_set_t checked_modules; + if (nof_top_level_pdus > 0) { + chk_top_level_pdus(); + // do not check ASN.1 modules, but assume they are already checked + for (size_t i = 0; i < nof_mods; i++) { + Module *module = mods_v[i]; + if (module->get_moduletype() == Module::MOD_ASN) + checked_modules.add(module, 0); + } + for (size_t i = 0; i < nof_mods; i++) { + Module *module = mods_v[i]; + if (module->get_moduletype() != Module::MOD_ASN) + module->chk_recursive(checked_modules); + } + } else { + // walk through all modules in bottom-up order + for (size_t i = 0; i < nof_mods; i++) + mods_v[i]->chk_recursive(checked_modules); + } + checked_modules.clear(); + } + + void Modules::chk_top_level_pdus() + { + Location loc(""); + for(size_t i=0; i=pduname.size()) { + loc.error("While searching top-level pdu `%s': " + "Please use the `modulename.identifier' format", + pduname.c_str()); + continue; + } + Module *module=0; + Identifier *pdu_id=0; + { // searching the module + const string& pduname_mod = pduname.substr(0, dotpos); + const string& pduname_id = pduname.substr(dotpos + 1); + { // ASN + Identifier modid(Identifier::ID_ASN, pduname_mod, true); + module = get_mod_byId(modid); + } + if (module && module->get_moduletype() == Module::MOD_ASN) { + pdu_id = new Identifier(Identifier::ID_ASN, pduname_id, true); + goto mod_ok; + } + { // TTCN + Identifier modid(Identifier::ID_TTCN, pduname_mod, true); + module = get_mod_byId(modid); + } + if (module && module->get_moduletype() == Module::MOD_TTCN) { + pdu_id = new Identifier(Identifier::ID_TTCN, pduname_id, true); + goto mod_ok; + } + { // C++ + Identifier modid(Identifier::ID_NAME, pduname_mod, true); + module = get_mod_byId(modid); + } + if(module) { + pdu_id = new Identifier(Identifier::ID_NAME, pduname_id, true); + goto mod_ok; + } + // error - no such module + loc.error("While searching top-level pdu `%s': " + "No module with name `%s'", + pduname.c_str(), pduname_mod.c_str()); + continue; + } + mod_ok: + Assignments *asss=module->get_asss(); + if(asss->has_local_ass_withId(*pdu_id)) { + Assignment *ass=asss->get_local_ass_byId(*pdu_id); + ass->chk(); + } + else { + loc.error("While searching top-level pdu `%s': " + "No assignment with identifier `%s'", + pduname.c_str(), pdu_id->get_dispname().c_str()); + } + delete pdu_id; + } // for top-level pdus + } + + void Modules::write_checksums() + { + fputs("Module name Language MD5 checksum Version\n" + "---------------------------------------------------------------------------\n", stderr); + size_t nof_mods = mods_v.size(); + for (size_t i = 0; i < nof_mods; i++) { + mods_v[i]->write_checksum(); + } + } + + void Modules::generate_code(CodeGenHelper& cgh) + { + Common::Module::rename_default_namespace(); // if needed + /* + The White Rabbit put on his spectacles. + "Where shall I begin, please your Majesty ?" he asked. + "Begin at the beginning,", the King said, very gravely, "and go on + till you come to the end: then stop." + -- Lewis Carroll + */ + for (size_t i = 0; i < mods_v.size(); i++) { + mods_v[i]->generate_code(cgh); + if (tcov_file_name && in_tcov_files(mods_v[i]->get_filename())) { + Free(effective_module_lines); + Free(effective_module_functions); + effective_module_lines = effective_module_functions = NULL; + } + } + + cgh.write_output(); + } + + + void Modules::dump(unsigned level) const + { + DEBUG(level, "Modules (%lu pcs.)", (unsigned long) mods_v.size()); + for(size_t i = 0; i < mods_v.size(); i++) mods_v[i]->dump(level); + } + + std::set Modules::getVersionsWithProductNumber() const { + std::set versions; + for (size_t i = 0; i < mods_v.size(); ++i) { + const ModuleVersion version = mods_v[i]->getVersion(); + if (version.hasProductNumber()) { + versions.insert(version); + } + } + return versions; + } + + void Modules::add_types_to_json_schema(JSON_Tokenizer& json) + { + for(size_t i = 0; i < mods_v.size(); ++i) { + mods_v[i]->add_types_to_json_schema(json); + } + } + + void Modules::add_func_to_json_schema(map& json_refs) + { + for(size_t i = 0; i < mods_v.size(); ++i) { + mods_v[i]->add_func_to_json_schema(json_refs); + } + } + + + // ================================= + // ===== Module + // ================================= + + ModuleVersion Module::getVersion() const { + return ModuleVersion(product_number, suffix, release, patch, build, extra); + } + + void Module::generate_literals(output_struct *target) + { + char *src = NULL; + char *hdr = NULL; + generate_bs_literals(src, hdr); // implementations follow directly below + generate_bp_literals(src, hdr); + generate_hs_literals(src, hdr); + generate_hp_literals(src, hdr); + generate_os_literals(src, hdr); + generate_op_literals(src, hdr); + generate_cs_literals(src, hdr); + generate_us_literals(src, hdr); + generate_oid_literals(src, hdr); + generate_pp_literals(src, hdr); + generate_mp_literals(src, hdr); + target->source.string_literals = + mputstr(target->source.string_literals, src); + if (CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE) { + target->header.global_vars = mputstr(target->header.global_vars, hdr); + } + Free(src); + Free(hdr); + } + + void Module::generate_bs_literals(char *&src, char *&hdr) + { + if (bs_literals.size() == 0) return; + // indicates whether we have found at least one non-empty bitstring + bool is_nonempty = false; + bool splitting = + CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE; + for (size_t i = 0; i < bs_literals.size(); i++) { + const string& str = bs_literals.get_nth_key(i); + size_t bits = str.size(); + if (bits == 0) continue; + if (is_nonempty) src = mputstr(src, ",\n"); + else { + src = mputstr(src, "static const unsigned char "); + is_nonempty = true; + } + src = mputprintf(src, "%s_bits[] = { ", + bs_literals.get_nth_elem(i)->c_str()); + // Filling up the octets one-by-one + for (size_t j = 0; j < (bits + 7) / 8; j++) { + size_t offset = 8 * j; + unsigned char value = 0; + for (size_t k = 0; k < 8 && k < bits - offset; k++) { + if (str[offset + k] == '1') value |= (1 << k); + } + if (j > 0) src = mputstr(src, ", "); + src = mputprintf(src, "%d", value); + } + src = mputstr(src, " }"); + } + if (is_nonempty) src = mputstr(src, ";\n"); + for (size_t i = 0; i < bs_literals.size(); i++) { + if (i > 0) { + src = mputstr(src, ",\n"); + if (splitting) hdr = mputstr(hdr, ",\n"); + } + else { + src = mputprintf(src, "%s const BITSTRING ", + splitting ? "extern" : "static"); + if (splitting) hdr = mputstr(hdr, "extern const BITSTRING "); + } + size_t bits = bs_literals.get_nth_key(i).size(); + const char *object_name = bs_literals.get_nth_elem(i)->c_str(); + if (bits > 0) src = mputprintf(src, "%s(%lu, %s_bits)", + object_name, (unsigned long) bits, object_name); + else src = mputprintf(src, "%s(0, NULL)", object_name); + if (splitting) hdr = mputstr(hdr, object_name); + } + src = mputstr(src, ";\n"); + if (splitting) hdr = mputstr(hdr, ";\n"); + } + + void Module::generate_bp_literals(char *&src, char *& /*hdr*/) + { + if (bp_literals.size() == 0) return; + for (size_t i = 0; i < bp_literals.size(); i++) { + if (i > 0) src = mputstr(src, ",\n"); + else src = mputstr(src, "static const unsigned char "); + src = mputprintf(src, "%s_elements[] = { ", + bp_literals.get_nth_elem(i)->c_str()); + const string& str = bp_literals.get_nth_key(i); + for (size_t j = 0; j < str.size(); j++) { + if (j > 0) src = mputstr(src, ", "); + switch (str[j]) { + case '0': + src = mputc(src, '0'); + break; + case '1': + src = mputc(src, '1'); + break; + case '?': + src = mputc(src, '2'); + break; + case '*': + src = mputc(src, '3'); + break; + default: + FATAL_ERROR("Invalid character in bitstring pattern."); + } + } + src = mputstr(src, " }"); + } + src = mputstr(src, ";\n"); + for (size_t i = 0; i < bp_literals.size(); i++) { + if (i > 0) src = mputstr(src, ",\n"); + else src = mputstr(src, "static const BITSTRING_template "); + const char *name = bp_literals.get_nth_elem(i)->c_str(); + src = mputprintf(src, "%s(%lu, %s_elements)", + name, (unsigned long) bp_literals.get_nth_key(i).size(), name); + } + src = mputstr(src, ";\n"); + } + + void Module::generate_hs_literals(char *&src, char *&hdr) + { + if (hs_literals.size() == 0) return; + // indicates whether we have found at least one non-empty hexstring + bool is_nonempty = false; + bool splitting = + CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE; + for (size_t i = 0; i < hs_literals.size(); i++) { + const string& str = hs_literals.get_nth_key(i); + size_t nibbles = str.size(); + if (nibbles == 0) continue; + size_t octets = (nibbles + 1) / 2; + const char *str_ptr = str.c_str(); + if (is_nonempty) src = mputstr(src, ",\n"); + else { + src = mputstr(src, "static const unsigned char "); + is_nonempty = true; + } + src = mputprintf(src, "%s_nibbles[] = { ", + hs_literals.get_nth_elem(i)->c_str()); + for (size_t j = 0; j < octets; j++) { + // Hex digit with even index always goes to the least significant + // 4 bits of the octet. + unsigned char value = char_to_hexdigit(str_ptr[2 * j]); + if (2 * j + 1 < nibbles) { + // Hex digit with odd index always goes to the most significant + // 4 bits of the octet. + // This digit is not present (bits are set to zero) if the length + // of hexstring is odd. + value += 16 * char_to_hexdigit(str_ptr[2 * j + 1]); + } + if (j > 0) src = mputstr(src, ", "); + src = mputprintf(src, "%u", value); + } + src = mputstr(src, " }"); + } + if (is_nonempty) src = mputstr(src, ";\n"); + for (size_t i = 0; i < hs_literals.size(); i++) { + if (i > 0) { + src = mputstr(src, ",\n"); + if (splitting) hdr = mputstr(hdr, ",\n"); + } + else { + src = mputprintf(src, "%s const HEXSTRING ", + splitting ? "extern" : "static"); + if (splitting) hdr = mputstr(hdr, "extern const HEXSTRING "); + } + size_t nibbles = hs_literals.get_nth_key(i).size(); + const char *object_name = hs_literals.get_nth_elem(i)->c_str(); + if (nibbles > 0) src = mputprintf(src, "%s(%lu, %s_nibbles)", + object_name, (unsigned long) nibbles, object_name); + else src = mputprintf(src, "%s(0, NULL)", object_name); + if (splitting) hdr = mputstr(hdr, object_name); + } + src = mputstr(src, ";\n"); + if (splitting) hdr = mputstr(hdr, ";\n"); + } + + void Module::generate_hp_literals(char *&src, char *& /*hdr*/) + { + if (hp_literals.size() == 0) return; + for (size_t i = 0; i < hp_literals.size(); i++) { + if (i > 0) src = mputstr(src, ",\n"); + else src = mputstr(src, "static const unsigned char "); + src = mputprintf(src, "%s_elements[] = { ", + hp_literals.get_nth_elem(i)->c_str()); + const string& str = hp_literals.get_nth_key(i); + size_t size = str.size(); + const char *str_ptr = str.c_str(); + for (size_t j = 0; j < size; j++) { + if (j > 0) src = mputstr(src, ", "); + unsigned char num; + if (str_ptr[j] == '?') num = 16; + else if (str_ptr[j] == '*') num = 17; + else num = char_to_hexdigit(str_ptr[j]); + src = mputprintf(src, "%u", num); + } + src = mputstr(src, " }"); + } + src = mputstr(src, ";\n"); + for (size_t i = 0; i < hp_literals.size(); i++) { + if (i > 0) src = mputstr(src, ",\n"); + else src = mputstr(src, "static const HEXSTRING_template "); + const char *name = hp_literals.get_nth_elem(i)->c_str(); + src = mputprintf(src, "%s(%lu, %s_elements)", + name, (unsigned long) hp_literals.get_nth_key(i).size(), name); + } + src = mputstr(src, ";\n"); + } + + void Module::generate_os_literals(char *&src, char *&hdr) + { + if (os_literals.size() == 0) return; + // indicates whether we have found at least one non-empty octetstring + bool is_nonempty = false; + bool splitting = + CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE; + for (size_t i = 0; i < os_literals.size(); i++) { + const string& str = os_literals.get_nth_key(i); + size_t size = str.size(); + if (size % 2) FATAL_ERROR("Invalid length for an octetstring."); + size_t octets = size / 2; + if (octets == 0) continue; + const char *str_ptr = str.c_str(); + if (is_nonempty) src = mputstr(src, ",\n"); + else { + src = mputstr(src, "static const unsigned char "); + is_nonempty = true; + } + src = mputprintf(src, "%s_octets[] = { ", + os_literals.get_nth_elem(i)->c_str()); + for (size_t j = 0; j < octets; j++) { + if (j > 0) src = mputstr(src, ", "); + src = mputprintf(src, "%u", 16 * char_to_hexdigit(str_ptr[2 * j]) + + char_to_hexdigit(str_ptr[2 * j + 1])); + } + src = mputstr(src, " }"); + } + if (is_nonempty) src = mputstr(src, ";\n"); + for (size_t i = 0; i < os_literals.size(); i++) { + if (i > 0) { + src = mputstr(src, ",\n"); + if (splitting) hdr = mputstr(hdr, ",\n"); + } + else { + src = mputprintf(src, "%s const OCTETSTRING ", + splitting ? "extern" : "static"); + if (splitting) hdr = mputstr(hdr, "extern const OCTETSTRING "); + } + size_t octets = os_literals.get_nth_key(i).size() / 2; + const char *object_name = os_literals.get_nth_elem(i)->c_str(); + if (octets > 0) src = mputprintf(src, "%s(%lu, %s_octets)", + object_name, (unsigned long) octets, object_name); + else src = mputprintf(src, "%s(0, NULL)", object_name); + if (splitting) hdr = mputstr(hdr, object_name); + } + src = mputstr(src, ";\n"); + if (splitting) hdr = mputstr(hdr, ";\n"); + } + + void Module::generate_op_literals(char *&src, char *& /*hdr*/) + { + if (op_literals.size() == 0) return; + vector pattern_lens; + for(size_t i = 0; i < op_literals.size(); i++) { + if (i > 0) src = mputstr(src, ",\n"); + else src = mputstr(src, "static const unsigned short "); + src = mputprintf(src, "%s_elements[] = { ", + op_literals.get_nth_elem(i)->c_str()); + const string& str = op_literals.get_nth_key(i); + size_t size = str.size(); + size_t pattern_len = 0; + const char *str_ptr = str.c_str(); + for (size_t j = 0; j < size; j++) { + if (j > 0) src = mputstr(src, ", "); + unsigned short num; + if (str_ptr[j] == '?') num = 256; + else if (str_ptr[j] == '*') num = 257; + else { + // first digit + num = 16 * char_to_hexdigit(str_ptr[j]); + j++; + if (j >= size) FATAL_ERROR("Unexpected end of octetstring pattern."); + // second digit + num += char_to_hexdigit(str_ptr[j]); + } + src = mputprintf(src, "%u", num); + pattern_len++; + } + src = mputstr(src, " }"); + pattern_lens.add(new size_t(pattern_len)); + } + src = mputstr(src, ";\n"); + for (size_t i = 0; i < op_literals.size(); i++) { + if (i > 0) src = mputstr(src, ",\n"); + else src = mputstr(src, "static const OCTETSTRING_template "); + const char *name = op_literals.get_nth_elem(i)->c_str(); + src = mputprintf(src, "%s(%lu, %s_elements)", + name, (unsigned long) *pattern_lens[i], name); + } + src = mputstr(src, ";\n"); + for (size_t i = 0; i < pattern_lens.size(); i++) delete pattern_lens[i]; + pattern_lens.clear(); + } + + void Module::generate_cs_literals(char *&src, char *&hdr) + { + if (cs_literals.size() == 0) return; + bool splitting = + CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE; + for (size_t i = 0; i < cs_literals.size(); i++) { + const string& str = cs_literals.get_nth_key(i); + size_t str_len = str.size(); + const char *str_ptr = str.c_str(); + const char *str_name = cs_literals.get_nth_elem(i)->c_str(); + + if (i > 0) { + src = mputstr(src, ",\n"); + if (splitting) hdr = mputstr(hdr, ",\n"); + } + else { + src = mputprintf(src, "%s const CHARSTRING ", + splitting ? "extern" : "static"); + if (splitting) hdr = mputstr(hdr, "extern const CHARSTRING "); + } + + switch (str_len) { + case 0: + src = mputprintf(src, "%s(0, NULL)", str_name); + break; + case 1: + src = mputprintf(src, "%s('", str_name); + src = Code::translate_character(src, *str_ptr, false); + src = mputstr(src, "')"); + break; + default: + src = mputprintf(src, "%s(%lu, \"", str_name, (unsigned long) str_len); + // Note: Code::translate_string() is not suitable because the string + // may contain NUL characters at which translate_string() stops + // immediately + for (size_t j = 0; j < str_len; j++) + src = Code::translate_character(src, str_ptr[j], true); + src = mputstr(src, "\")"); + break; + } // switch + if (splitting) hdr = mputstr(hdr, str_name); + } + src = mputstr(src, ";\n"); + if (splitting) hdr = mputstr(hdr, ";\n"); + } + + void Module::generate_pp_literals(char *&src, char *&) // padding patterns + { + if (pp_literals.size() == 0) return; + for (size_t i = 0; i < pp_literals.size(); i++) { + const string& pattern = pp_literals.get_nth_key(i); + size_t pattern_len = pattern.size(); + const char *pattern_ptr = pattern.c_str(); + if (i > 0) src = mputstr(src, ",\n"); + else src = mputstr(src, "static const unsigned char "); + src = mputprintf(src, "%s[] = { ", pp_literals.get_nth_elem(i)->c_str()); + if (pattern_len % 8 != 0) FATAL_ERROR("Module::generate_pp_literals()"); + size_t nof_octets = pattern_len / 8; + for (size_t j = 0; j < nof_octets; j++) { + if (j > 0) src = mputstr(src, ", "); + unsigned char octet = 0; + for (size_t k = 0; k < 8; k++) { + // take the octets in reverse order + // MSB is the first character of the string + octet <<= 1; + if (pattern_ptr[8 * (nof_octets - j - 1) + k] == '1') octet |= 0x01; + } + src = mputprintf(src, "0x%02x", octet); + } + src = mputstr(src, " }"); + } + src = mputstr(src, ";\n"); + } + + void Module::generate_mp_literals(char *&src, char *&) // matching patt. + { + if (mp_literals.size() == 0) return; + for (size_t i = 0; i < mp_literals.size(); i++) { + const string& str = mp_literals.get_nth_key(i); + if (str.size() < 1) FATAL_ERROR("Module::generate_mp_literals()"); + const char *str_ptr = str.c_str(); + + if (i > 0) src = mputstr(src, ",\n"); + else src = mputstr(src, "static const Token_Match "); + + src = mputprintf(src, "%s(\"", mp_literals.get_nth_elem(i)->c_str()); + src = Code::translate_string(src, str_ptr + 1); + // The first character of the string is case-sensitiveness flag: + // 'I' for yes, 'N' for no, + // 'F' for fixed string matching which is always case sensitive. + src = mputprintf(src, "\", %s%s)", (str_ptr[0]!='N') ? "TRUE" : "FALSE", + (str_ptr[0] == 'F') ? ", TRUE" : ""); + } + src = mputstr(src, ";\n"); + } + + void Module::generate_us_literals(char *&src, char *&hdr) // univ.cs + { + size_t n_literals = us_literals.size(); + if (n_literals == 0) return; + bool array_needed = false; + bool splitting = + CodeGenHelper::GetInstance().get_split_mode() != CodeGenHelper::SPLIT_NONE; + for (size_t i = 0; i < n_literals; i++) { + const ustring& value = us_literals.get_nth_key(i); + size_t value_size = value.size(); + if (value_size < 2) continue; + if (array_needed) src = mputstr(src, ",\n"); + else { + src = mputstr(src, "static const universal_char "); + array_needed = true; + } + src = mputprintf(src, "%s_uchars[] = { ", + us_literals.get_nth_elem(i)->c_str()); + const ustring::universal_char *uchars_ptr = value.u_str(); + for (size_t j = 0; j < value_size; j++) { + if (j > 0) src = mputstr(src, ", "); + src = mputprintf(src, "{ %u, %u, %u, %u }", uchars_ptr[j].group, + uchars_ptr[j].plane, uchars_ptr[j].row, uchars_ptr[j].cell); + } + src = mputstr(src, " }"); + } + if (array_needed) src = mputstr(src, ";\n"); + for (size_t i = 0; i < n_literals; i++) { + if (i > 0) { + src = mputstr(src, ",\n"); + if (splitting) hdr = mputstr(hdr, ",\n"); + } + else { + src = mputprintf(src, "%s const UNIVERSAL_CHARSTRING ", + splitting ? "extern" : "static"); + if (splitting) hdr = mputstr(hdr, "extern const UNIVERSAL_CHARSTRING "); + } + const char *value_name = us_literals.get_nth_elem(i)->c_str(); + const ustring& value = us_literals.get_nth_key(i); + size_t value_size = value.size(); + switch (value_size) { + case 0: + src = mputprintf(src, "%s(0, (const universal_char*)NULL)", value_name); + break; + case 1: { + const ustring::universal_char& uchar = value.u_str()[0]; + src = mputprintf(src, "%s(%u, %u, %u, %u)", value_name, + uchar.group, uchar.plane, uchar.row, uchar.cell); + break; } + default: + src = mputprintf(src, "%s(%lu, %s_uchars)", value_name, + (unsigned long) value_size, value_name); + break; + } + if (splitting) hdr = mputstr(hdr, value_name); + } + src = mputstr(src, ";\n"); + if (splitting) hdr = mputstr(hdr, ";\n"); + } + + void Module::generate_oid_literals(char *&src, char *& /*hdr*/) + { + if (oid_literals.size() == 0) return; + for (size_t i = 0; i < oid_literals.size(); i++) { + if (i > 0) src = mputstr(src, ",\n"); + else src = mputstr(src, "static const OBJID::objid_element "); + + src = mputprintf(src, "%s_comps[] = { %s }", + oid_literals.get_nth_elem(i)->oid_id.c_str(), + oid_literals.get_nth_key(i).c_str()); + } + src = mputstr(src, ";\n"); + for(size_t i = 0; i < oid_literals.size(); i++) { + const OID_literal *litstruct = oid_literals.get_nth_elem(i); + + if (i > 0) src = mputstr(src, ",\n"); + else src = mputstr(src, "static const OBJID "); + + src = mputprintf(src, "%s(%lu, %s_comps)", + litstruct->oid_id.c_str(), (unsigned long) litstruct->nof_elems, + litstruct->oid_id.c_str()); + } + src = mputstr(src, ";\n"); + } + + void Module::generate_functions(output_struct *output) + { + bool tcov_enabled = tcov_file_name && in_tcov_files(get_filename()); + bool has_pre_init_before_tcov = output->functions.pre_init != NULL; + if (tcov_enabled) { + output->functions.pre_init = mputprintf(output->functions.pre_init, + "TTCN_Location_Statistics::init_file_lines(\"%s\", effective_module_lines, sizeof(effective_module_lines) / sizeof(int));\n" \ + "TTCN_Location_Statistics::init_file_functions(\"%s\", effective_module_functions, sizeof(effective_module_functions) / sizeof(char *));\n", + get_tcov_file_name(get_filename()), get_tcov_file_name(get_filename())); + } + // pre_init function + bool has_pre_init = false; + if (output->functions.pre_init) { + output->source.static_function_prototypes = + mputstr(output->source.static_function_prototypes, + "static void pre_init_module();\n"); + output->source.static_function_bodies = mputstr(output->source.static_function_bodies, + "static void pre_init_module()\n" + "{\n"); + if (include_location_info) { + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, + (tcov_enabled && has_pre_init_before_tcov) ? "TTCN_Location_Statistics current_location(\"" + : "TTCN_Location current_location(\""); + output->source.static_function_bodies = + Code::translate_string(output->source.static_function_bodies, (tcov_enabled && has_pre_init_before_tcov) ? get_tcov_file_name(get_filename()) : get_filename()); + output->source.static_function_bodies = + mputprintf(output->source.static_function_bodies, + (tcov_enabled && has_pre_init_before_tcov) ? "\", 0, TTCN_Location_Statistics::LOCATION_UNKNOWN, \"%s\");\n" + : "\", 0, TTCN_Location::LOCATION_UNKNOWN, \"%s\");\n", get_modid().get_dispname().c_str()); + if (tcov_enabled && has_pre_init_before_tcov) { + effective_module_lines = + mputprintf(effective_module_lines, "%s0", + (effective_module_lines ? ", " : "")); + effective_module_functions = + mputprintf(effective_module_functions, "%s\"%s\"", + (effective_module_functions ? ", " : ""), get_modid().get_dispname().c_str()); + } + } + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, output->functions.pre_init); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, "}\n\n"); + Free(output->functions.pre_init); + output->functions.pre_init = NULL; + has_pre_init = true; + } + bool has_post_init_before_tcov = output->functions.post_init != NULL; + // post_init function + bool has_post_init = false; + if (output->functions.post_init) { + output->source.static_function_prototypes = mputstr(output->source.static_function_prototypes, + "static void post_init_module();\n"); + output->source.static_function_bodies = mputstr(output->source.static_function_bodies, + "static void post_init_module()\n" + "{\n"); + if (include_location_info) { + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, + (tcov_enabled && has_post_init_before_tcov) ? "TTCN_Location_Statistics current_location(\"" + : "TTCN_Location current_location(\""); + output->source.static_function_bodies = + Code::translate_string(output->source.static_function_bodies, (tcov_enabled && has_post_init_before_tcov) ? get_tcov_file_name(get_filename()) : get_filename()); + output->source.static_function_bodies = + mputprintf(output->source.static_function_bodies, + (tcov_enabled && has_post_init_before_tcov) ? "\", 0, TTCN_Location_Statistics::LOCATION_UNKNOWN, \"%s\");\n" + : "\", 0, TTCN_Location::LOCATION_UNKNOWN, \"%s\");\n", get_modid().get_dispname().c_str()); + if (tcov_enabled && has_post_init_before_tcov) { + effective_module_lines = + mputprintf(effective_module_lines, "%s0", + (effective_module_lines ? ", " : "")); + effective_module_functions = + mputprintf(effective_module_functions, "%s\"%s\"", + (effective_module_functions ? ", " : ""), get_modid().get_dispname().c_str()); + } + } + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, output->functions.post_init); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, "}\n\n"); + Free(output->functions.post_init); + output->functions.post_init = NULL; + has_post_init = true; + } + // set_param function + bool has_set_param; + if (output->functions.set_param) { + output->source.static_function_prototypes = mputstr(output->source.static_function_prototypes, + "static boolean set_module_param(Module_Param& param);\n"); + output->source.static_function_bodies = mputstr(output->source.static_function_bodies, + "static boolean set_module_param(Module_Param& param)\n" + "{\n" + "const char* const par_name = param.get_id()->get_current_name();\n"); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, output->functions.set_param); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, "return FALSE;\n" + "}\n\n"); + Free(output->functions.set_param); + output->functions.set_param = NULL; + has_set_param = true; + } else has_set_param = false; + // log_param function + bool has_log_param; + if (output->functions.log_param) { + output->source.static_function_prototypes = mputstr(output->source.static_function_prototypes, + "static void log_module_param();\n"); + output->source.static_function_bodies = mputstr(output->source.static_function_bodies, + "static void log_module_param()\n" + "{\n"); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, output->functions.log_param); + output->source.static_function_bodies = mputstr(output->source.static_function_bodies, + "}\n\n"); + Free(output->functions.log_param); + output->functions.log_param = NULL; + has_log_param = true; + } else has_log_param = false; + // init_comp function + bool has_init_comp; + if (output->functions.init_comp) { + output->source.static_function_prototypes = + mputstr(output->source.static_function_prototypes, + "static boolean init_comp_type(" + "const char *component_type, boolean init_base_comps);\n"); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, + "static boolean init_comp_type(const char *component_type, " + "boolean init_base_comps)\n" + "{\n(void)init_base_comps;\n"); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, + output->functions.init_comp); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, "return FALSE;\n" + "}\n\n"); + Free(output->functions.init_comp); + output->functions.init_comp = NULL; + has_init_comp = true; + } else has_init_comp = false; + // start function + bool has_start; + if (output->functions.start) { + output->source.static_function_prototypes = mputstr(output->source.static_function_prototypes, + "static boolean start_ptc_function(const char *function_name, " + "Text_Buf& function_arguments);\n"); + output->source.static_function_bodies = mputstr(output->source.static_function_bodies, + "static boolean start_ptc_function(const char *function_name, " + "Text_Buf& function_arguments)\n" + "{\n"); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, output->functions.start); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, "return FALSE;\n" + "}\n\n"); + Free(output->functions.start); + output->functions.start = NULL; + has_start = true; + } else has_start = false; + // control part + bool has_control; + if (output->functions.control) { + output->source.static_function_prototypes = mputstr(output->source.static_function_prototypes, + "static void module_control_part();\n"); + output->source.static_function_bodies = mputstr(output->source.static_function_bodies, + "static void module_control_part()\n" + "{\n"); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, output->functions.control); + output->source.static_function_bodies = + mputstr(output->source.static_function_bodies, "}\n\n"); + Free(output->functions.control); + output->functions.control = NULL; + has_control = true; + } else has_control = false; + // module checksum + if (has_checksum) { + output->source.string_literals = mputstr(output->source.string_literals, + "static const unsigned char module_checksum[] = {"); + for (size_t i = 0; i < sizeof(module_checksum); i++) { + if (i > 0) output->source.string_literals = + mputc(output->source.string_literals, ','); + output->source.string_literals = + mputprintf(output->source.string_literals, " 0x%02x", + module_checksum[i]); + } + output->source.string_literals = mputstr(output->source.string_literals, + " };\n"); + } + const char *module_name = modid->get_name().c_str(); + + // XML namespaces. Written in the order they are stored: + // sorted ASCIIbetically by the prefix. + // Not all namespaces are used by every module. Unfortunately, the array + // (which has the same size in all modules) cannot be compacted, because + // the indexes have already been used when the XER descriptors were written. + // All we can do is store NULLs for the unused namespaces. + size_t num_xml_namespaces = namespaces.size(); + if (moduletype == MOD_TTCN) { //TODO remove this when ASN.1 gets EXER + output->source.global_vars = mputprintf(output->source.global_vars, +#ifndef NDEBUG + "// written by %s in " __FILE__ " at %d\n" +#endif + "static const size_t num_namespaces = %lu;\n" +#ifndef NDEBUG + , __FUNCTION__, __LINE__ +#endif + , (unsigned long)num_xml_namespaces + ); + if (num_xml_namespaces != 0 || (control_ns && control_ns_prefix)) { + output->source.global_vars = mputstr(output->source.global_vars, + "static const namespace_t xml_namespaces[num_namespaces+1] = {\n"); + for (size_t i=0; i < namespaces.size(); ++i) { + if (used_namespaces.has_key(i)) { + output->source.global_vars = mputprintf(output->source.global_vars, + " { \"%s\", \"%s\" },\n", // ns, then prefix + namespaces.get_nth_elem(i), namespaces.get_nth_key(i).c_str()); + } + else { + output->source.global_vars = mputstr(output->source.global_vars, + " { NULL, NULL },\n"); // not used in this module + } + } // next namespace + output->source.global_vars = mputprintf(output->source.global_vars, + " { \"%s\", \"%s\" }\n};\n\n", + (control_ns ? control_ns : ""), + (control_ns_prefix ? control_ns_prefix : "")); + } // if there are namespaces + } // if TTCN + + + // module object + output->header.global_vars = mputprintf(output->header.global_vars, + "extern TTCN_Module %s;\n", + "module_object"); + + output->source.global_vars = mputprintf(output->source.global_vars, + "TTCN_Module %s(\"%s\", __DATE__, __TIME__, %s, %s", + "module_object", + + modid->get_dispname().c_str(), + (has_checksum ? "module_checksum" : "NULL"), + has_pre_init ? "pre_init_module" : "NULL"); + + if (moduletype == MOD_TTCN) { + // TTCN-3 specific function pointers + if (product_number == NULL) { + output->source.global_vars = mputstr(output->source.global_vars, ", NULL"); + } else { + output->source.global_vars = mputprintf(output->source.global_vars, ", \"%s\"", product_number); + } + string extra_str = extra ? ( string('"') + extra + string('"') ) : string("NULL"); + output->source.global_vars = mputprintf(output->source.global_vars, + ", %uU, %uU, %uU, %uU, %s, %luLU, %s, %s, %s, %s, %s, %s, %s", + suffix, release, patch, build, extra_str.c_str(), + (unsigned long)num_xml_namespaces, + ((num_xml_namespaces || (control_ns && control_ns_prefix)) ? "xml_namespaces" : "0"), + has_post_init ? "post_init_module" : "NULL", + has_set_param ? "set_module_param" : "NULL", + has_log_param ? "log_module_param" : "NULL", + has_init_comp ? "init_comp_type" : "NULL", + has_start ? "start_ptc_function" : "NULL", + has_control ? "module_control_part" : "NULL"); + } else { + // self checks for ASN.1 modules + if (has_post_init) + FATAL_ERROR("Module::generate_functions(): post_init function in ASN.1 module"); + if (has_set_param) + FATAL_ERROR("Module::generate_functions(): set_param function in ASN.1 module"); + if (has_log_param) + FATAL_ERROR("Module::generate_functions(): log_param function in ASN.1 module"); + if (has_init_comp) + FATAL_ERROR("Module::generate_functions(): init_comp function in ASN.1 module"); + if (has_start) + FATAL_ERROR("Module::generate_functions(): startable function in ASN.1 module"); + if (has_control) + FATAL_ERROR("Module::generate_functions(): control part in ASN.1 module"); + } + output->source.global_vars = mputstr(output->source.global_vars, ");\n"); + // #include into the source file + output->source.includes = mputprintf(output->source.includes, + "#include \"%s.hh\"\n", + duplicate_underscores ? module_name : modid->get_ttcnname().c_str()); + + output->source.global_vars = mputprintf(output->source.global_vars, + "\nstatic const RuntimeVersionChecker ver_checker(" + " current_runtime_version.requires_major_version_%d,\n" + " current_runtime_version.requires_minor_version_%d,\n" + " current_runtime_version.requires_patch_level_%d," + " current_runtime_version.requires_runtime_%d);\n", + TTCN3_MAJOR, TTCN3_MINOR, TTCN3_PATCHLEVEL, use_runtime_2 ? 2 : 1 + ); + if (tcov_enabled) { + output->source.global_vars = mputprintf(output->source.global_vars, + "\nstatic const int effective_module_lines[] = { %s };\n" \ + "static const char *effective_module_functions[] = { %s };\n", + effective_module_lines ? static_cast(effective_module_lines) : "", + effective_module_functions ? static_cast(effective_module_functions) : ""); + } + } + + void Module::generate_conversion_functions(output_struct *output) + { + for (size_t i = 0; i < type_conv_v.size(); i++) + type_conv_v[i] + ->gen_conv_func(&output->source.static_conversion_function_prototypes, + &output->source.static_conversion_function_bodies, + this); + } + + string Module::add_literal(map& literals, const string& str, + const char *prefix) + { + if (literals.has_key(str)) return *literals[str]; + else { + string *literal = new string(prefix+Int2string(literals.size())); + literals.add(str, literal); + return *literal; + } + } + + void Module::clear_literals(map& literals) + { + for (size_t i = 0; i < literals.size(); i++) + delete literals.get_nth_elem(i); + literals.clear(); + } + + map Module::namespaces; + map Module::invented_prefixes; + size_t Module::default_namespace_attempt = 0; + size_t Module::replacement_for_empty_prefix = (size_t)-1; + + Module::Module(moduletype_t p_mt, Identifier *p_modid) + : Scope(), moduletype(p_mt), modid(p_modid), + imp_checked(false), gen_code(false), has_checksum(false), + visible_mods(), module_checksum(), + bs_literals(), bp_literals(), hs_literals(), hp_literals(), os_literals(), + op_literals(), cs_literals(), us_literals(), pp_literals(), mp_literals(), + oid_literals(), tmp_id_count(0), + control_ns(p_mt == MOD_ASN ? mcopystr("urn:oid:2.1.5.2.0.1") : NULL), + control_ns_prefix(p_mt == MOD_ASN ? mcopystr("asn1") : NULL), + // only ASN.1 modules have default control namespace (X.693 amd1, 16.9) + used_namespaces(), type_conv_v(), product_number(NULL), + suffix(0), release(UINT_MAX), patch(UINT_MAX), build(UINT_MAX), extra(NULL) + { + if(!p_modid) + FATAL_ERROR("NULL parameter: Common::Module::Module()"); + memset(module_checksum, 0, sizeof(module_checksum)); + set_scopeMacro_name(modid->get_dispname()); + } + + Module::~Module() + { + delete modid; + visible_mods.clear(); + clear_literals(bs_literals); + clear_literals(bp_literals); + clear_literals(hs_literals); + clear_literals(hp_literals); + clear_literals(os_literals); + clear_literals(op_literals); + clear_literals(cs_literals); + clear_literals(pp_literals); + clear_literals(mp_literals); + for (size_t i = 0; i < us_literals.size(); i++) + delete us_literals.get_nth_elem(i); + us_literals.clear(); + for (size_t i = 0; i < oid_literals.size(); i++) + delete oid_literals.get_nth_elem(i); + oid_literals.clear(); + for (size_t i = 0; i < type_conv_v.size(); i++) + delete type_conv_v[i]; + type_conv_v.clear(); + Free(control_ns); + Free(control_ns_prefix); + used_namespaces.clear(); // all the values are NULL, no need to free + // static members below; repeated clear()s are redundant but harmless + namespaces.clear(); + invented_prefixes.clear(); + Free(product_number); + Free(extra); + } + + Type *Module::get_address_type() + { + FATAL_ERROR("Common::Module::get_address_type()"); + return 0; + } + + string Module::add_ustring_literal(const ustring& ustr) + { + if (us_literals.has_key(ustr)) return *us_literals[ustr]; + else { + string *literal = new string("us_" + Int2string(us_literals.size())); + us_literals.add(ustr, literal); + return *literal; + } + } + + string Module::add_objid_literal(const string& oi_str, const size_t nof_elems) + { + if(oid_literals.has_key(oi_str)) return oid_literals[oi_str]->oid_id; + else { + OID_literal *oi_struct = new OID_literal; + oi_struct->nof_elems = nof_elems; + oi_struct->oid_id = "oi_" + Int2string(oid_literals.size()); + oid_literals.add(oi_str, oi_struct); + return oi_struct->oid_id; + } + } + + void Module::add_type_conv(TypeConv *p_conv) + { + if (p_conv == NULL) FATAL_ERROR("Module::add_type_conv()"); + Type *p_from_type = p_conv->get_from_type(); + Type *p_to_type = p_conv->get_to_type(); + if (!p_from_type->is_structured_type() + || !p_to_type->is_structured_type()) + FATAL_ERROR("Module::add_type_conv()"); + if (p_from_type == p_to_type) { + // Never add the same types. + delete p_conv; + return; + } + for (size_t i = 0; i < type_conv_v.size(); i++) { + TypeConv *conv = type_conv_v[i]; + if (conv->get_from_type() == p_from_type + && conv->get_to_type() == p_to_type + && conv->is_temp() == p_conv->is_temp()) { + // Same pair of types, both for values or templates. We're the + // owners, deallocate. + delete p_conv; + return; + } + } + type_conv_v.add(p_conv); + } + + bool Module::needs_type_conv(Type *p_from_type, Type *p_to_type) const + { + for (size_t i = 0; i < type_conv_v.size(); i++) { + TypeConv *conv = type_conv_v[i]; + if (conv->get_from_type() == p_from_type + && conv->get_to_type() == p_to_type) + return true; + } + return false; + } + + void Module::chk_recursive(module_set_t& checked_modules) + { + if (checked_modules.has_key(this)) return; + // this must be added to the set at the beginning + // in order to deal with circular imports + checked_modules.add(this, 0); + // check the imported modules first + size_t nof_visible_mods = visible_mods.size(); + for (size_t i = 0; i < nof_visible_mods; i++) { + Module *m = visible_mods.get_nth_key(i); + if (m != this) m->chk_recursive(checked_modules); + } + // then check the module itself + chk(); // this is the only virtual call + } + + bool Module::is_visible(Module *m) + { + collect_visible_mods(); + return visible_mods.has_key(m); + } + + void Module::get_visible_mods(module_set_t& p_visible_mods) + { + if (visible_mods.has_key(this)) { + size_t nof_visible_mods = visible_mods.size(); + for (size_t i = 0; i < nof_visible_mods; i++) { + Module *m = visible_mods.get_nth_key(i); + if (!p_visible_mods.has_key(m)) p_visible_mods.add(m, 0); + } + } else { + get_imported_mods(p_visible_mods); + } + } + + void Module::write_checksum() + { + fprintf(stderr, "%-18s ", modid->get_dispname().c_str()); + switch (moduletype) { + case MOD_TTCN: fprintf(stderr, "%-15s ", "TTCN-3"); break; + case MOD_ASN: fprintf(stderr, "%-15s ", "ASN.1"); break; + case MOD_UNKNOWN: fprintf(stderr, "%-15s ", "OTHER"); break; + } + + if (!has_checksum) { + fputc('\n', stderr); + return; + } + + size_t nof_checksum = sizeof(module_checksum); + for (size_t i = 0; i < nof_checksum; i++) { + fprintf(stderr, "%02x", module_checksum[i]); + } + + if (release <= 999999 && patch < 30 && build < 100) { + char *product_identifier = + get_product_identifier(product_number, suffix, release, patch, build, extra); + fprintf(stderr, " %s", product_identifier); + Free(product_identifier); + } + + fputc('\n', stderr); + } + + char* Module::get_product_identifier(const char* product_number, + const unsigned int suffix, unsigned int release, unsigned int patch, + unsigned int build, const char* extra) + { + expstring_t ret_val = memptystr(); + if ( product_number == NULL + && suffix == UINT_MAX + && release == UINT_MAX + && patch == UINT_MAX + && build == UINT_MAX) { + ret_val = mputstr(ret_val, ""); + return ret_val; + } + if (product_number != NULL) { + ret_val = mputstr(ret_val, product_number); + if (suffix != 0) { + ret_val = mputprintf(ret_val, "/%d", suffix); + } + ret_val = mputc(ret_val, ' '); + } + + char* build_str = buildstr(build); + ret_val = mputprintf(ret_val, "R%u%c%s%s", release, eri(patch), build_str, extra ? extra : ""); + Free(build_str); + return ret_val; + } + + void Module::collect_visible_mods() + { + if (!visible_mods.has_key(this)) { + get_imported_mods(visible_mods); + if (!visible_mods.has_key(this)) visible_mods.add(this, 0); + } + } + + void Module::set_checksum(size_t checksum_len, + const unsigned char* checksum_ptr) + { + if (checksum_len != sizeof(module_checksum)) + FATAL_ERROR("Module::set_checksum(): invalid length"); + memcpy(module_checksum, checksum_ptr, sizeof(module_checksum)); + has_checksum = true; + } + + void Module::set_controlns(char *ns, char *prefix) + { + Free(control_ns); + control_ns = ns; + Free(control_ns_prefix); + control_ns_prefix = prefix; + } + + void Module::get_controlns(const char *&ns, const char *&prefix) + { + ns = control_ns; + prefix = control_ns_prefix; + } + + const size_t max_invented_prefixes = 10000; + void Module::add_namespace(const char *new_uri, char *&new_prefix) + { + const bool prefix_is_empty = new_prefix && !*new_prefix; + const string key(new_prefix ? new_prefix : ""); + if (new_prefix && !namespaces.has_key(key)) { + namespaces.add(key, new_uri); + if (*new_prefix == 0) { // first add of default namespace + ++default_namespace_attempt; + } + return; // newly added + } + else { // prefix already present (or we are required to invent one) + if (new_prefix) { + const char *uri_value = namespaces[key]; + if (!strcmp(uri_value, new_uri)) return; // same URI, same prefix: no-op + } + + // prefix already present but different URI, + // or prefix is NULL (which means we must invent a prefix) + + if (new_prefix && *new_prefix) { + Free(new_prefix); // prefix is not empty, discard it and start fresh + new_prefix = memptystr(); + } + + const string uri_key(new_uri); + if (invented_prefixes.has_key(uri_key)) { + // we already made one up for this URI + new_prefix = mputstr(new_prefix, invented_prefixes[uri_key]); + return; // already there + } + else { + // make one up on the spot + size_t iidx = invented_prefixes.size(); // "invented index" + new_prefix = mputprintf(new_prefix, "tq%04lu", (unsigned long)iidx++); + string made_up_prefix(new_prefix); + for (; iidx < max_invented_prefixes; ++iidx) { + if (namespaces.has_key(made_up_prefix)) { + // Some pervert wrote an XSD with a namespace prefix like tq0007! + // Make up another one in the same memory spot. + sprintf(new_prefix, "tq%04lu", (unsigned long)iidx); + made_up_prefix = new_prefix; + } + else break; + } + + if (iidx >= max_invented_prefixes) { + Location loc; // no particular location + loc.error("Internal limit: too many assigned prefixes"); + return; // not added + } + invented_prefixes.add(uri_key, new_prefix); + namespaces.add(made_up_prefix, new_uri); + + // Search for the newly added prefix and remember it. + replacement_for_empty_prefix = namespaces.find_key(made_up_prefix); + + if (prefix_is_empty) { + ++default_namespace_attempt; + } + return; // newly added + } + } // if (present) + } + + static const string empty_prefix; + void Module::rename_default_namespace() + { + if (default_namespace_attempt < 2) return; + // There was more than one default namespace. However, all but the first + // are already renamed to tq%d. + size_t di = namespaces.find_key(empty_prefix); // keys are prefixes + if (di < namespaces.size()) { // found it + const char *last_remaining_def_namespace = namespaces.get_nth_elem(di); + // we can't change a key, we can only remove and re-add it + namespaces.erase(empty_prefix); + + expstring_t empty_prefix_string = NULL; // force a made-up prefix + add_namespace(last_remaining_def_namespace, empty_prefix_string); + Free(empty_prefix_string); + } + else FATAL_ERROR("Module::rename_default_namespace"); + } + + size_t Module::get_ns_index(const char *prefix) + { + size_t idx = namespaces.find_key(string(prefix)); + if (idx >= namespaces.size()) { // not found + // If the the caller asked for the empty prefix and it wasn't found + // because it has been replaced, use the replacement. + if (*prefix == '\0' && replacement_for_empty_prefix != (size_t)-1) { + idx = replacement_for_empty_prefix; + } + else FATAL_ERROR("Module::get_ns_index()"); + } + + // Remember that the index is used by this module + if (!used_namespaces.has_key(idx)) { + used_namespaces.add(idx, NULL); + } + return idx; + } + + string Module::get_temporary_id() + { + static const string tmp_prefix("tmp_"); + return tmp_prefix + Int2string(tmp_id_count++); + } + + void Module::generate_code(CodeGenHelper& cgh) + { + if (!gen_code) { + nof_notupdated_files += 2; + DEBUG(1, "Code not generated for module `%s'.", + modid->get_dispname().c_str()); + return; + } + DEBUG(1, "Generating code for module `%s'.", + modid->get_dispname().c_str()); + + // TODO: Always assume to have circular imports until + // full program optimization is available, + // this increases the size of the generated code, + // but otherwise it is possible to create uncompilable code: + // 1) let the project of module A and B refer to each other, + // 2) A refers B, and compile A + // 3) edit B to refer to A and compile it ... + // As the code for A can not be rewritten the code will not compile + cgh.add_module(modid->get_name(), modid->get_ttcnname(), + moduletype == MOD_TTCN, true); + cgh.set_current_module(modid->get_ttcnname()); + + // language specific parts (definitions, imports, etc.) + //generate_code_internal(&target); <- needed to pass cgh + generate_code_internal(cgh); + + // string literals + generate_literals(cgh.get_current_outputstruct()); + // module level entry points + generate_functions(cgh.get_current_outputstruct()); + // type conversion functions for type compatibility + generate_conversion_functions(cgh.get_current_outputstruct()); + } + + void Module::dump(unsigned level) const + { + DEBUG(level, "Module: %s", get_modid().get_dispname().c_str()); + } + + // ================================= + // ===== Assignments + // ================================= + + Assignments *Assignments::get_scope_asss() + { + return this; + } + + Assignment *Assignments::get_ass_bySRef(Ref_simple *p_ref) + { + if (!p_ref || !parent_scope) + FATAL_ERROR("NULL parameter: Common::Assignments::get_ass_bySRef()"); + if (!p_ref->get_modid()) { + const Identifier *id = p_ref->get_id(); + if (id && has_local_ass_withId(*id)) return get_local_ass_byId(*id); + } + return parent_scope->get_ass_bySRef(p_ref); + } + + bool Assignments::has_ass_withId(const Identifier& p_id) + { + if (has_local_ass_withId(p_id)) return true; + else if (parent_scope) return parent_scope->has_ass_withId(p_id); + else return false; + } + + // ================================= + // ===== Assignment + // ================================= + + Assignment::Assignment(asstype_t p_asstype, Identifier *p_id) + : asstype(p_asstype), id(p_id), my_scope(0), checked(false), + visibilitytype(PUBLIC) + { + if (!id) FATAL_ERROR("Assignment::Assignment(): NULL parameter"); + } + + Assignment::Assignment(const Assignment& p) + : Node(p), Location(p), asstype(p.asstype), id(p.id->clone()), my_scope(0), + checked(false), visibilitytype(p.visibilitytype) + { + + } + + Assignment::~Assignment() + { + delete id; + } + + Assignment::asstype_t Assignment::get_asstype() const + { + return asstype; + } + + const char *Assignment::get_assname() const + { + switch (get_asstype()) { + case A_TYPE: + return "type"; + case A_CONST: + if (my_scope && my_scope->get_scope_mod()->get_moduletype() == + Module::MOD_ASN) return "value"; + else return "constant"; + case A_ERROR: + return "erroneous assignment"; + case A_OC: + return "information object class"; + case A_OBJECT: + return "information object"; + case A_OS: + return "information object set"; + case A_VS: + return "value set"; + case A_EXT_CONST: + return "external constant"; + case A_MODULEPAR: + return "module parameter"; + case A_MODULEPAR_TEMP: + return "template module parameter"; + case A_TEMPLATE: + return "template"; + case A_VAR: + return "variable"; + case A_VAR_TEMPLATE: + return "template variable"; + case A_TIMER: + return "timer"; + case A_PORT: + return "port"; + case A_FUNCTION: + case A_FUNCTION_RVAL: + case A_FUNCTION_RTEMP: + return "function"; + case A_EXT_FUNCTION: + case A_EXT_FUNCTION_RVAL: + case A_EXT_FUNCTION_RTEMP: + return "external function"; + case A_ALTSTEP: + return "altstep"; + case A_TESTCASE: + return "testcase"; + case A_PAR_VAL: + case A_PAR_VAL_IN: + return "value parameter"; + case A_PAR_VAL_OUT: + return "`out' value parameter"; + case A_PAR_VAL_INOUT: + return "`inout' value parameter"; + case A_PAR_TEMPL_IN: + return "template parameter"; + case A_PAR_TEMPL_OUT: + return "`out' template parameter"; + case A_PAR_TEMPL_INOUT: + return "`inout' template parameter"; + case A_PAR_TIMER: + return "timer parameter"; + case A_PAR_PORT: + return "port parameter"; + default: + return ""; + } + } + + string Assignment::get_description() + { + string ret_val(get_assname()); + ret_val += " `"; + switch (asstype) { + case A_PAR_VAL: + case A_PAR_VAL_IN: + case A_PAR_VAL_OUT: + case A_PAR_VAL_INOUT: + case A_PAR_TEMPL_IN: + case A_PAR_TEMPL_OUT: + case A_PAR_TEMPL_INOUT: + case A_PAR_TIMER: + case A_PAR_PORT: + // parameter is identified using its id + ret_val += id->get_dispname(); + break; + case A_CONST: + case A_TEMPLATE: + case A_VAR: + case A_VAR_TEMPLATE: + case A_TIMER: + // these can be both local and global + if (is_local()) ret_val += id->get_dispname(); + else ret_val += get_fullname(); + break; + default: + // the rest is always global + ret_val += get_fullname(); + } + ret_val += "'"; + return ret_val; + } + + void Assignment::set_my_scope(Scope *p_scope) + { + my_scope=p_scope; + } + + bool Assignment::is_local() const + { + return false; + } + + Setting *Assignment::get_Setting() + { + FATAL_ERROR("Common::Assignment::get_Setting()"); + return 0; + } + + Type *Assignment::get_Type() + { + FATAL_ERROR("Common::Assignment::get_Type()"); + return 0; + } + + Value *Assignment::get_Value() + { + FATAL_ERROR("Common::Assignment::get_Value()"); + return 0; + } + + Ttcn::Template *Assignment::get_Template() + { + FATAL_ERROR("Common::Assignment::get_Template()"); + return 0; + } + + bool Assignment::get_lazy_eval() const + { + FATAL_ERROR("Common::Assignment::get_lazy_eval()"); + return false; + } + + Ttcn::FormalParList *Assignment::get_FormalParList() + { + return 0; + } + + Ttcn::ArrayDimensions *Assignment::get_Dimensions() + { + return 0; + } + + Type *Assignment::get_RunsOnType() + { + return 0; + } + + void Assignment::chk_ttcn_id() + { + if(!my_scope) return; + if(!get_id().get_has_valid(Identifier::ID_TTCN) + && my_scope->get_parent_scope()==my_scope->get_scope_mod() + // or ... + && my_scope->get_scope_mod()->get_modid().get_dispname()[0]!='<') + warning("The identifier `%s' is not reachable from TTCN-3", + get_id().get_dispname().c_str()); + } + + // *this is the (var/const/modulepar/etc.) definition we want to access. + // p_scope is the location from where we want to reach the definition. + string Assignment::get_genname_from_scope(Scope *p_scope, + const char *p_prefix) + { + if (!p_scope || !my_scope) + FATAL_ERROR("Assignment::get_genname_from_scope()"); + string ret_val; + + Module *my_mod = my_scope->get_scope_mod_gen(); + if ((my_mod != p_scope->get_scope_mod_gen()) && + !Asn::Assignments::is_spec_asss(my_mod)) { + // when the definition is referred from another module + // the reference shall be qualified with the namespace of my module + ret_val = my_mod->get_modid().get_name(); + ret_val += "::"; + } + if (p_prefix) ret_val += p_prefix; + ret_val += get_genname(); + // add the cast to real type if its a lazy formal paramter + switch (asstype) { + case A_PAR_VAL: + case A_PAR_VAL_IN: + case A_PAR_TEMPL_IN: + if (get_lazy_eval() && p_prefix==NULL) { + Type* type = get_Type(); + string type_genname = (asstype==A_PAR_TEMPL_IN) ? type->get_genname_template(p_scope) : type->get_genname_value(p_scope); + ret_val = string("((") + type_genname + string("&)") + ret_val + string(")"); + } + break; + default: + // nothing to do + break; + } + return ret_val; + } + + const char *Assignment::get_module_object_name() + { + if (!my_scope) FATAL_ERROR("Assignment::get_module_object_name()"); + return "module_object"; + } + + void Assignment::use_as_lvalue(const Location&) + { + FATAL_ERROR("Common::Assignment::use_as_lvalue()"); + } + + void Assignment::generate_code(output_struct *, bool) + { + } + + void Assignment::generate_code(CodeGenHelper&) + { + } + + void Assignment::dump(unsigned level) const + { + DEBUG(level, "Assignment: %s (%d)", + id->get_dispname().c_str(), asstype); + } + + Ttcn::Group* Assignment::get_parent_group() + { + return NULL; + } + +} // namespace Common diff --git a/compiler2/AST.hh b/compiler2/AST.hh new file mode 100644 index 0000000..693559c --- /dev/null +++ b/compiler2/AST.hh @@ -0,0 +1,560 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Common_AST_HH +#define _Common_AST_HH + + +#undef new +#include +#include +#include +#include "../common/dbgnew.hh" + +#include "../common/ModuleVersion.hh" +#include "CompilerError.hh" +#include "Setting.hh" +#include "Type.hh" +#include "Value.hh" +#include "vector.hh" + +namespace Ttcn { + // not defined here + class Template; + class FormalParList; + class ArrayDimensions; + class Group; + class Module; +} // namespace Ttcn + +// not defined here +class JSON_Tokenizer; + +/** + * This namespace contains things used both in TTCN-3 + * and ASN.1 compiler. + */ +namespace Common { + + /** + * \defgroup AST AST + * + * These classes provide a unified interface for language entities + * present both in TTCN and ASN. (Most of) the classes defined here + * are abstract, and have a descendant (with the same name) in the + * namespaces Asn and Ttcn. + * + * @{ + */ + + class Identifier; + class Modules; + class Module; + class Assignments; + class Assignment; + class TypeConv; + class CodeGenHelper; + + enum visibility_t { + NOCHANGE, /* for parser usage only; default visibility */ + PUBLIC, /* public visibility */ + PRIVATE, /* private visibility */ + FRIEND /* friend visibility */ + }; + + /** + * Class for storing modules. + * + * This is, in effect, the "root" of the AST: there is only one instance + * of this class (declared in main.cc). + */ + class Modules : public Node { + private: + /** Containers to store the modules. */ + vector mods_v; + map mods_m; + + /** Not implemented */ + Modules(const Modules& p); + Modules& operator=(const Modules& p); + public: + /** The default constructor. */ + Modules(); + /** The destructor. */ + ~Modules(); + /** Not implemented: generates FATAL_ERROR */ + virtual Modules *clone() const; + /** Adds a new module. The uniqueness of identifier is not checked. */ + void add_mod(Module *p_mod); + /** Returns whether a module with the given \a modid exists. */ + bool has_mod_withId(const Identifier& p_modid); + /** Gets the module with the given \a modid. Returns 0 if the + * module does not exist (w/o error message). See also: + * has_mod_withId */ + Module* get_mod_byId(const Identifier& p_modid); + /** Returns the referenced assignment or 0 if it does not exist. + * Append an error message when necessary. */ + Assignment* get_ass_bySRef(Ref_simple *p_ref); + /** Checks the uniqueness of module identifiers. Prints an error + * message if get_modid() returns the same for two + * modules. */ + void chk_uniq(); + /** Performs the semantic analysis on modules of the ATS. + * Generates error/warning messages when necessary */ + void chk(); + void write_checksums(); + std::set getVersionsWithProductNumber() const; + private: + /* Checks the ASN.1 top-level PDU types that were passed as command line + * arguments */ + void chk_top_level_pdus(); + public: + void generate_code(CodeGenHelper& cgh); + void dump(unsigned level=1) const; + + /** Generates JSON schema segments for the types defined in the modules + * and adds them to the JSON schema parameter. */ + void add_types_to_json_schema(JSON_Tokenizer& json); + + /** Generates JSON schemas containing references to the types defined in the + * modules. Information related to the types' JSON encoding and decoding + * functions is also inserted after the references. */ + void add_func_to_json_schema(map& json_refs); + }; + + /** + * Interface-class to represent a module. + * + * Abstract class because of clone() and a bunch of other methods. + */ + class Module : public Scope, public Location { + public: + enum moduletype_t { MOD_UNKNOWN, MOD_ASN, MOD_TTCN }; + /** The map is used as a set. */ + typedef map module_set_t; + protected: // *::Module need access + moduletype_t moduletype; + /** Module identifier ("module name") */ + Identifier *modid; + /** The \c Modules collection which contains this module. Not owned. */ + /** Indicates whether the import list has been checked. */ + bool imp_checked; + /** Indicates whether to generate C++ code for the module. */ + bool gen_code; + /** Indicates whether the module has a checksum. */ + bool has_checksum; + /** Contains the set of modules that are visible through imports (i.e. the + * module is imported either directly or indirectly by an imported module). + * The set is complete if \a this is added to the set. */ + module_set_t visible_mods; + /** Contains the checksum (more correctly, a hash) of the module. + * It is an MD5 hash of the TTCN source, computed by the lexer. */ + unsigned char module_checksum[16]; + + /** @name Containers to store string literals. + * @{ */ + map bs_literals; ///< bitstring values + map bp_literals; ///< bitstring patterns + map hs_literals; ///< hexstring values + map hp_literals; ///< hexstring patterns + map os_literals; ///< octetstring values + map op_literals; ///< octetstring patterns + map cs_literals; ///< charstring values + map us_literals; ///< universal charstring values + map pp_literals; ///< padding patterns (RAW codec) + map mp_literals; ///< matching patterns (TEXT codec) + /** @} */ + + struct OID_literal { + size_t nof_elems; + string oid_id; + }; + map oid_literals; + + /** Counter for the temporary identifiers */ + size_t tmp_id_count; + + /** Control namespace and prefix. + * The module owns these strings. */ + char * control_ns; + char * control_ns_prefix; + + /** Namespace declarations encountered (global for the entire program). + * Keys are the prefixes. Values are the URIs. */ + static map namespaces; + + /** The index of the replacement for the empty prefix, or -1. Returned by + * \p get_ns_index if the empty prefix has indeed been replaced. */ + static size_t replacement_for_empty_prefix; + + /** Namespace prefixes made up to avoid clashes. + * Keys are the URIs (!), values are the prefixes. + * (This is a reverse of a subset of the \p namespaces member). + * This allows reuse of made-up prefixes if the same namespace URI + * appears again. */ + static map invented_prefixes; + + /** Indexes of the namespaces used by this module. + * Written while Common::Type::generate_code_xerdescriptor() makes calls + * to Common::Module::get_ns_index(). */ + map used_namespaces; + + /** How many different namespace URIs with empty prefix have been added */ + static size_t default_namespace_attempt; + + /** Type conversions found in this module */ + vector type_conv_v; + + /** @name Module version fields + * @{ */ + char* product_number; + unsigned int suffix; + unsigned int release; + unsigned int patch; + unsigned int build; + char* extra; + /** @} */ + + friend class Ttcn::Module; + + /* * Value of GLOBAL-DEFAULTS MODIFIED-ENCODINGS */ + //TODO: introduce bool modified_encodings; + + /** Generates code for all string literals that belong to the + * module into \a target */ + void generate_literals(output_struct *target); + /** Generates the module level entry functions based on + * \a output->functions. The resulting functions are placed into + * \a output->source.function_bodies. + * Also writes the control part, module checksum, XML namespaces, + * module object to output->source.global_vars */ + void generate_functions(output_struct *output); + void generate_conversion_functions(output_struct *output); + private: + /** Copy constructor not implemented */ + Module(const Module& p); + /** Assignment disabled */ + Module& operator=(const Module& p); + + /** Adds \a str to container \a literals with prefix \a prefix */ + static string add_literal(map& literals, const string& str, + const char *prefix); + + void generate_bs_literals(char *&src, char *&hdr); + void generate_bp_literals(char *&src, char *&hdr); + void generate_hs_literals(char *&src, char *&hdr); + void generate_hp_literals(char *&src, char *&hdr); + void generate_os_literals(char *&src, char *&hdr); + void generate_op_literals(char *&src, char *&hdr); + void generate_cs_literals(char *&src, char *&hdr); + void generate_us_literals(char *&src, char *&hdr); + void generate_oid_literals(char *&src, char *&hdr); + void generate_pp_literals(char *&src, char *&hdr); + void generate_mp_literals(char *&src, char *&hdr); + + /** Clears the container \a literals */ + static void clear_literals(map& literals); + + public: + Module(moduletype_t p_mt, Identifier *modid); + virtual ~Module(); + /** Adds type conversion \p p_conv to this module. */ + void add_type_conv(TypeConv *p_conv); + /** Checks if \p p_from_type and \p p_to_type types need conversion in + * this module. */ + bool needs_type_conv(Type *p_from_type, Type *p_to_type) const; + /** Returns the module type (either TTCN-3 or ASN.1). */ + moduletype_t get_moduletype() const {return moduletype;} + /** Sets the flag to generate C++ code for this module. */ + void set_gen_code() {gen_code = true;} + /** Returns whether to generate C++ code for this module. */ + bool get_gen_code() const {return gen_code;} + /** Returns the module-identifier. */ + const Identifier& get_modid() const {return *modid;} + /** Gets the module scope. This function returns this scope or a + * scope above this or 0 if neither is a Module. */ + virtual Module* get_scope_mod() {return this;} + virtual Module* get_scope_mod_gen() {return this;} + virtual Assignments *get_asss() =0; + virtual Common::Assignment* importAssignment( + const Identifier& p_source_modid, const Identifier& p_id) const =0; + /** Returns true if a symbol with identifier \a p_id is + * exported. */ + virtual bool exports_sym(const Identifier& p_id) =0; + /** Returns whether the module has an imported definition/assignment with + * identifier \a p_id */ + virtual bool has_imported_ass_withId(const Identifier& p_id) = 0; + /** Returns a pointer to the TTCN-3 special address type that is defined in + * the TTCN-3 module. A NULL pointer is returned if the address type is not + * defined in this module. This function is applicable to TTCN-3 modules + * only (otherwise a FATAL_ERROR will occur). */ + virtual Type *get_address_type(); + /** Checks imports (and propagates the code generation + * flags). */ + virtual void chk_imp(ReferenceChain& refch, vector& moduleStack) = 0; + /** Checks everything (imports, exports, assignments) */ + virtual void chk() = 0; + /** Checks this module and all imported modules in bottom-up order. + * Argument \a checked_modules contains the list of modules that are + * already checked */ + void chk_recursive(module_set_t& checked_modules); + /** Returns whether \a m is visible from \a this through imports. */ + bool is_visible(Module *m); + /** Extends \a p_visible_mods with the set of visible modules. It uses the + * cache \a visible_mods if possible or calls \a get_imported_mods() + * otherwise. */ + void get_visible_mods(module_set_t& p_visible_mods); + /** Walks through the import list and collects the imported modules into + * \a p_imported_mods recursively. */ + virtual void get_imported_mods(module_set_t& p_imported_mods) = 0; + void write_checksum(); + static char* get_product_identifier(const char* product_number, + const unsigned int suffix, unsigned int release, unsigned int patch, + unsigned int build, const char* extra=NULL); + ModuleVersion getVersion() const; + protected: // *::Module need access + /** Collects the set of visible modules into \a visible_mods. */ + void collect_visible_mods(); + virtual void generate_code_internal(CodeGenHelper& cgh) = 0; + public: + /** Adds a string to the module's bitstring container. Returns a + * string like "bs_xx", where xx is the index of the literal in + * the container. */ + inline string add_bitstring_literal(const string& bstr) + { return add_literal(bs_literals, bstr, "bs_"); } + inline string add_bitstring_pattern(const string& bpat) + { return add_literal(bp_literals, bpat, "bp_"); } + inline string add_hexstring_literal(const string& hstr) + { return add_literal(hs_literals, hstr, "hs_"); } + inline string add_hexstring_pattern(const string& hpat) + { return add_literal(hp_literals, hpat, "hp_"); } + inline string add_octetstring_literal(const string& ostr) + { return add_literal(os_literals, ostr, "os_"); } + inline string add_octetstring_pattern(const string& opat) + { return add_literal(op_literals, opat, "op_"); } + inline string add_charstring_literal(const string& cstr) + { return add_literal(cs_literals, cstr, "cs_"); } + inline string add_padding_pattern(const string& ppat) + { return add_literal(pp_literals, ppat, "pp_"); } + inline string add_matching_literal(const string& mpat) + { return add_literal(mp_literals, mpat, "mp_"); } + string add_ustring_literal(const ustring& ustr); + string add_objid_literal(const string& oi_str, const size_t nof_elems); + + /** Sets the module checksum. Parameter \a checksum_ptr points to the + * checksum to be set, which consists of \a checksum_len bytes. */ + void set_checksum(size_t checksum_len, const unsigned char* checksum_ptr); + + /** Returns an identifier used for temporary C++ objects, + * which is unique in the module */ + string get_temporary_id(); + + /** Sets the control namespace and its prefix. + * Any previous value is overwritten. + * Takes ownership of the strings (must be allocated on the heap). */ + void set_controlns(char *ns, char *prefix); + + /** Gets the control namespace components. + * The caller must not free the strings. */ + void get_controlns(const char * &ns, const char * &prefix); + + /** Adds a namespace to the list of known namespaces. + * No effect if the namespace is already in the map. + * @param new_uri namespace URI + * @param new_prefix namespace prefix; NULL means "make up a prefix" + * @note If \p new_prefix is empty and there is already a namespace with + * an empty prefix, a new, non-empty prefix is invented for this URI; + * in this case \p new_prefix is modified to contain the "made-up" value. + * @note \p new_prefix \b MUST be expstring_t or allocated by Malloc + * (add_namespace may call Free() on it) */ + static void add_namespace(const char *new_uri, char * &new_prefix); + + /** Returns the number of XML namespaces */ + static inline size_t get_nof_ns() + { return namespaces.size(); } + + /** Return the index of the given namespace prefix in the list of namespaces. + * If the namespace is not found, FATAL_ERROR occurs. + * @note also records the index in the per-instance member used_namespaces + * (which is why it cannot be static) */ + size_t get_ns_index(const char *prefix); + + /** Rename the default namespace, but only if there were two or more + * namespaces with empty prefixes */ + static void rename_default_namespace(); + + /** Generates C++ code for the module */ + void generate_code(CodeGenHelper& cgh); + virtual void dump(unsigned level) const; + + /** Generates JSON schema segments for the types defined in the module + * and adds them to the JSON schema parameter. */ + virtual void add_types_to_json_schema(JSON_Tokenizer&) = 0; + + /** Generates JSON schemas containing references to the types that have JSON + * encoding and/or decoding functions declared in the module. Information + * related to these functions is also inserted after the references + * (only for TTCN-3 modules). */ + virtual void add_func_to_json_schema(map&) = 0; + }; + + /** + * Class to store assignments. + */ + class Assignments : public Scope { + protected: // Ttcn::Definitions and Asn::Assignments need access + + Assignments(const Assignments& p): Scope(p) {} + public: + /** Constructor. */ + Assignments() : Scope() {} + + virtual Assignments* get_scope_asss(); + /** Returns the referenced assignment or 0 if it does not exist. + * An error message is generated when necessary. */ + virtual Assignment* get_ass_bySRef(Ref_simple *p_ref); + /** Returns whether an assignment with id \a p_id exists; + * either in the current scope or its parent (recursively). */ + virtual bool has_ass_withId(const Identifier& p_id); + /** Returns whether an assignment with id \a p_id exists. + * Unlike \a has_ass_withId() this function does not look into the + * parent scope. */ + virtual bool has_local_ass_withId(const Identifier& p_id) = 0; + /** Returns the locally defined assignment with the given id, + * or NULL if it does not exist. */ + virtual Assignment* get_local_ass_byId(const Identifier& p_id) = 0; + /** Returns the number of assignments. Only the uniquely named + * assignments are visible. */ + virtual size_t get_nof_asss() = 0; + /** Returns the assignment with the given index. Only the uniquely + * named assignments are visible. */ + virtual Assignment* get_ass_byIndex(size_t p_i) = 0; + }; + + /** + * Abstract class to represent different kinds of assignments. + */ + class Assignment : public Node, public Location { + public: + enum asstype_t { + A_TYPE, /**< type */ + A_CONST, /**< value (const) */ + A_UNDEF, /**< undefined/undecided (ASN.1) */ + A_ERROR, /**< erroneous; the kind cannot be deduced (ASN.1) */ + A_OC, /**< information object class (ASN.1) */ + A_OBJECT, /**< information object (ASN.1) */ + A_OS, /**< information object set (ASN.1) */ + A_VS, /**< value set (ASN.1) */ + A_EXT_CONST, /**< external constant (TTCN-3) */ + A_MODULEPAR, /**< module parameter (TTCN-3) */ + A_MODULEPAR_TEMP, /**< template module parameter */ + A_TEMPLATE, /**< template (TTCN-3) */ + A_VAR, /**< variable (TTCN-3) */ + A_VAR_TEMPLATE, /**< template variable, dynamic template (TTCN-3) */ + A_TIMER, /**< timer (TTCN-3) */ + A_PORT, /**< port (TTCN-3) */ + A_FUNCTION, /**< function without return type (TTCN-3) */ + A_FUNCTION_RVAL, /**< function that returns a value (TTCN-3) */ + A_FUNCTION_RTEMP, /**< function that returns a template (TTCN-3) */ + A_EXT_FUNCTION, /**< external function without return type (TTCN-3) */ + A_EXT_FUNCTION_RVAL, /**< ext. func that returns a value (TTCN-3) */ + A_EXT_FUNCTION_RTEMP, /**< ext. func that returns a template (TTCN-3) */ + A_ALTSTEP, /**< altstep (TTCN-3) */ + A_TESTCASE, /**< testcase (TTCN-3) */ + A_PAR_VAL, /**< formal parameter (value) (TTCN-3) */ + A_PAR_VAL_IN, /**< formal parameter (in value) (TTCN-3) */ + A_PAR_VAL_OUT, /**< formal parameter (out value) (TTCN-3) */ + A_PAR_VAL_INOUT, /**< formal parameter (inout value) (TTCN-3) */ + A_PAR_TEMPL_IN, /**< formal parameter ([in] template) (TTCN-3) */ + A_PAR_TEMPL_OUT, /**< formal parameter (out template) (TTCN-3) */ + A_PAR_TEMPL_INOUT,/**< formal parameter (inout template) (TTCN-3) */ + A_PAR_TIMER, /**< formal parameter (timer) (TTCN-3) */ + A_PAR_PORT /**< formal parameter (port) (TTCN-3) */ + }; + protected: // Ttcn::Definition and Asn::Assignment need access + asstype_t asstype; + Identifier *id; /**< the name of the assignment */ + Scope *my_scope; /**< the scope this assignment belongs to */ + bool checked; + visibility_t visibilitytype; + + /// Copy constructor disabled + Assignment(const Assignment& p); + /// Assignment disabled + Assignment& operator=(const Assignment& p); + virtual string get_genname() const = 0; + public: + Assignment(asstype_t p_asstype, Identifier *p_id); + virtual ~Assignment(); + virtual Assignment* clone() const =0; + virtual asstype_t get_asstype() const; + /** Returns the string representation of the assignment type */ + const char *get_assname() const; + /** Returns the description of the definition, which consists of the + * assignment type and name. The name is either the fullname or only + * the id. It depends on \a asstype and \a my_scope. */ + string get_description(); + /** Gets the id of the assignment. */ + const Identifier& get_id() const {return *id;} + /** Sets the internal pointer my_scope to \a p_scope. */ + virtual void set_my_scope(Scope *p_scope); + Scope* get_my_scope() const { return my_scope; } + bool get_checked() const { return checked; } + /** Return the visibility type of the assignment */ + visibility_t get_visibility() const { return visibilitytype; } + /** Returns whether the definition belongs to a TTCN-3 statement block + * (i.e. it is defined in the body of a function, testcase, altstep or + * control part). */ + virtual bool is_local() const; + /** @name Need to be overridden and implemented in derived classes. + * Calling these methods causes a FATAL_ERROR. + * + * @{ + */ + virtual Setting* get_Setting(); + virtual Type *get_Type(); + virtual Value *get_Value(); + virtual Ttcn::Template *get_Template(); + virtual bool get_lazy_eval() const; + /** @} */ + /** Returns the formal parameter list of a TTCN-3 definition */ + virtual Ttcn::FormalParList *get_FormalParList(); + /** Returns the dimensions of TTCN-3 port and timer arrays or NULL + * otherwise. */ + virtual Ttcn::ArrayDimensions *get_Dimensions(); + /** Returns the component type referred by the 'runs on' clause of a + * TTCN-3 definition */ + virtual Type *get_RunsOnType(); + /** Semantic check */ + virtual void chk() = 0; + /** Checks whether the assignment has a valid TTCN-3 identifier, + * i.e. is reachable from TTCN. */ + void chk_ttcn_id(); + /** Returns a string containing the C++ reference pointing to this + * definition from the C++ equivalent of scope \a p_scope. The reference + * is a simple identifier qualified with a namespace when necessary. + * If \a p_prefix is not NULL it is inserted before the string returned by + * function \a get_genname(). */ + string get_genname_from_scope(Scope *p_scope, const char *p_prefix = 0); + /** Returns the name of the C++ object in the RTE that contains the common + * entry points for the module that the definition belongs to */ + const char *get_module_object_name(); + /** A stub function to avoid dynamic_cast's. It causes FATAL_ERROR unless + * \a this is an `in' value or template parameter. The real implementation + * is in class Ttcn::FormalPar. */ + virtual void use_as_lvalue(const Location& p_loc); + virtual void generate_code(output_struct *target, bool clean_up = false); + virtual void generate_code(CodeGenHelper& cgh); // FIXME: this should be pure virtual + virtual void dump(unsigned level) const; + virtual Ttcn::Group* get_parent_group(); + }; + + /** @} end of AST group */ + +} // namespace Common + +#endif // _Common_AST_HH diff --git a/compiler2/Code.cc b/compiler2/Code.cc new file mode 100644 index 0000000..f9769d9 --- /dev/null +++ b/compiler2/Code.cc @@ -0,0 +1,244 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "Code.hh" +#include "../common/memory.h" +#include "error.h" + +#include + +namespace Common { + + // ================================= + // ===== Code + // ================================= + + void Code::init_output(output_struct *output) + { + output->header.includes = NULL; + output->header.class_decls = NULL; + output->header.typedefs = NULL; + output->header.class_defs = NULL; + output->header.function_prototypes = NULL; + output->header.global_vars = NULL; + output->header.testport_includes = NULL; + output->source.includes = NULL; + output->source.static_function_prototypes = NULL; + output->source.static_conversion_function_prototypes = NULL; + output->source.string_literals = NULL; + output->source.class_defs = NULL; + output->source.global_vars = NULL; + output->source.methods = NULL; + output->source.function_bodies = NULL; + output->source.static_function_bodies = NULL; + output->source.static_conversion_function_bodies = NULL; + output->functions.pre_init = NULL; + output->functions.post_init = NULL; + output->functions.set_param = NULL; + output->functions.log_param = NULL; + output->functions.init_comp = NULL; + output->functions.start = NULL; + output->functions.control = NULL; + } + + void Code::merge_output(output_struct *dest, output_struct *src) + { + dest->header.includes = + mputstr(dest->header.includes, src->header.includes); + dest->header.class_decls = + mputstr(dest->header.class_decls, src->header.class_decls); + dest->header.typedefs = + mputstr(dest->header.typedefs, src->header.typedefs); + dest->header.class_defs = + mputstr(dest->header.class_defs, src->header.class_defs); + dest->header.function_prototypes = + mputstr(dest->header.function_prototypes, + src->header.function_prototypes); + dest->header.global_vars = + mputstr(dest->header.global_vars, src->header.global_vars); + dest->header.testport_includes = + mputstr(dest->header.testport_includes, src->header.testport_includes); + dest->source.includes = + mputstr(dest->source.includes, src->source.includes); + dest->source.static_function_prototypes = + mputstr(dest->source.static_function_prototypes, + src->source.static_function_prototypes); + dest->source.static_conversion_function_prototypes = + mputstr(dest->source.static_conversion_function_prototypes, + src->source.static_conversion_function_prototypes); + dest->source.string_literals = + mputstr(dest->source.string_literals, src->source.string_literals); + dest->source.class_defs = + mputstr(dest->source.class_defs, src->source.class_defs); + dest->source.global_vars = + mputstr(dest->source.global_vars, src->source.global_vars); + dest->source.methods = + mputstr(dest->source.methods, src->source.methods); + dest->source.function_bodies = + mputstr(dest->source.function_bodies, src->source.function_bodies); + dest->source.static_function_bodies = + mputstr(dest->source.static_function_bodies, + src->source.static_function_bodies); + dest->source.static_conversion_function_bodies = + mputstr(dest->source.static_conversion_function_bodies, + src->source.static_conversion_function_bodies); + dest->functions.pre_init = + mputstr(dest->functions.pre_init, src->functions.pre_init); + dest->functions.post_init = + mputstr(dest->functions.post_init, src->functions.post_init); + dest->functions.set_param = + mputstr(dest->functions.set_param, src->functions.set_param); + dest->functions.log_param = + mputstr(dest->functions.log_param, src->functions.log_param); + dest->functions.init_comp = + mputstr(dest->functions.init_comp, src->functions.init_comp); + dest->functions.start = + mputstr(dest->functions.start, src->functions.start); + dest->functions.control = + mputstr(dest->functions.control, src->functions.control); + } + + void Code::free_output(output_struct *output) + { + Free(output->header.includes); + Free(output->header.class_decls); + Free(output->header.typedefs); + Free(output->header.class_defs); + Free(output->header.function_prototypes); + Free(output->header.global_vars); + Free(output->header.testport_includes); + Free(output->source.includes); + Free(output->source.static_function_prototypes); + Free(output->source.static_conversion_function_prototypes); + Free(output->source.string_literals); + Free(output->source.class_defs); + Free(output->source.global_vars); + Free(output->source.methods); + Free(output->source.function_bodies); + Free(output->source.static_function_bodies); + Free(output->source.static_conversion_function_bodies); + Free(output->functions.pre_init); + Free(output->functions.post_init); + Free(output->functions.set_param); + Free(output->functions.log_param); + Free(output->functions.init_comp); + Free(output->functions.start); + Free(output->functions.control); + init_output(output); + } + + void Code::init_cdef(const_def *cdef) + { + cdef->decl = NULL; + cdef->def = NULL; + //cdef->cdef = NULL; + cdef->init = NULL; + } + + void Code::merge_cdef(output_struct *dest, const_def *cdef) + { + dest->header.global_vars = mputstr(dest->header.global_vars, cdef->decl); + dest->source.global_vars = mputstr(dest->source.global_vars, cdef->def); + dest->functions.pre_init = mputstr(dest->functions.pre_init, cdef->init); + } + + void Code::free_cdef(const_def *cdef) + { + Free(cdef->decl); + Free(cdef->def); + //Free(cdef->cdef); + Free(cdef->init); + } + + void Code::init_expr(expression_struct *expr) + { + expr->preamble = NULL; + expr->expr = NULL; + expr->postamble = NULL; + } + + void Code::clean_expr(expression_struct *expr) + { + Free(expr->expr); + expr->expr = NULL; + } + + void Code::free_expr(expression_struct *expr) + { + Free(expr->preamble); + Free(expr->expr); + Free(expr->postamble); + } + + char* Code::merge_free_expr(char* str, expression_struct *expr, + bool is_block) + { + if (expr->preamble || expr->postamble) { + // open a statement block if the expression has a preamble or postamble + str = mputstr(str, "{\n"); + // append the preamble if present + if (expr->preamble) str = mputstr(str, expr->preamble); + } + // append the expression itself + str = mputstr(str, expr->expr); + // terminate it with a bracket or semi-colon + if (is_block) str = mputstr(str, "}\n"); + else str = mputstr(str, ";\n"); + if (expr->preamble || expr->postamble) { + // append the postamble if present + if (expr->postamble) str = mputstr(str, expr->postamble); + // close the statement block + str = mputstr(str, "}\n"); + } + free_expr(expr); + return str; + } + + char *Code::translate_character(char *str, char c, bool in_string) + { + int i = (unsigned char)c; + switch (i) { + case '\a': + return mputstr(str, "\\a"); + case '\b': + return mputstr(str, "\\b"); + case '\f': + return mputstr(str, "\\f"); + case '\n': + return mputstr(str, "\\n"); + case '\r': + return mputstr(str, "\\r"); + case '\t': + return mputstr(str, "\\t"); + case '\v': + return mputstr(str, "\\v"); + case '\\': + return mputstr(str, "\\\\"); + case '\'': + if (in_string) return mputc(str, '\''); + else return mputstr(str, "\\'"); + case '"': + if (in_string) return mputstr(str, "\\\""); + else return mputc(str, '"'); + case '?': + // to avoid recognition of trigraphs + if (in_string) return mputstr(str, "\\?"); + else return mputc(str, '?'); + default: + if (isascii(i) && isprint(i)) return mputc(str, c); + return mputprintf(str, in_string ? "\\%03o" : "\\%o", i); + } + } + + char *Code::translate_string(char *str, const char *src) + { + for (size_t i = 0; src[i] != '\0'; i++) + str = translate_character(str, src[i], true); + return str; + } + +} // namespace Common diff --git a/compiler2/Code.hh b/compiler2/Code.hh new file mode 100644 index 0000000..8f8cac7 --- /dev/null +++ b/compiler2/Code.hh @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Common_Code_HH +#define _Common_Code_HH + +#include "ttcn3/compiler.h" + +namespace Common { + + /** + * \addtogroup AST + * + * @{ + */ + + /** + * Abstract class for storing Code. + */ + class Code { + public: + + static void init_output(output_struct *output); + static void merge_output(output_struct *dest, output_struct *src); + static void free_output(output_struct *output); + + static void init_cdef(const_def *cdef); + static void merge_cdef(output_struct *dest, const_def *cdef); + static void free_cdef(const_def *cdef); + + static void init_expr(expression_struct *expr); + static void clean_expr(expression_struct *expr); + static void free_expr(expression_struct *expr); + static char* merge_free_expr(char* str, expression_struct *expr, + bool is_block=false); + + /** Appends the C/C++ equivalent of character \a c to \a str. If flag + * \a in_string is true (i.e. the \a c is a part of a string literal) then + * the " character is escaped, otherwise (i.e. the \a c is a character + * constant) ' is escaped. The function uses the standard C escape sequences + * if possible or the octal notation for non-printable characters. */ + static char *translate_character(char *str, char c, bool in_string); + /** Appends the C/C++ equivalent of literal string \a src to \a str. */ + static char *translate_string(char *str, const char *src); + }; + + /** @} end of AST group */ + +} // namespace Common + +#endif // _Common_Code_HH diff --git a/compiler2/CodeGenHelper.cc b/compiler2/CodeGenHelper.cc new file mode 100644 index 0000000..d096883 --- /dev/null +++ b/compiler2/CodeGenHelper.cc @@ -0,0 +1,307 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "CodeGenHelper.hh" +#include "Code.hh" +#include "error.h" +#include "main.hh" +#include +#include + +namespace Common { + +CodeGenHelper* CodeGenHelper::instance = 0; + +CodeGenHelper::generated_output_t::generated_output_t() : + is_module(false), + is_ttcn(true), + has_circular_import(false) +{ + Code::init_output(&os); +} + +CodeGenHelper::generated_output_t::~generated_output_t() { + Code::free_output(&os); +} + +// from Type.cc +const char* const CodeGenHelper::typetypemap[] = { + "", /**< undefined */ + "", /**< erroneous (e.g. nonexistent reference) */ + "", /**< null (ASN.1) */ + "", /**< boolean */ + "", /**< integer */ + "", /**< integer / ASN */ + "", /**< real/float */ + "", /**< enumerated / ASN */ + "", /**< enumerated / TTCN */ + "", /**< bitstring */ + "", /**< bitstring */ + "", /**< hexstring (TTCN-3) */ + "", /**< octetstring */ + "", /**< charstring (TTCN-3) */ + "", /**< universal charstring (TTCN-3) */ + "", /**< UTF8String (ASN.1) */ + "", /**< NumericString (ASN.1) */ + "", /**< PrintableString (ASN.1) */ + "", /**< TeletexString (ASN.1) */ + "", /**< VideotexString (ASN.1) */ + "", /**< IA5String (ASN.1) */ + "", /**< GraphicString (ASN.1) */ + "", /**< VisibleString (ASN.1) */ + "", /**< GeneralString (ASN.1) */ + "", /**< UniversalString (ASN.1) */ + "", /**< BMPString (ASN.1) */ + "", /**< UnrestrictedCharacterString (ASN.1) */ + "", /**< UTCTime (ASN.1) */ + "", /**< GeneralizedTime (ASN.1) */ + "", /** Object descriptor, a kind of string (ASN.1) */ + "", /**< object identifier */ + "", /**< relative OID (ASN.1) */ + "_union", /**< choice /ASN, uses u.secho */ + "_union", /**< union /TTCN, uses u.secho */ + "_seqof", /**< sequence (record) of */ + "_setof", /**< set of */ + "_seq", /**< sequence /ASN, uses u.secho */ + "_seq", /**< record /TTCN, uses u.secho */ + "_set", /**< set /ASN, uses u.secho */ + "_set", /**< set /TTCN, uses u.secho */ + "", /**< ObjectClassFieldType (ASN.1) */ + "", /**< open type (ASN.1) */ + "", /**< ANY (deprecated ASN.1) */ + "", /**< %EXTERNAL (ASN.1) */ + "", /**< EMBEDDED PDV (ASN.1) */ + "", /**< referenced */ + "", /**< special referenced (by pointer, not by name) */ + "", /**< selection type (ASN.1) */ + "", /**< verdict type (TTCN-3) */ + "", /**< port type (TTCN-3) */ + "", /**< component type (TTCN-3) */ + "", /**< address type (TTCN-3) */ + "", /**< default type (TTCN-3) */ + "", /**< array (TTCN-3), uses u.array */ + "", /**< signature (TTCN-3) */ + "", /**< function reference (TTCN-3) */ + "", /**< altstep reference (TTCN-3) */ + "", /**< testcase reference (TTCN-3) */ + "", /**< anytype (TTCN-3) */ + 0 +}; + +CodeGenHelper::CodeGenHelper() : + split_mode(SPLIT_NONE) +{ + if (instance != 0) + FATAL_ERROR("Attempted to create a second code generator."); + instance = this; +} + +CodeGenHelper& CodeGenHelper::GetInstance() { + if (instance == 0) + FATAL_ERROR("Trying to access to the already destroyed code generator."); + return *instance; +} + +void CodeGenHelper::set_split_mode(split_type st) { + split_mode = st; +} + +bool CodeGenHelper::set_split_mode(const char* type) { + if (strcmp(type, "none") == 0) + split_mode = SPLIT_NONE; + else if (strcmp(type, "type") == 0) + split_mode = SPLIT_BY_KIND; + else + return false; + return true; +} + +CodeGenHelper::split_type CodeGenHelper::get_split_mode() const { + return split_mode; +} + +void CodeGenHelper::add_module(const string& name, const string& dispname, + bool is_ttcn, bool has_circular_import) { + generated_output_t* go = new generated_output_t; + go->filename.clear(); + go->modulename = name; + go->module_dispname = dispname; + go->is_module = true; + go->is_ttcn = is_ttcn; + go->has_circular_import = has_circular_import; + generated_code.add(dispname, go); + module_names_t* mod_names = new module_names_t; + mod_names->name = name; + mod_names->dispname = dispname; + modules.add(mod_names); +} + +output_struct* CodeGenHelper::get_outputstruct(const string& name) { + return &generated_code[name]->os; +} + +void CodeGenHelper::set_current_module(const string& name) { + current_module = name; +} + +output_struct* CodeGenHelper::get_outputstruct(Ttcn::Definition* def) { + string key = get_key(*def); + const string& new_name = current_module + key; + if (!generated_code.has_key(new_name)) { + generated_output_t* go = new generated_output_t; + go->filename = key; + go->modulename = generated_code[current_module]->modulename; + go->module_dispname = generated_code[current_module]->module_dispname; + generated_code.add(new_name, go); + go->os.source.includes = mprintf("\n#include \"%s.hh\"\n" + , current_module.c_str()); + } + return &generated_code[new_name]->os; +} + +output_struct* CodeGenHelper::get_outputstruct(Type* type) { + string key = get_key(*type); + const string& new_name = current_module + key; + if (!generated_code.has_key(new_name)) { + generated_output_t* go = new generated_output_t; + go->filename = key; + go->modulename = generated_code[current_module]->modulename; + go->module_dispname = generated_code[current_module]->module_dispname; + generated_code.add(new_name, go); + go->os.source.includes = mprintf("\n#include \"%s.hh\"\n" + , current_module.c_str()); + } + return &generated_code[new_name]->os; +} + +output_struct* CodeGenHelper::get_current_outputstruct() { + return &generated_code[current_module]->os; +} + +void CodeGenHelper::transfer_value(char* &dst, char* &src) { + dst = mputstr(dst, src); + Free(src); + src = 0; +} + +void CodeGenHelper::finalize_generation(Type* type) { + string key = get_key(*type); + if (key.empty()) return; + + output_struct& dst = *get_current_outputstruct(); + output_struct& src = *get_outputstruct(current_module + key); + // key is not empty so these can never be the same + + transfer_value(dst.header.includes, src.header.includes); + transfer_value(dst.header.class_decls, src.header.class_decls); + transfer_value(dst.header.typedefs, src.header.typedefs); + transfer_value(dst.header.class_defs, src.header.class_defs); + transfer_value(dst.header.function_prototypes, src.header.function_prototypes); + transfer_value(dst.header.global_vars, src.header.global_vars); + transfer_value(dst.header.testport_includes, src.header.testport_includes); + + transfer_value(dst.source.global_vars, src.source.global_vars); + + transfer_value(dst.functions.pre_init, src.functions.pre_init); + transfer_value(dst.functions.post_init, src.functions.post_init); + + transfer_value(dst.functions.set_param, src.functions.set_param); + transfer_value(dst.functions.log_param, src.functions.log_param); + transfer_value(dst.functions.init_comp, src.functions.init_comp); + transfer_value(dst.functions.start, src.functions.start); + transfer_value(dst.functions.control, src.functions.control); +} + +string CodeGenHelper::get_key(Ttcn::Definition& def) const { + string retval; + switch (split_mode) { + case SPLIT_NONE: + // returns the current module + break; + case SPLIT_BY_KIND: + break; + case SPLIT_BY_NAME: + retval += "_" + def.get_id().get_name(); + break; + case SPLIT_BY_HEURISTICS: + break; + } + return retval; +} + +string CodeGenHelper::get_key(Type& type) const { + string retval; + switch (split_mode) { + case SPLIT_NONE: + break; + case SPLIT_BY_KIND: { + Type::typetype_t tt = type.get_typetype(); + switch(tt) { + case Type::T_CHOICE_A: + case Type::T_CHOICE_T: + case Type::T_SEQOF: + case Type::T_SETOF: + case Type::T_SEQ_A: + case Type::T_SEQ_T: + case Type::T_SET_A: + case Type::T_SET_T: + retval += typetypemap[(int)tt]; + break; + default: + // put it into the module (no suffix) + break; + } + break; } + case SPLIT_BY_NAME: + break; + case SPLIT_BY_HEURISTICS: + break; + } + return retval; +} + +void CodeGenHelper::write_output() { + size_t i, j; + if (split_mode == SPLIT_BY_KIND) { + // Create empty files to have a fix set of files to compile + string fname; + for (j = 0; j < modules.size(); j++) { + for (i = 0; typetypemap[i]; i++) { + fname = modules[j]->dispname + typetypemap[i]; + if (!generated_code.has_key(fname)) { + generated_output_t* go = new generated_output_t; + go->filename = typetypemap[i]; + go->modulename = modules[j]->name; + go->module_dispname = modules[j]->dispname; + go->os.source.includes = mcopystr( + "\n//This file intentionally empty." + "\n#include \n"); + generated_code.add(fname, go); + } + } + } + } + generated_output_t* go; + for (i = 0; i < generated_code.size(); i++) { + go = generated_code.get_nth_elem(i); + ::write_output(&go->os, go->modulename.c_str(), go->module_dispname.c_str(), + go->filename.c_str(), go->is_ttcn, go->has_circular_import, go->is_module); + } +} + +CodeGenHelper::~CodeGenHelper() { + size_t i; + for (i = 0; i < generated_code.size(); i++) + delete generated_code.get_nth_elem(i); + generated_code.clear(); + for (i = 0; i < modules.size(); i++) + delete modules[i]; + modules.clear(); + instance = 0; +} + +} diff --git a/compiler2/CodeGenHelper.hh b/compiler2/CodeGenHelper.hh new file mode 100644 index 0000000..cee1242 --- /dev/null +++ b/compiler2/CodeGenHelper.hh @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Common_CodeGenHelper_HH +#define _Common_CodeGenHelper_HH + +#include "ttcn3/compiler.h" +#include "map.hh" +#include "vector.hh" +#include "string.hh" +#include "ttcn3/AST_ttcn3.hh" +#include "Type.hh" + +namespace Ttcn { +class Definition; +} + +namespace Common { + +class CodeGenHelper { +public: + enum split_type { + SPLIT_NONE, ///< original code generation + SPLIT_BY_KIND, ///< place different kind of types in their own file + SPLIT_BY_NAME, ///< place all definitions/assignments in their own file + SPLIT_BY_HEURISTICS ///< heuristic function will decide the structure + }; + +private: + struct generated_output_t { + + generated_output_t(); + ~generated_output_t(); + + output_struct os; + string modulename; + string module_dispname; + string filename; + bool is_module; + bool is_ttcn; + bool has_circular_import; + }; + + static const char* const typetypemap[]; + + typedef map output_map_t; + + output_map_t generated_code; + split_type split_mode; + + struct module_names_t { + string name; + string dispname; + }; + + vector modules; + string current_module; + + static CodeGenHelper* instance; + +public: + CodeGenHelper(); + + static CodeGenHelper& GetInstance(); + + void set_split_mode(split_type st); + bool set_split_mode(const char* type); + split_type get_split_mode() const; + + void add_module(const string& name, const string& dispname, bool is_ttcn, + bool has_circular_import); + output_struct* get_outputstruct(const string& name); + output_struct* get_outputstruct(Ttcn::Definition* def); + output_struct* get_outputstruct(Type* type); + output_struct* get_current_outputstruct(); + void finalize_generation(Type* type); + + void set_current_module(const string& name); + + void write_output(); + + ~CodeGenHelper(); + +private: + string get_key(Ttcn::Definition& def) const; + string get_key(Type& type) const; + static void transfer_value(char* &dst, char* &src); +}; + +} + +#endif /* _Common_CodeGenHelper_HH */ diff --git a/compiler2/CompField.cc b/compiler2/CompField.cc new file mode 100644 index 0000000..07a7b0a --- /dev/null +++ b/compiler2/CompField.cc @@ -0,0 +1,205 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "CompField.hh" +#include "Type.hh" +#include "Value.hh" +#include "CompilerError.hh" + +namespace Common { + +// ================================= +// ===== CompField +// ================================= + +CompField::CompField(Identifier *p_name, Type *p_type, bool p_is_optional, + Value *p_defval) + : Node(), Location(), name(p_name), type(p_type), + is_optional(p_is_optional), defval(p_defval), rawattrib(0) +{ + if(!p_name || !p_type) + FATAL_ERROR("NULL parameter: Common::CompField::CompField()"); + type->set_ownertype(Type::OT_COMP_FIELD, this); +} + +CompField::CompField(const CompField& p) + : Node(p), Location(p), is_optional(p.is_optional), rawattrib(0) +{ + name=p.name->clone(); + type=p.type->clone(); + type->set_ownertype(Type::OT_COMP_FIELD, this); + defval=p.defval?p.defval->clone():0; +} + +CompField::~CompField() +{ + delete name; + delete type; + delete defval; + delete rawattrib; +} + +CompField *CompField::clone() const +{ + return new CompField(*this); +} + +void CompField::set_fullname(const string& p_fullname) +{ + string base_name(p_fullname + "." + name->get_dispname()); + Node::set_fullname(base_name); + type->set_fullname(base_name); + if (defval) defval->set_fullname(base_name + "."); +} + +void CompField::set_my_scope(Scope *p_scope) +{ + type->set_my_scope(p_scope); + if (defval) defval->set_my_scope(p_scope); +} + +void CompField::set_raw_attrib(RawAST* r_attr) +{ + delete rawattrib; + rawattrib=r_attr; +} + +void CompField::dump(unsigned level) const +{ + name->dump(level); + type->dump(level + 1); + if(is_optional) + DEBUG(level + 1, "optional"); + if(defval) { + DEBUG(level + 1, "with default value"); + defval->dump(level + 2); + } +} + +// ================================= +// ===== CompFieldMap +// ================================= + +CompFieldMap::CompFieldMap(const CompFieldMap& p) + : Node(p), my_type(0), checked(false) +{ + size_t nof_comps = p.v.size(); + for (size_t i = 0; i < nof_comps; i++) v.add(p.v[i]->clone()); +} + +CompFieldMap::~CompFieldMap() +{ + size_t nof_comps = v.size(); + for (size_t i = 0; i < nof_comps; i++) delete v[i]; + v.clear(); + m.clear(); +} + +CompFieldMap *CompFieldMap::clone() const +{ + return new CompFieldMap(*this); +} + +void CompFieldMap::set_fullname(const string& p_fullname) +{ + Node::set_fullname(p_fullname); + size_t nof_comps = v.size(); + for (size_t i = 0; i < nof_comps; i++) v[i]->set_fullname(p_fullname); +} + +void CompFieldMap::set_my_scope(Scope *p_scope) +{ + size_t nof_comps = v.size(); + for (size_t i = 0; i < nof_comps; i++) v[i]->set_my_scope(p_scope); +} + +void CompFieldMap::add_comp(CompField *comp) +{ + v.add(comp); + if (checked) { + const string& name = comp->get_name().get_name(); + if (m.has_key(name)) FATAL_ERROR("CompFieldMap::add_comp(%s)", name.c_str()); + m.add(name, comp); + } +} + +bool CompFieldMap::has_comp_withName(const Identifier& p_name) +{ + if (!checked) chk_uniq(); + return m.has_key(p_name.get_name()); +} + +CompField* CompFieldMap::get_comp_byName(const Identifier& p_name) +{ + if (!checked) chk_uniq(); + return m[p_name.get_name()]; +} + +const char *CompFieldMap::get_typetype_name() const +{ + if (!my_type) FATAL_ERROR("CompFieldMap::get_typetype_name()"); + switch (my_type->get_typetype()) { + case Type::T_ANYTYPE: + return "anytype"; + case Type::T_CHOICE_T: + return "union"; + case Type::T_SEQ_T: + return "record"; + case Type::T_SET_T: + return "set"; + case Type::T_OPENTYPE: + return "open type"; + default: + return ""; + } +} + +void CompFieldMap::chk_uniq() +{ + if (checked) return; + const char *typetype_name = get_typetype_name(); + size_t nof_comps = v.size(); + for (size_t i = 0; i < nof_comps; i++) { + CompField *comp = v[i]; + const Identifier& id = comp->get_name(); + const string& name = id.get_name(); + if (m.has_key(name)) { + const char *dispname = id.get_dispname().c_str(); + comp->error("Duplicate %s field name `%s'", typetype_name, dispname); + m[name]->note("Field `%s' is already defined here", dispname); + } else m.add(name, comp); + } + checked = true; +} + +void CompFieldMap::chk() +{ + if (!checked) chk_uniq(); + const char *typetype_name = get_typetype_name(); + size_t nof_comps = v.size(); + for (size_t i = 0; i < nof_comps; i++) { + CompField *comp = v[i]; + const Identifier& id = comp->get_name(); + Error_Context cntxt(comp, "In %s field `%s'", typetype_name, + id.get_dispname().c_str()); + Type *t = comp->get_type(); + t->set_genname(my_type->get_genname_own(), id.get_name()); + t->set_parent_type(my_type); + t->chk(); + t->chk_embedded(true, "embedded into another type"); + } +} + +void CompFieldMap::dump(unsigned level) const +{ + size_t nof_comps = v.size(); + DEBUG(level, "component fields: (%lu pcs.) @ %p", + (unsigned long) nof_comps, (const void*)this); + for (size_t i = 0; i < nof_comps; i++) v[i]->dump(level + 1); +} + +} /* namespace Common */ diff --git a/compiler2/CompField.hh b/compiler2/CompField.hh new file mode 100644 index 0000000..c65aa02 --- /dev/null +++ b/compiler2/CompField.hh @@ -0,0 +1,101 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef COMPFIELD_HH_ +#define COMPFIELD_HH_ + +#include "Setting.hh" + +class RawAST; + +namespace Common { + +/** + * A class to represent a field of a compound type (sequence/record, + * set and choice/union). + */ +class CompField : public Node, public Location { +private: + /** The name of the field. Owned by the CompField. */ + Identifier *name; + /** The type of the field. Owned. */ + Type *type; + bool is_optional; + /** Default value or 0 if no default value. Owned. */ + Value *defval; + /** Raw attributes or 0. Owned */ + RawAST *rawattrib; + /** Copy constructor not implemented */ + CompField(const CompField& p); + /** Assignment disabled */ + CompField& operator=(const CompField& p); +public: + CompField(Identifier *p_name, Type *p_type, bool p_is_optional=false, + Value *p_defval=0); + virtual ~CompField(); + virtual CompField *clone() const; + virtual void set_fullname(const string& p_fullname); + void set_my_scope(Scope *p_scope); + const Identifier& get_name() const { return *name; } + Type *get_type() const { return type; } + RawAST* get_raw_attrib() const { return rawattrib; } + void set_raw_attrib(RawAST* r_attr); + bool get_is_optional() const { return is_optional; } + bool has_default() const { return defval != 0; } + Value *get_defval() const { return defval; } + virtual void dump(unsigned level) const; +}; + +/** + * Class to represent a map of TTCN-3 StructFieldDef (BNF + * 23). Create a CompFieldMap and use add_comp(CompField *) to add + * each StructFieldDef (a.k.a. CompRef) into it! Finally, pass + * CompFieldMap* to constructors of record/set/union types! + */ +class CompFieldMap : public Node { +private: + /** Maps the name of the component to the actual component. */ + map m; + /** Contains pointers to the individual CompField s. + * The CompFieldMap owns the CompFields and will free them. */ + vector v; + /** Points to the owner type, which shall be a TTCN-3 record, set or + * union or an ASN.1 open type. + * The CompFieldMap does not own the type. */ + Type *my_type; + /** Indicates whether the uniqueness of field identifiers has been + * verified. */ + bool checked; + + CompFieldMap(const CompFieldMap& p); + /** Assignment disabled */ + CompFieldMap& operator=(const CompFieldMap& p); +public: + CompFieldMap() : Node(), m(), v(), my_type(0), checked(false) {} + virtual ~CompFieldMap(); + virtual CompFieldMap *clone() const; + virtual void set_fullname(const string& p_fullname); + virtual void set_my_scope(Scope *p_scope); + void set_my_type(Type *p_my_type) { my_type = p_my_type; } + void add_comp(CompField *comp); + size_t get_nof_comps() const { return v.size(); } + CompField* get_comp_byIndex(size_t n) const { return v[n]; } + bool has_comp_withName(const Identifier& p_name); + CompField* get_comp_byName(const Identifier& p_name); +private: + const char *get_typetype_name() const; + /** Check the uniqueness of field identifiers. + * Builds the map \c m in the process. */ + void chk_uniq(); +public: + void chk(); + virtual void dump(unsigned level) const; +}; + + +} /* namespace Common */ +#endif /* COMPFIELD_HH_ */ diff --git a/compiler2/CompType.cc b/compiler2/CompType.cc new file mode 100644 index 0000000..3f09be2 --- /dev/null +++ b/compiler2/CompType.cc @@ -0,0 +1,664 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "CompType.hh" + +#include "ttcn3/AST_ttcn3.hh" +#include "ttcn3/Attributes.hh" + +// implemented in comptype_attrib_la.l +extern void parseExtendsCompTypeRefList(Ttcn::AttributeSpec const& attrib, + Common::CompTypeRefList*& attr_comp_refs); + +namespace Common { + +// ================================= +// ===== ComponentTypeBody +// ================================= + +ComponentTypeBody::~ComponentTypeBody() +{ + for(size_t i = 0; i < def_v.size(); i++) delete def_v[i]; + def_v.clear(); + delete extends_refs; + delete attr_extends_refs; + all_defs_m.clear(); + orig_defs_m.clear(); + compatible_m.clear(); +} + +ComponentTypeBody *ComponentTypeBody::clone() const +{ + FATAL_ERROR("ComponentTypeBody::clone()"); +} + +void ComponentTypeBody::set_fullname(const string& p_fullname) +{ + Scope::set_fullname(p_fullname); + for(size_t i = 0; i < def_v.size(); i++) { + Ttcn::Definition *def = def_v[i]; + def->set_fullname(p_fullname + "." + def->get_id().get_dispname()); + } + if (extends_refs) + extends_refs->set_fullname(p_fullname+"."); + if (attr_extends_refs) + attr_extends_refs->set_fullname(get_fullname()+"."); +} + +void ComponentTypeBody::set_my_scope(Scope *p_scope) +{ + set_parent_scope(p_scope); + if (extends_refs) extends_refs->set_my_scope(p_scope); + if (attr_extends_refs) attr_extends_refs->set_my_scope(p_scope); +} + +void ComponentTypeBody::add_extends(CompTypeRefList *p_crl) +{ + if (extends_refs || !p_crl || check_state!=CHECK_INITIAL) + FATAL_ERROR("ComponentTypeBody::add_extends()"); + extends_refs = p_crl; +} + +bool ComponentTypeBody::is_compatible(ComponentTypeBody *other) +{ + if (other==this) return true; + chk(CHECK_EXTENDS); + other->chk(CHECK_EXTENDS); + // a component with no definitions is compatible with all components + if (def_v.size()==0 && !extends_refs && !attr_extends_refs) return true; + return other->compatible_m.has_key(this); +} + +void ComponentTypeBody::add_ass(Ttcn::Definition *p_ass) +{ + if (check_state!=CHECK_INITIAL || !p_ass) + FATAL_ERROR("ComponentTypeBody::add_ass()"); + p_ass->set_my_scope(this); + def_v.add(p_ass); +} + +bool ComponentTypeBody::has_local_ass_withId(const Identifier& p_id) +{ + chk(); + return all_defs_m.has_key(p_id.get_name()); +} + +Assignment* ComponentTypeBody::get_local_ass_byId(const Identifier& p_id) +{ + chk(); + return all_defs_m[p_id.get_name()]; +} + +size_t ComponentTypeBody::get_nof_asss() +{ + chk(); + return all_defs_m.size(); +} + +bool ComponentTypeBody::has_ass_withId(const Identifier& p_id) +{ + if (has_local_ass_withId(p_id)) return true; + else if (parent_scope) return parent_scope->has_ass_withId(p_id); + else return false; +} + +Assignment* ComponentTypeBody::get_ass_byIndex(size_t p_i) +{ + chk(); + return all_defs_m.get_nth_elem(p_i); +} + +bool ComponentTypeBody::is_own_assignment(const Assignment* p_ass) +{ + for(size_t i = 0; i < def_v.size(); i++) { + if (def_v[i] == p_ass) return true; + } + return false; +} + +Assignment* ComponentTypeBody::get_ass_bySRef(Ref_simple *p_ref) +{ + if (!p_ref || !parent_scope) + FATAL_ERROR("ComponentTypeBody::get_ass_bySRef()"); + if (!p_ref->get_modid()) { + const Identifier *id = p_ref->get_id(); + if (id && has_local_ass_withId(*id)) { + Assignment* ass = get_local_ass_byId(*id); + if (!ass) FATAL_ERROR("ComponentTypeBody::get_ass_bySRef()"); + + for(size_t i = 0; i < def_v.size(); i++) { + if (def_v[i] == ass) return ass; + } + + if (ass->get_visibility() == PUBLIC) { + return ass; + } + + p_ref->error("The member definition `%s' in component type `%s'" + " is not visible in this scope", id->get_dispname().c_str(), + comp_id->get_dispname().c_str()); + return 0; + } + } + return parent_scope->get_ass_bySRef(p_ref); +} + +void ComponentTypeBody::dump(unsigned level) const +{ + if (extends_refs) { + DEBUG(level, "Extends references:"); + extends_refs->dump(level+1); + } + DEBUG(level, "Definitions: (%lu pcs.)", (unsigned long) def_v.size()); + for(size_t i = 0; i < def_v.size(); i++) def_v[i]->dump(level + 1); + if (attr_extends_refs) { + DEBUG(level, "Extends attribute references:"); + attr_extends_refs->dump(level+1); + } +} + +// read out the contents of the with attribute extension, +// parse it to the the attr_extends_refs member variable, +// collects all extends components from all attributes along the attrib path +void ComponentTypeBody::chk_extends_attr() +{ + if (check_state>=CHECK_WITHATTRIB) return; + check_state = CHECK_WITHATTRIB; + Ttcn::WithAttribPath* w_attrib_path = my_type->get_attrib_path(); + if(w_attrib_path) + { + vector const &real_attribs = + w_attrib_path->get_real_attrib(); + for (size_t i = 0; i < real_attribs.size(); i++) + { + Ttcn::SingleWithAttrib *act_attr = real_attribs[i]; + if (act_attr->get_attribKeyword()==Ttcn::SingleWithAttrib::AT_EXTENSION) + parseExtendsCompTypeRefList(act_attr->get_attribSpec(), + attr_extends_refs); + } + } + if (attr_extends_refs) + { + attr_extends_refs->set_fullname(get_fullname()+"."); + attr_extends_refs->set_my_scope(parent_scope); + } +} + +void ComponentTypeBody::chk_recursion(ReferenceChain& refch) +{ + if (refch.add(get_fullname())) { + if (extends_refs) extends_refs->chk_recursion(refch); + if (attr_extends_refs) attr_extends_refs->chk_recursion(refch); + } +} + +// contained components must already be checked, +// having valid compatible_m maps +void ComponentTypeBody::init_compatibility(CompTypeRefList *crl, + bool is_standard_extends) +{ + for (size_t i = 0; i < crl->get_nof_comps(); i++) + { + ComponentTypeBody *cb = crl->get_nth_comp_body(i); + if (!compatible_m.has_key(cb)) + compatible_m.add(cb, is_standard_extends ? cb : NULL); + // compatible with all components which are compatible with the compatible + // component + for (size_t j = 0; j < cb->compatible_m.size(); j++) + { + ComponentTypeBody *ccb = cb->compatible_m.get_nth_key(j); + ComponentTypeBody *ccbval = cb->compatible_m.get_nth_elem(j); + if (!compatible_m.has_key(ccb)) + compatible_m.add(ccb, is_standard_extends ? ccbval : NULL); + } + } +} + +void ComponentTypeBody::chk_extends() +{ + if (check_state>=CHECK_EXTENDS) return; + check_state = CHECK_EXTENDS; + // check the references in component extends parts (keyword and attribute) + if (extends_refs) extends_refs->chk(CHECK_EXTENDS); + if (attr_extends_refs) attr_extends_refs->chk(CHECK_EXTENDS); + // check for circular reference chains + ReferenceChain refch(this, "While checking component type extensions"); + chk_recursion(refch); + // build compatibility map for faster is_compatible() and generate_code() + // contained components must already have valid compatible_m map + // keys used in is_compatible(), values used in generate_code() + if (extends_refs) init_compatibility(extends_refs, true); + if (attr_extends_refs) init_compatibility(attr_extends_refs, false); +} + +void ComponentTypeBody::collect_defs_from_standard_extends() +{ + Assignments *module_defs = parent_scope->get_scope_asss(); + for (size_t i = 0; i < extends_refs->get_nof_comps(); i++) { + ComponentTypeBody *parent = extends_refs->get_nth_comp_body(i); + // iterate through all definitions of the parent + // parent is already checked (has it's inherited defs included) + for (size_t j = 0; j < parent->all_defs_m.size(); j++) { + Ttcn::Definition *def = parent->all_defs_m.get_nth_elem(j); + const Identifier& id = def->get_id(); + const string& name = id.get_name(); + if (all_defs_m.has_key(name)) { + Ttcn::Definition *my_def = all_defs_m[name]; + if (my_def != def) { + // it is not the same definition inherited on two paths + const char *dispname_str = id.get_dispname().c_str(); + if (my_def->get_my_scope() == this) { + my_def->error("Local definition `%s' collides with definition " + "inherited from component type `%s'", dispname_str, + def->get_my_scope()->get_fullname().c_str()); + def->note("Inherited definition of `%s' is here", dispname_str); + } else { + error("Definition `%s' inherited from component type `%s' " + "collides with definition inherited from `%s'", dispname_str, + def->get_my_scope()->get_fullname().c_str(), + my_def->get_my_scope()->get_fullname().c_str()); + def->note("Definition of `%s' in `%s' is here", dispname_str, + def->get_my_scope()->get_fullname().c_str()); + my_def->note("Definition of `%s' in `%s' is here", dispname_str, + my_def->get_my_scope()->get_fullname().c_str()); + } + } + } else { + all_defs_m.add(name, def); + if (def->get_my_scope()->get_scope_mod() != + module_defs->get_scope_mod()) { + // def comes from another module + if (module_defs->has_local_ass_withId(id)) { + const char *dispname_str = id.get_dispname().c_str(); + error("The name of inherited definition `%s' is not unique in " + "the scope hierarchy", dispname_str); + module_defs->get_local_ass_byId(id)->note("Symbol `%s' is " + "already defined here in a higher scope unit", dispname_str); + def->note("Definition `%s' inherited from component type `%s' " + "is here", dispname_str, + def->get_my_scope()->get_fullname().c_str()); + } else if (module_defs->is_valid_moduleid(id)) { + def->warning("Inherited definition with name `%s' hides a " + "module identifier", id.get_dispname().c_str()); + } + } + } + } + } +} + +void ComponentTypeBody::collect_defs_from_attribute_extends() +{ + for (size_t i = 0; i < attr_extends_refs->get_nof_comps(); i++) { + ComponentTypeBody *parent = attr_extends_refs->get_nth_comp_body(i); + // iterate through all definitions of the parent + // parent is already checked (has it's inherited defs included) + for (size_t j = 0; j < parent->all_defs_m.size(); j++) { + Ttcn::Definition *def = parent->all_defs_m.get_nth_elem(j); + const Identifier& id = def->get_id(); + const char *dispname_str = id.get_dispname().c_str(); + const string& name = id.get_name(); + // the definition to be imported must be already in the all_defs_m map + // and must belong to owner (not be inherited) + // orig_defs_map contains backed up own definitions + if (all_defs_m.has_key(name)) { + Ttcn::Definition *my_def = all_defs_m[name]; + if (my_def->get_my_scope() == this) { + // my_def is a local definition + if (orig_defs_m.has_key(name)) FATAL_ERROR( \ + "ComponentTypeBody::collect_defs_from_attribute_extends()"); + orig_defs_m.add(name, my_def); // backup for init + all_defs_m[name] = def; // point to inherited def + } else { + // my_def comes from another component type + // exclude case when the same definition is inherited on different + // paths, there must be a local definition + if (def!=my_def || !orig_defs_m.has_key(name)) { + error("Definition `%s' inherited from component type `%s' " + "collides with definition inherited from `%s'", dispname_str, + def->get_my_scope()->get_fullname().c_str(), + my_def->get_my_scope()->get_fullname().c_str()); + def->note("Definition of `%s' in `%s' is here", + dispname_str, def->get_my_scope()->get_fullname().c_str()); + my_def->note("Definition of `%s' in `%s' is here", + dispname_str, my_def->get_my_scope()->get_fullname().c_str()); + if (orig_defs_m.has_key(name)) { + // the same definition is also present locally + orig_defs_m[name]->note("Local definition of `%s' is here", + dispname_str); + } + } + } + } else { + error("Missing local definition of `%s', which was inherited from " + "component type `%s'", dispname_str, + def->get_my_scope()->get_fullname().c_str()); + def->note("Inherited definition of `%s' is here", dispname_str); + } + } + } +} + +void ComponentTypeBody::chk_defs_uniq() +{ + if (check_state>=CHECK_DEFUNIQ) return; + check_state = CHECK_DEFUNIQ; + if (extends_refs) extends_refs->chk(CHECK_DEFUNIQ); + if (attr_extends_refs) attr_extends_refs->chk(CHECK_DEFUNIQ); + size_t nof_defs = def_v.size(); + if (nof_defs > 0) { + Error_Context cntxt(this, "While checking uniqueness of component " + "element definitions"); + Assignments *module_defs = parent_scope->get_scope_asss(); + // add own definitions to all_def_m + for (size_t i = 0; i < nof_defs; i++) { + Ttcn::Definition *def = def_v[i]; + const Identifier& id = def->get_id(); + const string& name = id.get_name(); + if (all_defs_m.has_key(name)) { + const char *dispname_str = id.get_dispname().c_str(); + def->error("Duplicate definition with name `%s'", dispname_str); + all_defs_m[name]->note("Previous definition of `%s' is here", + dispname_str); + } else { + all_defs_m.add(name, def); + if (module_defs->has_local_ass_withId(id)) { + const char *dispname_str = id.get_dispname().c_str(); + def->error("Component element name `%s' is not unique in the " + "scope hierarchy", dispname_str); + module_defs->get_local_ass_byId(id)->note("Symbol `%s' is " + "already defined here in a higher scope unit", dispname_str); + } else if (module_defs->is_valid_moduleid(id)) { + def->warning("Definition with name `%s' hides a module identifier", + id.get_dispname().c_str()); + } + } + } + } + if (extends_refs || attr_extends_refs) { + // collect all inherited definitions + Error_Context cntxt(this, "While checking uniqueness of inherited " + "component element definitions"); + if (extends_refs) collect_defs_from_standard_extends(); + if (attr_extends_refs) collect_defs_from_attribute_extends(); + } +} + +void ComponentTypeBody::chk_my_defs() +{ + if (check_state>=CHECK_OWNDEFS) return; + check_state = CHECK_OWNDEFS; + Error_Context cntxt(this, "In component element definitions"); + for (size_t i = 0; i < def_v.size(); i++) def_v[i]->chk(); +} + +void ComponentTypeBody::chk_attr_ext_defs() +{ + if (check_state>=CHECK_EXTDEFS) return; + check_state = CHECK_EXTDEFS; + size_t nof_inherited_defs = orig_defs_m.size(); + if (nof_inherited_defs > 0) { + Error_Context cntxt(this, "While checking whether the local and " + "inherited component element definitions are identical"); + // for definitions inherited with attribute extends check if + // local and inherited definitions are identical + for (size_t i = 0; i < nof_inherited_defs; i++) { + const string& key = orig_defs_m.get_nth_key(i); + Ttcn::Definition *original_def = orig_defs_m.get_nth_elem(i); + Ttcn::Definition *inherited_def = all_defs_m[key]; + if (!original_def->chk_identical(inherited_def)) + all_defs_m[key] = original_def; + } + } +} + +void ComponentTypeBody::chk(check_state_t required_check_state) +{ + if (checking || check_state==CHECK_FINAL) return; + checking = true; + switch (check_state) + { + case CHECK_INITIAL: + chk_extends_attr(); + if (required_check_state==CHECK_WITHATTRIB) break; + // no break + case CHECK_WITHATTRIB: + chk_extends(); + if (required_check_state==CHECK_EXTENDS) break; + // no break + case CHECK_EXTENDS: + chk_defs_uniq(); + if (required_check_state==CHECK_DEFUNIQ) break; + // no break + case CHECK_DEFUNIQ: + chk_my_defs(); + if (required_check_state==CHECK_OWNDEFS) break; + // no break + case CHECK_OWNDEFS: + chk_attr_ext_defs(); + if (required_check_state==CHECK_EXTDEFS) break; + // no break + case CHECK_EXTDEFS: + check_state = CHECK_FINAL; + // no break + case CHECK_FINAL: + break; + default: + FATAL_ERROR("ComponentTypeBody::chk()"); + } + checking = false; +} + +void ComponentTypeBody::set_genname(const string& prefix) +{ + for (size_t i = 0; i < def_v.size(); i++) { + Ttcn::Definition *def = def_v[i]; + def->set_genname(prefix + def->get_id().get_name()); + } +} + + +void ComponentTypeBody::generate_code(output_struct* target) +{ + if (check_state != CHECK_FINAL || !comp_id) + FATAL_ERROR("ComponentTypeBody::generate_code()"); + // beginning of block in init_comp + target->functions.init_comp = mputprintf(target->functions.init_comp, + "if (!strcmp(component_type, \"%s\")) {\n", + comp_id->get_dispname().c_str()); + + // call init_comp for all components which are compatible + // with this component along standard extends paths + if (extends_refs) { + bool has_base_comps = false; + for (size_t i = 0; i < compatible_m.size(); i++) { + ComponentTypeBody *cb = compatible_m.get_nth_elem(i); + // recursive initialization is needed if the component type is + // inherited using the standard "extends" mechanism and the component + // type has its own definitions + if (cb && cb->def_v.size() > 0) { + if (!has_base_comps) { + target->functions.init_comp = mputstr(target->functions.init_comp, + "if (init_base_comps) {\n"); + has_base_comps = true; + } + const char *ct_dispname_str = cb->get_id()->get_dispname().c_str(); + Module *ct_mod = cb->get_scope_mod_gen(); + if (ct_mod == get_scope_mod_gen()) { + // the other component type is in the same module + // call the initializer function recursively + target->functions.init_comp = mputprintf( + target->functions.init_comp, "init_comp_type(\"%s\", FALSE);\n", + ct_dispname_str); + } else { + // the other component type is imported from another module + // use the module list for initialization + target->functions.init_comp = mputprintf( + target->functions.init_comp, + "Module_List::initialize_component(\"%s\", \"%s\", FALSE);\n", + ct_mod->get_modid().get_dispname().c_str(), ct_dispname_str); + } + } + } + if (has_base_comps) { + // closing of the if() above + target->functions.init_comp = mputstr(target->functions.init_comp, + "}\n"); + } + } + + // code generation for embedded definitions + size_t nof_defs = def_v.size(); + for (size_t i = 0; i < nof_defs; i++) { + Ttcn::Definition *def = def_v[i]; + const string& name = def->get_id().get_name(); + if (orig_defs_m.has_key(name)) { + // def is hidden by an inherited definiton + // only an initializer shall be generated + target->functions.init_comp = def->generate_code_init_comp( + target->functions.init_comp, all_defs_m[name]); + } else { + // def is a normal (non-inherited) definition + def->generate_code(target, true); + } + } + + // end of block in init_comp + target->functions.init_comp = mputstr(target->functions.init_comp, + "return TRUE;\n" + "} else "); +} + +char *ComponentTypeBody::generate_code_comptype_name(char *str) +{ + if (!comp_id) + FATAL_ERROR("ComponentTypeBody::generate_code_comtype_name()"); + return mputprintf(str, "\"%s\", \"%s\"", + parent_scope->get_scope_mod_gen()->get_modid().get_dispname().c_str(), + comp_id->get_dispname().c_str()); +} + +void ComponentTypeBody::set_parent_path(Ttcn::WithAttribPath* p_path) { + for (size_t i = 0; i < def_v.size(); i++) + def_v[i]->set_parent_path(p_path); +} + +// ================================= +// ===== CompTypeRefList +// ================================= + +CompTypeRefList::~CompTypeRefList() +{ + for (size_t i=0; idump(level+1); +} + +void CompTypeRefList::set_fullname(const string& p_fullname) +{ + Node::set_fullname(p_fullname); + for (size_t i=0; iset_fullname(p_fullname + "."); +} + +void CompTypeRefList::chk_uniq() +{ + if (checked) return; + checked = true; + for (size_t i = 0; i < comp_ref_v.size(); i++) + { + Ttcn::Reference *ref = comp_ref_v[i]; + Type *type = ref->chk_comptype_ref(); + if (type) + { + // add the component body to the map or error if it's duplicate + ComponentTypeBody *cb = type->get_CompBody(); + if (cb) + { + if (comp_body_m.has_key(cb)) + { + const string& type_name = type->get_typename(); + const char *name = type_name.c_str(); + ref->error("Duplicate reference to component with name `%s'", name); + comp_body_m[cb]->note("Previous reference to `%s' is here", name); + } + else + { + // map and vector must always have same content + comp_body_m.add(cb, ref); + comp_body_v.add(cb); + } + } + } + } +} + +void CompTypeRefList::chk(ComponentTypeBody::check_state_t + required_check_state) +{ + chk_uniq(); + for (size_t i=0; ichk(required_check_state); +} + +void CompTypeRefList::chk_recursion(ReferenceChain& refch) +{ + for (size_t i = 0; i < comp_body_v.size(); i++) { + refch.mark_state(); + comp_body_v[i]->chk_recursion(refch); + refch.prev_state(); + } +} + +void CompTypeRefList::set_my_scope(Scope *p_scope) +{ + for (size_t i=0; iset_my_scope(p_scope); +} + +size_t CompTypeRefList::get_nof_comps() +{ + if (!checked) chk_uniq(); + return comp_body_v.size(); +} + +ComponentTypeBody *CompTypeRefList::get_nth_comp_body(size_t i) +{ + if (!checked) chk_uniq(); + return comp_body_v[i]; +} + +Ttcn::Reference *CompTypeRefList::get_nth_comp_ref(size_t i) +{ + if (!checked) chk_uniq(); + return comp_body_m[comp_body_v[i]]; +} + +bool CompTypeRefList::has_comp_body(ComponentTypeBody *cb) +{ + if (!checked) chk_uniq(); + return comp_body_m.has_key(cb); +} + +} /* namespace Common */ diff --git a/compiler2/CompType.hh b/compiler2/CompType.hh new file mode 100644 index 0000000..eb14224 --- /dev/null +++ b/compiler2/CompType.hh @@ -0,0 +1,176 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef COMPTYPE_HH_ +#define COMPTYPE_HH_ + +#include "Setting.hh" + +struct output_struct_t; + +namespace Ttcn { +class Definition; +class WithAttribPath; +class Reference; +} + +namespace Common { + +class CompTypeRefList; + +/** Class to represent the definition of a component type */ +class ComponentTypeBody : public Scope, public Location { +public: + /** represents the check state of this component + * every check increments the value */ + enum check_state_t { + CHECK_INITIAL, /**< initial state before checks */ + CHECK_WITHATTRIB, /**< with attribute checked, + set by chk_extends_attr() */ + CHECK_EXTENDS, /**< component extension checked, + set by chk_extends() */ + CHECK_DEFUNIQ, /**< definitions id uniqueness checked, + set by chk_defs_uniq() */ + CHECK_OWNDEFS, /**< own definitions checked, + set by chk_my_defs() */ + CHECK_EXTDEFS, /**< definitions inherited by attribute checked, + set by chk_attr_ext_defs() */ + CHECK_FINAL /**< everything was checked, set by chk() */ + }; +private: + /** Identifier of this component */ + const Identifier *comp_id; + /** the Type that contains this, needed to reach w_attrib_path */ + Type *my_type; + /** tells which checks have already been performed */ + check_state_t check_state; + /** true when chk() is running */ + bool checking; + /** Vector containing own definitions. Used for building. */ + vector def_v; + /** component references from the "extends" part or NULL if there were no */ + CompTypeRefList *extends_refs; + /** component references from the extends attribute or NULL */ + CompTypeRefList *attr_extends_refs; + /** map of own definitions equal to inherited by extension attribute + * needed to initialize the the value with own value, + * pointers to the defs are owned by def_v */ + map orig_defs_m; + /** map of my and inherited definitions */ + map all_defs_m; + /** compatibility map for is_compatible() function, filled in chk(), + * all components inherited along pure extends-keyword path have the value + * equal to the key, others have NULL value */ + map compatible_m; + void init_compatibility(CompTypeRefList *crl, bool is_standard_extends); +private: + /** Copy constructor not implemented */ + ComponentTypeBody(const ComponentTypeBody& p); + /** Assignment not implemented */ + ComponentTypeBody& operator=(const ComponentTypeBody& p); +public: + ComponentTypeBody() + : Scope(), comp_id(0), my_type(0), check_state(CHECK_INITIAL), + checking(false), def_v(), extends_refs(0), attr_extends_refs(0), + orig_defs_m(), all_defs_m(), compatible_m() { } + ~ComponentTypeBody(); + ComponentTypeBody *clone() const; + + void set_id(const Identifier *p_id) { comp_id = p_id; } + Identifier const * get_id() const { return comp_id; } + void set_my_type(Type *p_type) { my_type = p_type; } + Type* get_my_type() { return my_type; } + + virtual void set_fullname(const string& p_fullname); + virtual void set_my_scope(Scope *p_scope); + + bool has_local_ass_withId(const Identifier& p_id); + Assignment* get_local_ass_byId(const Identifier& p_id); + bool has_ass_withId(const Identifier& p_id); + bool is_own_assignment(const Assignment* p_ass); + size_t get_nof_asss(); + Assignment* get_ass_byIndex(size_t p_i); + virtual Assignment *get_ass_bySRef(Ref_simple *p_ref); + + void add_extends(CompTypeRefList *p_crl); + + /** Returns if this component is compatible with the given other component. + * This component is compatible with other component if this extends the + * other component (with standard extends or with extension attribute) + * directly or this extends a component which is compatible with other */ + bool is_compatible(ComponentTypeBody *other); + /** Adds the assignment p_ass and becomes the owner of it. + * The uniqueness of the identifier is not checked. */ + void add_ass(Ttcn::Definition *p_ass); + /** Prints the contents of the component. */ + void dump(unsigned level) const; +private: + void chk_extends_attr(); +public: + /** Check component extends recursions (extends keyword and attribute) */ + void chk_recursion(ReferenceChain& refch); +private: + void collect_defs_from_standard_extends(); + void collect_defs_from_attribute_extends(); + /** Checks the AST for correct component extensions. */ + void chk_extends(); + /** Checks definition id uniqueness */ + void chk_defs_uniq(); + /** Checks all own definitions */ + void chk_my_defs(); + /** Checks definitions inherited with attribute extends */ + void chk_attr_ext_defs(); +public: + /** perform all checks */ + void chk(check_state_t required_check_state = CHECK_FINAL); + /** Sets the genname of embedded definitions using \a prefix. */ + void set_genname(const string& prefix); + void generate_code(output_struct_t *target); + /** Generates a pair of C++ strings that contain the module name and name + * of the component type and appends them to \a str. */ + char *generate_code_comptype_name(char *str); + + void set_parent_path(Ttcn::WithAttribPath* p_path); +}; + +/** Class to represent a list of references to components */ +class CompTypeRefList : public Node, public Location { +private: + bool checked; + vector comp_ref_v; + /** Pointers to ComponentTypeBody objects in the AST, filled by chk() */ + map comp_body_m; + /** Contains the keys of comp_body_m in the order determined by comp_ref_v, + * used to perform checks in deterministic order ( the order of keys in + * comp_body_m is platform dependent */ + vector comp_body_v; + /** Copy constructor not implemented */ + CompTypeRefList(const CompTypeRefList& p); + /** Assignment disabled */ + CompTypeRefList& operator=(const CompTypeRefList& p); +public: + CompTypeRefList() + : checked(false), comp_ref_v(), comp_body_m(), comp_body_v() { } + ~CompTypeRefList(); + CompTypeRefList *clone() const; + void add_ref(Ttcn::Reference *p_ref); + void dump(unsigned level) const; + virtual void set_fullname(const string& p_fullname); + void chk_uniq(); + void chk(ComponentTypeBody::check_state_t required_check_state); + void chk_recursion(ReferenceChain& refch); + virtual void set_my_scope(Scope *p_scope); + + /** utility functions to access comp_body_m */ + size_t get_nof_comps(); + ComponentTypeBody *get_nth_comp_body(size_t i); + Ttcn::Reference *get_nth_comp_ref(size_t i); + bool has_comp_body(ComponentTypeBody *cb); +}; + +} /* namespace Common */ +#endif /* COMPTYPE_HH_ */ diff --git a/compiler2/CompilerError.cc b/compiler2/CompilerError.cc new file mode 100644 index 0000000..88b5acc --- /dev/null +++ b/compiler2/CompilerError.cc @@ -0,0 +1,325 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "error.h" +#include "CompilerError.hh" +#include "../common/memory.h" +#include "../common/path.h" +#include "main.hh" +#include "Setting.hh" + +#include +#include +#include +#include +#ifndef MINGW +# include +#endif + +unsigned verb_level=0x0007; /* default value */ + +const char *argv0; /* the programname :) */ + +void fatal_error(const char *filename, int lineno, const char *fmt, ...) +{ + va_list parameters; +#ifdef FATAL_DEBUG + va_start(parameters, fmt); + Common::Location loc(filename, lineno); + Common::Error_Context::report_error(&loc, fmt, parameters); + va_end(parameters); +#else + fprintf(stderr, "FATAL ERROR: %s: In line %d of %s: ", + argv0, lineno, filename); + va_start(parameters, fmt); + vfprintf(stderr, fmt, parameters); + va_end(parameters); + putc('\n', stderr); +#endif + fflush(stderr); + abort(); +} + +void ERROR(const char *fmt, ...) +{ + fprintf(stderr, "%s: error: ", argv0); + va_list parameters; + va_start(parameters, fmt); + vfprintf(stderr, fmt, parameters); + va_end(parameters); + putc('\n', stderr); + fflush(stderr); + Common::Error_Context::increment_error_count(); +} + +void WARNING(const char *fmt, ...) +{ + if(!(verb_level & 2)) return; + fprintf(stderr, "%s: warning: ", argv0); + va_list parameters; + va_start(parameters, fmt); + vfprintf(stderr, fmt, parameters); + va_end(parameters); + putc('\n', stderr); + fflush(stderr); + Common::Error_Context::increment_warning_count(); +} + +void NOTSUPP(const char *fmt, ...) +{ + if(!(verb_level & 1)) return; + fprintf(stderr, "%s: warning: not supported: ", argv0); + va_list parameters; + va_start(parameters, fmt); + vfprintf(stderr, fmt, parameters); + va_end(parameters); + putc('\n', stderr); + fflush(stderr); + Common::Error_Context::increment_warning_count(); +} + +void NOTIFY(const char *fmt, ...) +{ + if(!(verb_level & 4)) return; + fprintf(stderr, "Notify: "); + va_list parameters; + va_start(parameters, fmt); + vfprintf(stderr, fmt, parameters); + va_end(parameters); + putc('\n', stderr); + fflush(stderr); +} + +void DEBUG(unsigned level, const char *fmt, ...) +{ + if((level>7?7:level)>((verb_level>>3)&0x07)) return; + fprintf(stderr, "%*sDebug: ", level, ""); + va_list parameters; + va_start(parameters, fmt); + vfprintf(stderr, fmt, parameters); + va_end(parameters); + putc('\n', stderr); + fflush(stderr); +} + +unsigned int get_error_count(void) +{ + return Common::Error_Context::get_error_count(); +} + +unsigned int get_warning_count(void) +{ + return Common::Error_Context::get_warning_count(); +} + +void path_error(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + char *err_msg = mprintf_va_list(fmt, ap); + va_end(ap); + ERROR("%s", err_msg); + Free(err_msg); +} + +namespace Common { + + unsigned int Error_Context::error_count = 0, Error_Context::warning_count = 0; + unsigned int Error_Context::max_errors = (unsigned)-1; + + bool Error_Context::chain_printed = false; + + Error_Context *Error_Context::head = 0, *Error_Context::tail = 0; + + void Error_Context::print_context(FILE *fp) + { + int level = 0; + for (Error_Context *ptr = head; ptr; ptr = ptr->next) { + if (ptr->is_restorer) FATAL_ERROR("Error_Context::print()"); + else if (!ptr->str) continue; + else if (!ptr->is_printed) { + for (int i = 0; i < level; i++) putc(' ', fp); + if (ptr->location) ptr->location->print_location(fp); + if (gcc_compat) fputs("note: ", fp); // CDT ignores "note" + fputs(ptr->str, fp); + fputs(":\n", fp); + ptr->is_printed = true; + } + level++; + } + for (int i = 0; i < level; i++) putc(' ', fp); + chain_printed = true; + } + + Error_Context::Error_Context(size_t n_keep) + : prev(0), next(0), location(0), str(0), is_printed(false), + is_restorer(true), outer_printed(false) + { + Error_Context *begin = head; + for (size_t i = 0; i < n_keep; i++) { + if (!begin) break; + begin = begin->next; + } + if (begin == head) { + // complete backup + next = head; + head = 0; + prev = tail; + tail = 0; + } else { + // partial backup (only elements before begin are kept) + next = begin; + if (begin) { + prev = tail; + tail = begin->prev; + tail->next = 0; + begin->prev = 0; + } else prev = 0; + } + outer_printed = chain_printed; + chain_printed = false; + } + + Error_Context::Error_Context(const Location *p_location) + : prev(0), next(0), location(p_location), str(0), is_printed(false), + is_restorer(false), outer_printed(false) + { + if (!head) head = this; + if (tail) tail->next = this; + prev = tail; + next = 0; + tail = this; + } + + Error_Context::Error_Context(const Location *p_location, + const char *p_fmt, ...) + : prev(0), next(0), location(p_location), str(0), is_printed(false), + is_restorer(false), outer_printed(false) + { + va_list args; + va_start(args, p_fmt); + str = mprintf_va_list(p_fmt, args); + va_end(args); + + if (!head) head = this; + if (tail) tail->next = this; + prev = tail; + next = 0; + tail = this; + } + + Error_Context::~Error_Context() + { + if (is_restorer) { + if (chain_printed) { + for (Error_Context *ptr = next; ptr; ptr = ptr->next) + ptr->is_printed = false; + } else chain_printed = outer_printed; + if (head) { + // partial restoration + if (next) { + tail->next = next; + next->prev = tail; + tail = prev; + } + } else { + // full restoration + head = next; + tail = prev; + } + } else { + Free(str); + if (tail != this) FATAL_ERROR("Error_Context::~Error_Context()"); + if (prev) prev->next = 0; + else head = 0; + tail = prev; + } + } + + void Error_Context::set_message(const char *p_fmt, ...) + { + if (is_restorer) FATAL_ERROR("Error_Context::set_message()"); + Free(str); + va_list args; + va_start(args, p_fmt); + str = mprintf_va_list(p_fmt, args); + va_end(args); + is_printed = false; + } + + void Error_Context::report_error(const Location *loc, const char *fmt, + va_list args) + { + if (!suppress_context) print_context(stderr); + Location my_location; + if (tail != 0 && loc && loc->get_filename() == 0) { + // borrow location information from the innermost context + my_location.set_location( *(tail->location) ); + loc = &my_location; + } + if (loc) loc->print_location(stderr); + fputs("error: ", stderr); + vfprintf(stderr, fmt, args); + putc('\n', stderr); + fflush(stderr); + increment_error_count(); + } + + void Error_Context::report_warning(const Location *loc, const char *fmt, + va_list args) + { + if(!(verb_level & 2)) return; + if (!suppress_context) print_context(stderr); + if (loc) loc->print_location(stderr); + fputs("warning: ", stderr); + vfprintf(stderr, fmt, args); + putc('\n', stderr); + fflush(stderr); + increment_warning_count(); + } + + void Error_Context::report_note(const Location *loc, const char *fmt, + va_list args) + { + if (!suppress_context) print_context(stderr); + if (loc) loc->print_location(stderr); + fputs("note: ", stderr); + vfprintf(stderr, fmt, args); + putc('\n', stderr); + fflush(stderr); + } + + void Error_Context::increment_error_count() + { + if (++error_count >= max_errors) { + fputs("Maximum number of errors reached, aborting.\n", stderr); + fflush(stderr); + abort(); + } + } + + void Error_Context::increment_warning_count() + { + warning_count++; + } + + void Error_Context::print_error_statistics() + { + if (error_count == 0) { + if (warning_count == 0) NOTIFY("No errors or warnings were detected."); + else NOTIFY("No errors and %u warning%s were detected.", + warning_count, warning_count > 1 ? "s" : ""); + } else { + if (warning_count == 0) NOTIFY("%u error%s and no warnings were " + "detected.", error_count, error_count > 1 ? "s" : ""); + else NOTIFY("%u error%s and %u warning%s were detected.", + error_count, error_count > 1 ? "s" : "", + warning_count, warning_count > 1 ? "s" : ""); + } + } + +} // namespace Common diff --git a/compiler2/CompilerError.hh b/compiler2/CompilerError.hh new file mode 100644 index 0000000..9405a00 --- /dev/null +++ b/compiler2/CompilerError.hh @@ -0,0 +1,105 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Common_Error_HH +#define _Common_Error_HH + +#include +#include +#include + +#include "error.h" + +namespace Common { + + class Location; + + /** + * Class Error_Context. :) + */ + class Error_Context { + private: + /** Counts errors, warnings. */ + static unsigned int error_count, warning_count; + /** Indicates whether the actual chain was printed. */ + static bool chain_printed; + /** The head and tail of the actual chain. */ + static Error_Context *head, *tail; + + /** List-linking pointers. This contains the saved chain in a + * restorer element. */ + Error_Context *prev, *next; + /** Pointer to the location info structure. */ + const Location *location; + /** The message of the element. */ + char *str; + /** Indicates whether this element was already printed. */ + bool is_printed; + /** Indicates whether this element contains an outer chain. */ + bool is_restorer; + /** Indicates whether the outer chain was printed. */ + bool outer_printed; + /** Maximum number of errors to report */ + static unsigned int max_errors; + + /** Copy constructor not implemented. */ + Error_Context(const Error_Context& p); + /** Assignment not implemented */ + Error_Context& operator=(const Error_Context& p); + private: + /** Prints the actual chain of error contexts to fp. */ + static void print_context(FILE *fp); + public: + /** Starts a new chain and preserves/restores the existing chain, + * but keeps the n_keep elements of the old chain. */ + Error_Context(size_t n_keep = 0); + /** Adds a new element to the chain. The message shall be set + * later with a call to set_message (e.g. in a conditional + * construct). */ + Error_Context(const Location *p_location); + /** Adds a new element to the chain with the given message. */ + Error_Context(const Location *p_location, const char *p_fmt, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); + /** Destructor. Removes element from the chain. */ + ~Error_Context(); + + /** Assigns the given message to the element */ + void set_message(const char *p_fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); + + /** Generic error reporting function. */ + static void report_error(const Location *loc, const char *fmt, + va_list args); + + /** Generic warning reporting function. */ + static void report_warning(const Location *loc, const char *fmt, + va_list args); + + static void report_note(const Location *loc, const char *fmt, + va_list args); + + /** Returns the number of errors encountered. */ + static unsigned int get_error_count() { return error_count; } + /** Returns the number of warnings encountered. */ + static unsigned int get_warning_count() { return warning_count; } + /** Increments the error counter. */ + static void increment_error_count(); + /** Increments the warning counter. */ + static void increment_warning_count(); + + /** Prints statistics about the number of errors and warnings */ + static void print_error_statistics(); + + /** Set the maximum number of errors */ + static void set_max_errors(unsigned int maxe) { + max_errors = maxe; + } + }; + +} // namespace Common + +#endif // _Common_Error_HH diff --git a/compiler2/Constraint.cc b/compiler2/Constraint.cc new file mode 100644 index 0000000..3ba9c51 --- /dev/null +++ b/compiler2/Constraint.cc @@ -0,0 +1,1137 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "Constraint.hh" +#include "CompilerError.hh" +#include "Int.hh" +#include "Type.hh" +#include "Value.hh" +#include "subtype.hh" +#include "Identifier.hh" +#include "CompField.hh" +#include "asn1/Block.hh" +#include "asn1/TokenBuf.hh" + +namespace Common { + + // ================================= + // ===== Constraints + // ================================= + + Constraints::Constraints(const Constraints& p) + : Node(p), cons(), my_type(0), subtype(0), extendable(false), extension(0) + { + size_t nof_cons = p.cons.size(); + for (size_t i = 0; i < nof_cons; i++) cons.add(p.cons[i]->clone()); + } + + Constraints::~Constraints() + { + size_t nof_cons = cons.size(); + for (size_t i = 0; i < nof_cons; i++) delete cons[i]; + cons.clear(); + delete subtype; + delete extension; + } + + Constraints *Constraints::clone() const + { + return new Constraints(*this); + } + + void Constraints::add_con(Constraint *p_con) + { + if (!p_con) FATAL_ERROR("Constraints::add_con()"); + cons.add(p_con); + if (my_type) p_con->set_my_type(my_type); + } + + Constraint* Constraints::get_tableconstraint() const + { + size_t nof_cons = cons.size(); + for (size_t i = 0; i < nof_cons; i++) { + Constraint *con = cons[i]; + if (con->get_constrtype() == Constraint::CT_TABLE) return con; + } + return 0; + } + + void Constraints::set_my_type(Type *p_my_type) + { + my_type=p_my_type; + size_t nof_cons = cons.size(); + for (size_t i = 0; i < nof_cons; i++) cons[i]->set_my_type(p_my_type); + } + + void Constraints::chk_table() + { + if(!my_type) FATAL_ERROR("Constraints::chk_table()"); + size_t nof_cons = cons.size(); + for (size_t i = 0; i < nof_cons; i++) { + Error_Context cntxt(my_type, "In constraint #%lu of type `%s'", + (unsigned long) (i + 1), my_type->get_typename().c_str()); + Constraint::constrtype_t cst = cons[i]->get_constrtype(); + if (cst==Constraint::CT_TABLE) cons[i]->chk(); + } + } + + void Constraints::chk(SubtypeConstraint* parent_subtype) + { + if(!my_type) FATAL_ERROR("Common::Constraints::chk()"); + if (parent_subtype) { + subtype = new SubtypeConstraint(my_type->get_subtype_type()); + subtype->copy(parent_subtype); + } + size_t nof_cons = cons.size(); + for (size_t i = 0; i < nof_cons; i++) { + Error_Context cntxt(my_type, "In constraint #%lu of type `%s'", + (unsigned long) (i + 1), my_type->get_typename().c_str()); + cons[i]->set_fullname(my_type->get_fullname()+"..<"+string(cons[i]->get_name())+">"); + cons[i]->set_my_cons(this); + Constraint::constrtype_t cst = cons[i]->get_constrtype(); + if (cst!=Constraint::CT_TABLE) cons[i]->chk(); + if ( (cst==Constraint::CT_IGNORE) || (cst==Constraint::CT_TABLE) ) continue; // ignore + SubtypeConstraint* sc = cons[i]->get_subtype(); + SubtypeConstraint* sc_ext = cons[i]->get_extension(); + if (!sc) break; // stop on error + extendable = cons[i]->is_extendable(); + if (extension) { // only the root part shall be kept + delete extension; + extension = 0; + } + if (subtype) { + if (sc->is_subset(subtype)==TFALSE) { + cons[i]->error("Constraint #%lu is %s, this is not a subset of %s", + (unsigned long) (i + 1), + sc->to_string().c_str(), + subtype->to_string().c_str()); + break; // stop on error + } + if (sc_ext && (sc_ext->is_subset(subtype)==TFALSE)) { + cons[i]->error("Extension addition of constraint #%lu is %s, this is not a subset of %s", + (unsigned long) (i + 1), + sc_ext->to_string().c_str(), + subtype->to_string().c_str()); + break; // stop on error + } + if (sc_ext) { + extension = new SubtypeConstraint(my_type->get_subtype_type()); + extension->copy(sc_ext); + extension->intersection(subtype); + } + subtype->intersection(sc); + } else { + subtype = new SubtypeConstraint(my_type->get_subtype_type()); + subtype->copy(sc); + if (sc_ext) { + extension = new SubtypeConstraint(my_type->get_subtype_type()); + extension->copy(sc_ext); + } + } + } + } + + // ================================= + // ===== Constraint + // ================================= + + Constraint::Constraint(const Constraint& p): + Node(p), Location(p), constrtype(p.constrtype), + my_type(0), my_scope(0), my_parent(0), my_cons(0), + checked(false), subtype(0), extendable(false), extension(0) + { + } + + Constraint::Constraint(constrtype_t p_constrtype): + Node(), Location(), constrtype(p_constrtype), + my_type(0), my_scope(0), my_parent(0), my_cons(0), + checked(false), subtype(0), extendable(false), extension(0) + { + } + + Constraint::~Constraint() + { + delete subtype; + delete extension; + } + + Scope* Constraint::get_my_scope() + { + if (!my_type) FATAL_ERROR("Constraint::get_my_scope()"); + return my_scope ? my_scope : my_type->get_my_scope(); + } + + void Constraint::set_my_cons(Constraints* p_my_cons) + { + my_cons = p_my_cons; + } + + Constraints* Constraint::get_my_cons() + { + Constraint* c = this; + while (c) { + if (c->my_cons) return c->my_cons; + c = c->my_parent; + } + FATAL_ERROR("Constraint::get_my_cons()"); + return NULL; + } + + bool Constraint::in_char_context() const + { + Constraint* parent = my_parent; + while (parent) { + if (parent->get_constrtype()==CT_PERMITTEDALPHABET) return true; + parent = parent->get_my_parent(); + } + return false; + } + + bool Constraint::in_inner_constraint() const + { + Constraint* parent = my_parent; + while (parent) { + switch (parent->get_constrtype()) { + case CT_SINGLEINNERTYPE: + case CT_MULTIPLEINNERTYPE: + return true; + default: + break; + } + parent = parent->get_my_parent(); + } + return false; + } + + // ================================= + // ===== ElementSetSpecsConstraint + // ================================= + + ElementSetSpecsConstraint::ElementSetSpecsConstraint(const ElementSetSpecsConstraint& p) + : Constraint(p) + { + extendable = true; + root_constr = p.root_constr ? p.root_constr->clone() : 0; + ext_constr = p.ext_constr ? p.ext_constr->clone() : 0; + } + + ElementSetSpecsConstraint::ElementSetSpecsConstraint(Constraint* p_root_constr, Constraint* p_ext_constr) + : Constraint(CT_ELEMENTSETSPEC), root_constr(p_root_constr), ext_constr(p_ext_constr) + { + if (!p_root_constr) FATAL_ERROR("ElementSetSpecsConstraint::ElementSetSpecsConstraint()"); + // p_ext_constr can be NULL + extendable = true; + } + + ElementSetSpecsConstraint::~ElementSetSpecsConstraint() + { + delete root_constr; + delete ext_constr; + } + + void ElementSetSpecsConstraint::chk() + { + if (checked) return; + checked = true; + if (!root_constr || !my_type) FATAL_ERROR("ElementSetSpecsConstraint::chk()"); + Error_Context cntxt(this, "While checking ElementSetSpecs constraint"); + root_constr->set_my_type(my_type); + if (ext_constr) ext_constr->set_my_type(my_type); + root_constr->set_my_scope(get_my_scope()); + if (ext_constr) ext_constr->set_my_scope(get_my_scope()); + root_constr->set_my_parent(this); + if (ext_constr) ext_constr->set_my_parent(this); + root_constr->chk(); + if (ext_constr) ext_constr->chk(); + SubtypeConstraint::subtype_t my_subtype_type = my_type->get_subtype_type(); + // naming ((r1,x1),...,(r2,x2)) according to X.680(11/2008) I.4.3.8 + SubtypeConstraint* r1 = root_constr->get_subtype(); + if (!r1) return; // root_constr is invalid, error already reported there + SubtypeConstraint* x1 = root_constr->get_extension(); + if (!ext_constr) { + // only root part exists + subtype = new SubtypeConstraint(my_subtype_type); + subtype->copy(r1); + if (x1) { + extension = new SubtypeConstraint(my_subtype_type); + extension->copy(x1); + } + return; + } + SubtypeConstraint* r2 = ext_constr->get_subtype(); + if (!r2) return; // ext_constr is invalid, error already reported there + SubtypeConstraint* x2 = ext_constr->get_extension(); + subtype = new SubtypeConstraint(my_subtype_type); + subtype->copy(r1); + extension = new SubtypeConstraint(my_subtype_type); + extension->copy(r2); + if (x1) extension->union_(x1); + if (x2) extension->union_(x2); + extension->except(r1); + } + + void ElementSetSpecsConstraint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + root_constr->set_fullname(p_fullname+"..<"+string(root_constr->get_name())+">"); + if (ext_constr) + ext_constr->set_fullname(p_fullname+"..<"+string(ext_constr->get_name())+">"); + } + + // ================================= + // ===== IgnoredConstraint + // ================================= + + IgnoredConstraint::IgnoredConstraint(const IgnoredConstraint& p) + : Constraint(p), my_name(p.my_name) + { + } + + IgnoredConstraint::IgnoredConstraint(const char* p_name) + : Constraint(CT_IGNORE), my_name(p_name) + { + if (p_name==NULL) FATAL_ERROR("IgnoredConstraint::IgnoredConstraint()"); + } + + void IgnoredConstraint::chk() + { + if (checked) return; + checked = true; + if (!my_type) FATAL_ERROR("IgnoredConstraint::chk()"); + if (in_char_context()) { + error("%s not allowed inside a permitted alphabet constraint", get_name()); + return; + } else { + if (my_parent) warning("%s inside a %s is treated as `ALL' (constraint is dropped)", get_name(), my_parent->get_name()); + //else warning("%s is ignored", get_name()); + } + // ignored constraint does not constrain the type, set to full set + subtype = new SubtypeConstraint(my_type->get_subtype_type()); + } + + // ================================= + // ===== SingleValueConstraint + // ================================= + + SingleValueConstraint::SingleValueConstraint(const SingleValueConstraint& p) + : Constraint(p) + { + value = p.value ? p.value->clone() : 0; + } + + SingleValueConstraint::~SingleValueConstraint() + { + delete value; + } + + SingleValueConstraint::SingleValueConstraint(Value* p_value) + : Constraint(CT_SINGLEVALUE), value(p_value) + { + if (!p_value) FATAL_ERROR("SingleValueConstraint::SingleValueConstraint()"); + } + + void SingleValueConstraint::chk() + { + if (checked) return; + checked = true; + if (!value || !my_type) FATAL_ERROR("SingleValueConstraint::chk()"); + Error_Context cntxt(this, "While checking single value constraint"); + value->set_my_scope(get_my_scope()); + value->set_my_governor(my_type); + my_type->chk_this_value_ref(value); + my_type->chk_this_value(value, 0, Type::EXPECTED_CONSTANT, + INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, NO_SUB_CHK); + if (in_char_context()) { + subtype = SubtypeConstraint::create_from_asn_charvalues(my_type, value); + } else { + subtype = SubtypeConstraint::create_from_asn_value(my_type, value); + } + } + + void SingleValueConstraint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + value->set_fullname(p_fullname+"."); + } + + // ================================= + // ===== ContainedSubtypeConstraint + // ================================= + + ContainedSubtypeConstraint::ContainedSubtypeConstraint(const ContainedSubtypeConstraint& p) + : Constraint(p) + { + type = p.type ? p.type->clone() : 0; + } + + ContainedSubtypeConstraint::~ContainedSubtypeConstraint() + { + delete type; + } + + ContainedSubtypeConstraint::ContainedSubtypeConstraint(Type* p_type, bool p_has_includes) + : Constraint(CT_CONTAINEDSUBTYPE), type(p_type), has_includes(p_has_includes) + { + if (!p_type) FATAL_ERROR("ContainedSubtypeConstraint::ContainedSubtypeConstraint()"); + } + + void ContainedSubtypeConstraint::chk() + { + if (checked) return; + checked = true; + if (!type || !my_type) FATAL_ERROR("ContainedSubtypeConstraint::chk()"); + Error_Context cntxt(this, "While checking contained subtype constraint"); + + type->set_my_scope(get_my_scope()); + type->chk(); + if (type->get_typetype()==Type::T_ERROR) return; + + if (my_type->get_type_refd_last()->get_typetype()==Type::T_OPENTYPE) { + // TODO: open type and anytype should have their own ST_ANY subtype, now this is only ignored + subtype = new SubtypeConstraint(my_type->get_subtype_type()); + return; + } + + if (!type->is_identical(my_type)) { + error("Contained subtype constraint is invalid, constrained and constraining types have different root type"); + return; + } + // check subtype of referenced type + SubType* t_st = type->get_sub_type(); + if (t_st==NULL) { + error("Contained subtype constraint is invalid, the constraining type has no subtype constraint"); + return; + } + + // check circular subtype reference + Type* my_owner = get_my_cons()->get_my_type(); + if (!my_owner || !my_owner->get_sub_type()) FATAL_ERROR("ContainedSubtypeConstraint::chk()"); + if (!my_owner->get_sub_type()->add_parent_subtype(t_st)) return; + + if (t_st->get_subtypetype()==SubtypeConstraint::ST_ERROR) return; + if (t_st->get_subtypetype()!=my_type->get_subtype_type()) FATAL_ERROR("ContainedSubtypeConstraint::chk()"); + + subtype = SubtypeConstraint::create_from_contained_subtype(t_st->get_root(), in_char_context(), this); + } + + void ContainedSubtypeConstraint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + type->set_fullname(p_fullname+"."); + } + + // ================================= + // ===== RangeEndpoint + // ================================= + + RangeEndpoint::RangeEndpoint(const RangeEndpoint& p): + Node(p), Location(p), type(p.type), inclusive(p.inclusive) + { + value = p.value ? p.value->clone() : 0; + } + + RangeEndpoint::~RangeEndpoint() + { + delete value; + } + + RangeEndpoint::RangeEndpoint(endpoint_t p_type): + Node(), Location(), type(p_type), value(0), inclusive(true) + { + if (type==VALUE) FATAL_ERROR("RangeEndpoint::RangeEndpoint()"); + } + + RangeEndpoint::RangeEndpoint(Value* p_value): + Node(), Location(), type(RangeEndpoint::VALUE), value(p_value), inclusive(true) + { + if (!p_value) FATAL_ERROR("RangeEndpoint::RangeEndpoint()"); + } + + void RangeEndpoint::chk(Type* my_type, ValueRangeConstraint* constraint) + { + if (value) { + value->set_my_scope(constraint->get_my_scope()); + my_type->chk_this_value_ref(value); + my_type->chk_this_value(value, 0, Type::EXPECTED_CONSTANT, + INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, NO_SUB_CHK); + } + } + + void RangeEndpoint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + if (value) value->set_fullname(p_fullname+"."); + } + + // ================================= + // ===== ValueRangeConstraint + // ================================= + + ValueRangeConstraint::ValueRangeConstraint(const ValueRangeConstraint& p) + : Constraint(p) + { + lower_endpoint = p.lower_endpoint ? p.lower_endpoint->clone() : 0; + upper_endpoint = p.upper_endpoint ? p.upper_endpoint->clone() : 0; + } + + ValueRangeConstraint::ValueRangeConstraint(RangeEndpoint* p_lower, RangeEndpoint* p_upper) + : Constraint(CT_VALUERANGE), lower_endpoint(p_lower), upper_endpoint(p_upper) + { + if (!p_lower || !p_upper) FATAL_ERROR("ValueRangeConstraint::ValueRangeConstraint()"); + } + + void ValueRangeConstraint::chk() + { + if (checked) return; + checked = true; + if (!lower_endpoint || !upper_endpoint || !my_type) FATAL_ERROR("ValueRangeConstraint::chk()"); + Error_Context cntxt(this, "While checking value range constraint"); + SubtypeConstraint::subtype_t my_subtype_type = my_type->get_subtype_type(); + switch (my_subtype_type) { + case SubtypeConstraint::ST_INTEGER: + case SubtypeConstraint::ST_FLOAT: + break; + case SubtypeConstraint::ST_CHARSTRING: + switch (my_type->get_type_refd_last()->get_typetype()) { + case Type::T_NUMERICSTRING: + case Type::T_PRINTABLESTRING: + case Type::T_IA5STRING: + case Type::T_VISIBLESTRING: + if (!in_char_context()) { + error("Value range constraint must be inside a permitted alphabet or size constraint"); + return; + } + break; + default: + error("Value range constraint is not allowed for type `%s'", my_type->get_typename().c_str()); + return; + } + break; + case SubtypeConstraint::ST_UNIVERSAL_CHARSTRING: + switch (my_type->get_type_refd_last()->get_typetype()) { + case Type::T_UTF8STRING: + case Type::T_UNIVERSALSTRING: + case Type::T_BMPSTRING: + if (!in_char_context()) { + error("Value range constraint must be inside a permitted alphabet or size constraint"); + return; + } + break; + default: + error("Value range constraint is not allowed for type `%s'", my_type->get_typename().c_str()); + return; + } + break; + default: + error("Value range constraint is not allowed for type `%s'", my_type->get_typename().c_str()); + return; + } + lower_endpoint->chk(my_type, this); + upper_endpoint->chk(my_type, this); + Value* vmin = lower_endpoint->get_value(); + if (vmin) vmin = vmin->get_value_refd_last(); + Value* vmax = upper_endpoint->get_value(); + if (vmax) vmax = vmax->get_value_refd_last(); + // the subtype of the Constraints object at the time of calling this chk() + // function is constructed from all the previously calculated constraints + // (it is not yet the final subtype). This is needed to calculate the + // current MIN and MAX values. + SubtypeConstraint* parent_subtype = get_my_cons()->get_subtype(); + subtype = SubtypeConstraint::create_from_asn_range( + vmin, lower_endpoint->get_exclusive(), + vmax, upper_endpoint->get_exclusive(), + this, my_subtype_type, + in_inner_constraint() ? NULL /*the parent is invalid for an inner field*/ : parent_subtype); + } + + void ValueRangeConstraint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + lower_endpoint->set_fullname(p_fullname+"."); + upper_endpoint->set_fullname(p_fullname+"."); + } + + // ================================= + // ===== SizeConstraint + // ================================= + + SizeConstraint::SizeConstraint(const SizeConstraint& p) + : Constraint(p) + { + constraint = p.constraint ? p.constraint->clone() : 0; + } + + SizeConstraint::SizeConstraint(Constraint* p) + : Constraint(CT_SIZE), constraint(p) + { + if (!p) FATAL_ERROR("SizeConstraint::SizeConstraint()"); + } + + void SizeConstraint::chk() + { + if (checked) return; + checked = true; + if (!constraint || !my_type) FATAL_ERROR("SizeConstraint::chk()"); + Error_Context cntxt(this, "While checking size constraint"); + constraint->set_my_type(Type::get_pooltype(Type::T_INT_A)); + constraint->set_my_scope(get_my_scope()); + constraint->set_my_parent(this); + constraint->chk(); + subtype = SubtypeConstraint::create_asn_size_constraint( + constraint->get_subtype(), in_char_context(), my_type, this); + extendable = constraint->is_extendable(); + if (constraint->get_extension()) { + extension = SubtypeConstraint::create_asn_size_constraint( + constraint->get_extension(), in_char_context(), my_type, this); + } + } + + void SizeConstraint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + constraint->set_fullname(p_fullname+".<"+string(constraint->get_name())+">"); + } + + // ================================= + // ===== PermittedAlphabetConstraint + // ================================= + + PermittedAlphabetConstraint::PermittedAlphabetConstraint(const PermittedAlphabetConstraint& p) + : Constraint(p) + { + constraint = p.constraint ? p.constraint->clone() : 0; + } + + PermittedAlphabetConstraint::PermittedAlphabetConstraint(Constraint* p) + : Constraint(CT_PERMITTEDALPHABET), constraint(p) + { + if (!p) FATAL_ERROR("PermittedAlphabetConstraint::PermittedAlphabetConstraint()"); + } + + void PermittedAlphabetConstraint::chk() + { + if (checked) return; + checked = true; + if (!constraint || !my_type) FATAL_ERROR("PermittedAlphabetConstraint::chk()"); + Error_Context cntxt(this, "While checking permitted alphabet constraint"); + constraint->set_my_type(my_type); + constraint->set_my_scope(get_my_scope()); + constraint->set_my_parent(this); + constraint->chk(); + subtype = SubtypeConstraint::create_permitted_alphabet_constraint( + constraint->get_subtype(), in_char_context(), my_type, this); + extendable = constraint->is_extendable(); + if (constraint->get_extension()) { + extension = SubtypeConstraint::create_permitted_alphabet_constraint( + constraint->get_extension(), in_char_context(), my_type, this); + } + } + + void PermittedAlphabetConstraint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + constraint->set_fullname(p_fullname+".<"+string(constraint->get_name())+">"); + } + + // ================================= + // ===== SetOperationConstraint + // ================================= + + SetOperationConstraint::SetOperationConstraint(const SetOperationConstraint& p) + : Constraint(p), operationtype(p.operationtype) + { + operand_a = p.operand_a ? p.operand_a->clone() : 0; + operand_b = p.operand_b ? p.operand_b->clone() : 0; + } + + void SetOperationConstraint::set_first_operand(Constraint* p_a) + { + if (operand_a || !p_a) FATAL_ERROR("SetOperationConstraint::set_first_operand()"); + operand_a = p_a; + } + + SetOperationConstraint::SetOperationConstraint(Constraint* p_a, operationtype_t p_optype, Constraint* p_b) + : Constraint(CT_SETOPERATION), operationtype(p_optype), operand_a(p_a), operand_b(p_b) + { + // p_a can be null + if (!p_b) FATAL_ERROR("SetOperationConstraint::SetOperationConstraint()"); + } + + const char* SetOperationConstraint::get_operationtype_str() const + { + switch (operationtype) { + case UNION: + return "union"; + case INTERSECTION: + return "intersection"; + case EXCEPT: + return "except"; + } + return ""; + } + + void SetOperationConstraint::chk() + { + if (checked) return; + checked = true; + if (!operand_a || !operand_b || !my_type) FATAL_ERROR("SetOperationConstraint::chk()"); + Error_Context cntxt(this, "While checking %s operation", get_operationtype_str()); + operand_a->set_my_type(my_type); + operand_b->set_my_type(my_type); + operand_a->set_my_scope(get_my_scope()); + operand_b->set_my_scope(get_my_scope()); + operand_a->set_my_parent(this); + operand_b->set_my_parent(this); + operand_a->chk(); + operand_b->chk(); + + extendable = (operationtype!=EXCEPT) ? + (operand_a->is_extendable() || operand_b->is_extendable()) : + operand_a->is_extendable(); + SubtypeConstraint::subtype_t my_subtype_type = my_type->get_subtype_type(); + // naming ((r1,x1),...,(r2,x2)) according to X.680(11/2008) I.4.3.8 + SubtypeConstraint* r1 = operand_a->get_subtype(); + SubtypeConstraint* x1 = operand_a->get_extension(); + SubtypeConstraint* r2 = operand_b->get_subtype(); + SubtypeConstraint* x2 = operand_b->get_extension(); + if (!r1 || !r2) return; // something invalid, error already reported there + subtype = new SubtypeConstraint(my_subtype_type); + subtype->copy(r1); + switch (operationtype) { + case UNION: + subtype->union_(r2); + if (x1 || x2) { + extension = new SubtypeConstraint(my_subtype_type); + if (x1 && x2) { + extension->copy(subtype); + extension->union_(x1); + extension->union_(x2); + extension->except(subtype); + } else { + extension->copy(x1?x1:x2); + } + } + break; + case INTERSECTION: + subtype->intersection(r2); + if (x1 || x2) { + extension = new SubtypeConstraint(my_subtype_type); + if (x1 && x2) { + extension->copy(r1); + extension->union_(x1); + SubtypeConstraint* ext_tmp = new SubtypeConstraint(my_subtype_type); + ext_tmp->copy(r2); + ext_tmp->union_(x2); + extension->intersection(ext_tmp); + delete ext_tmp; + extension->except(subtype); + } else { + extension->copy(r1); + extension->intersection(x1?x1:x2); + } + } + break; + case EXCEPT: + subtype->except(r2); + if (x1) { + extension = new SubtypeConstraint(my_subtype_type); + if (x2) { + extension->copy(x1); + SubtypeConstraint* ext_tmp = new SubtypeConstraint(my_subtype_type); + ext_tmp->copy(r2); + ext_tmp->union_(x2); + extension->except(ext_tmp); + delete ext_tmp; + extension->except(subtype); + } else { + extension->copy(x1); + extension->except(r2); + extension->except(subtype); + } + } + break; + default: + FATAL_ERROR("SetOperationConstraint::chk()"); + } + } + + void SetOperationConstraint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + operand_a->set_fullname(p_fullname+"..<"+string(operand_a->get_name())+">"); + operand_b->set_fullname(p_fullname+"..<"+string(operand_b->get_name())+">"); + } + + // ================================= + // ===== FullSetConstraint + // ================================= + + void FullSetConstraint::chk() + { + SubtypeConstraint::subtype_t my_subtype_type = my_type->get_subtype_type(); + subtype = new SubtypeConstraint(my_subtype_type); + } + + // ================================= + // ===== PatternConstraint + // ================================= + + PatternConstraint::PatternConstraint(const PatternConstraint& p) + : Constraint(p) + { + value = p.value ? p.value->clone() : 0; + } + + PatternConstraint::~PatternConstraint() + { + delete value; + } + + PatternConstraint::PatternConstraint(Value* p_value) + : Constraint(CT_PATTERN), value(p_value) + { + if (!p_value) FATAL_ERROR("PatternConstraint::PatternConstraint()"); + } + + void PatternConstraint::chk() + { + if (checked) return; + checked = true; + if (!value || !my_type) FATAL_ERROR("PatternConstraint::chk()"); + Error_Context cntxt(this, "While checking pattern constraint"); + switch (my_type->get_subtype_type()) { + case SubtypeConstraint::ST_CHARSTRING: + case SubtypeConstraint::ST_UNIVERSAL_CHARSTRING: + break; + default: + error("Pattern constraint is not allowed for type `%s'", my_type->get_typename().c_str()); + return; + } + value->set_my_scope(get_my_scope()); + value->set_my_governor(my_type); + my_type->chk_this_value_ref(value); + my_type->chk_this_value(value, 0, Type::EXPECTED_CONSTANT, + INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, NO_SUB_CHK); + // ignore ASN.1 pattern constraint (9.1 Transformation rules, point 4.) + if (in_char_context()) { + error("%s not allowed inside a permitted alphabet constraint", get_name()); + return; + } else { + if (my_parent) warning("%s inside a %s is treated as `ALL' (constraint is dropped)", + get_name(), my_parent->get_name()); + else warning("%s is ignored", get_name()); + } + subtype = new SubtypeConstraint(my_type->get_subtype_type()); + } + + void PatternConstraint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + value->set_fullname(p_fullname+"."); + } + + // ================================= + // ===== SingleInnerTypeConstraint + // ================================= + + SingleInnerTypeConstraint::SingleInnerTypeConstraint(const SingleInnerTypeConstraint& p) + : Constraint(p) + { + constraint = p.constraint ? p.constraint->clone() : 0; + } + + SingleInnerTypeConstraint::SingleInnerTypeConstraint(Constraint* p) + : Constraint(CT_SINGLEINNERTYPE), constraint(p) + { + if (!p) FATAL_ERROR("SingleInnerTypeConstraint::SingleInnerTypeConstraint()"); + } + + void SingleInnerTypeConstraint::chk() + { + if (checked) return; + checked = true; + if (!constraint || !my_type) FATAL_ERROR("SingleInnerTypeConstraint::chk()"); + Error_Context cntxt(this, "While checking inner type constraint"); + Type* t = my_type->get_type_refd_last(); + if (!t->is_seof()) { + error("Single inner type constraint (WITH COMPONENT) cannot be used on type `%s'", my_type->get_typename().c_str()); + return; + } + Type* field_type = t->get_ofType(); // determine the type of the field to which it refers + constraint->set_my_type(field_type); + constraint->set_my_scope(get_my_scope()); + constraint->set_my_parent(this); + constraint->chk(); + //if (constraint->get_subtype()) { // if the constraint was not erroneous + // TODO: this could be added to the a tree structure constraint on my_type, + // tree structure needed because of set operations, constraint cannot + // be added to field_type + //} + // inner subtype is ignored ( ETSI ES 201 873-7 V4.1.2 -> 9.1 Transformation rules ) + subtype = new SubtypeConstraint(my_type->get_subtype_type()); + } + + void SingleInnerTypeConstraint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + constraint->set_fullname(p_fullname+".<"+string(constraint->get_name())+">"); + } + + // ================================= + // ===== NamedConstraint + // ================================= + + NamedConstraint::NamedConstraint(Identifier* p_id, Constraint* p_value_constraint, presence_constraint_t p_presence_constraint): + Constraint(CT_NAMED), id(p_id), value_constraint(p_value_constraint), presence_constraint(p_presence_constraint) + { + if (!id) FATAL_ERROR("NamedConstraint::NamedConstraint()"); + } + + NamedConstraint::NamedConstraint(const NamedConstraint& p) + : Constraint(p) + { + id = p.id->clone(); + value_constraint = p.value_constraint ? p.value_constraint->clone() : 0; + presence_constraint = p.presence_constraint; + } + + NamedConstraint::~NamedConstraint() + { + delete id; + delete value_constraint; + } + + const char* NamedConstraint::get_presence_constraint_name() const + { + switch (presence_constraint) { + case PC_NONE: return ""; + case PC_PRESENT: return "PRESENT"; + case PC_ABSENT: return "ABSENT"; + case PC_OPTIONAL: return "OPTIONAL"; + default: FATAL_ERROR("NamedConstraint::get_presence_constraint_name()"); + } + } + + void NamedConstraint::chk() + { + if (checked) return; + checked = true; + if (!my_type) FATAL_ERROR("NamedConstraint::chk()"); + Error_Context cntxt(this, "While checking named constraint"); + if (value_constraint) { + value_constraint->set_my_type(my_type); + value_constraint->set_my_scope(get_my_scope()); + value_constraint->set_my_parent(this); + value_constraint->chk(); + } + subtype = new SubtypeConstraint(my_type->get_subtype_type()); // ignored + } + + void NamedConstraint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + if (value_constraint) { + value_constraint->set_fullname(p_fullname+".<"+string(value_constraint->get_name())+">"); + } + } + + // ================================= + // ===== MultipleInnerTypeConstraint + // ================================= + + MultipleInnerTypeConstraint::MultipleInnerTypeConstraint(const MultipleInnerTypeConstraint& p) + : Constraint(p) + { + partial = p.partial; + for (size_t i=0; iclone() ); + } + } + + MultipleInnerTypeConstraint::~MultipleInnerTypeConstraint() + { + named_con_map.clear(); + for (size_t i=0; iget_type_refd_last(); + + switch (t->get_typetype()) { + case Type::T_REAL: { // associated ASN.1 type is a SEQUENCE + Identifier t_id(Identifier::ID_ASN, string("REAL")); + t = t->get_my_scope()->get_scope_asss()->get_local_ass_byId(t_id)->get_Type(); + if (t->get_typetype()!=Type::T_SEQ_A) FATAL_ERROR("MultipleInnerTypeConstraint::chk()"); + } break; + case Type::T_CHOICE_A: + case Type::T_SEQ_A: // T_EXTERNAL, T_EMBEDDED_PDV, T_UNRESTRICTEDSTRING + case Type::T_SET_A: + break; + default: + FATAL_ERROR("MultipleInnerTypeConstraint::chk()"); + } + // check that all NamedConstraints refer to an existing component + // if it exists add it to the map<> and check uniqueness + // for SEQUENCE check order of fields + size_t max_idx = 0; // current highest field index, to detect invalid order + bool invalid_order = false; + size_t present_count = 0; + size_t absent_count = 0; + for (size_t i=0; iget_id(); + if (t->has_comp_withName(id)) { + if (named_con_map.has_key(id)) { + named_con_vec[i]->error("Duplicate reference to field `%s' of type `%s'", + id.get_dispname().c_str(), my_type->get_typename().c_str()); + named_con_map[id]->note("Previous reference to field `%s' is here", + id.get_dispname().c_str()); + } else { + named_con_map.add(id, named_con_vec[i]); + if (t->get_typetype()==Type::T_SEQ_A) { + size_t curr_idx = t->get_comp_index_byName(id); + if (curr_idxget_presence_constraint()) { + case NamedConstraint::PC_PRESENT: + present_count++; + break; + case NamedConstraint::PC_ABSENT: + absent_count++; + break; + default: + break; + } + } + CompField* cf = t->get_comp_byName(id); + switch (t->get_typetype()) { + case Type::T_SEQ_A: + case Type::T_SET_A: + if (!cf->get_is_optional() && (named_con_vec[i]->get_presence_constraint()!=NamedConstraint::PC_NONE)) { + named_con_vec[i]->error("Presence constraint `%s' cannot be used on mandatory field `%s'", + named_con_vec[i]->get_presence_constraint_name(), id.get_dispname().c_str()); + } + break; + default: + break; + } + Type* field_type = cf->get_type(); + named_con_vec[i]->set_my_type(field_type); + named_con_vec[i]->set_my_scope(get_my_scope()); + named_con_vec[i]->set_my_parent(this); + named_con_vec[i]->chk(); + } else { + named_con_vec[i]->error("Type `%s' does not have a field named `%s'", + my_type->get_typename().c_str(), id.get_dispname().c_str()); + } + } + if (invalid_order) { + error("The order of fields must be the same as in the definition of type `%s'", + my_type->get_typename().c_str()); + } + if (t->get_typetype()==Type::T_CHOICE_A) { + if (present_count>1) { + error("CHOICE type `%s' cannot have more than one `PRESENT' field", my_type->get_typename().c_str()); + } + // in FullSpecification all not listed fields that can be absent are implicitly ABSENT + size_t real_absent_count = absent_count + ((!get_partial())?(t->get_nof_comps()-named_con_map.size()):0); + if (real_absent_count>=t->get_nof_comps()) { + error("All fields of CHOICE type `%s' are `ABSENT'", my_type->get_typename().c_str()); + if (real_absent_count>absent_count) { + note("%ld not listed field%s implicitly `ABSENT' because FullSpecification was used", + (long)(real_absent_count-absent_count), ((real_absent_count-absent_count)>1)?"s are":" is"); + } + } + } + + // inner subtype is ignored ( ETSI ES 201 873-7 V4.1.2 -> 9.1 Transformation rules ) + subtype = new SubtypeConstraint(my_type->get_subtype_type()); + } + + void MultipleInnerTypeConstraint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + for (size_t i=0; iset_fullname(p_fullname+".<"+string(named_con_vec[i]->get_name())+" "+Int2string(i)+">"); + } + } + + // ================================= + // ===== UnparsedMultipleInnerTypeConstraint + // ================================= + + UnparsedMultipleInnerTypeConstraint::UnparsedMultipleInnerTypeConstraint(const UnparsedMultipleInnerTypeConstraint& p) + : Constraint(p) + { + block = p.block ? p.block->clone() : 0; + constraint = 0; + } + + UnparsedMultipleInnerTypeConstraint::UnparsedMultipleInnerTypeConstraint(Block* p_block) + : Constraint(CT_UNPARSEDMULTIPLEINNERTYPE), block(p_block), constraint(0) + { + if (!block) FATAL_ERROR("UnparsedMultipleInnerTypeConstraint::UnparsedMultipleInnerTypeConstraint()"); + } + + UnparsedMultipleInnerTypeConstraint::~UnparsedMultipleInnerTypeConstraint() + { + delete block; + delete constraint; + } + + void UnparsedMultipleInnerTypeConstraint::chk() + { + if (checked) return; + checked = true; + if (!my_type) FATAL_ERROR("UnparsedMultipleInnerTypeConstraint::chk()"); + Error_Context cntxt(this, "While checking inner type constraint"); + Type* t = my_type->get_type_refd_last(); + switch (t->get_typetype()) { + case Type::T_REAL: // associated ASN.1 type is a SEQUENCE + case Type::T_CHOICE_A: + case Type::T_SEQ_A: // also refd by T_EXTERNAL, T_EMBEDDED_PDV and T_UNRESTRICTEDSTRING + case Type::T_SET_A: + break; + default: + error("Multiple inner type constraint (WITH COMPONENTS) cannot be used on type `%s'", my_type->get_typename().c_str()); + return; + } + Node *node = block->parse(KW_Block_MultipleTypeConstraints); + constraint = dynamic_cast(node); + if (!constraint) { + delete node; + return; // parsing error was already reported + } + constraint->set_my_type(my_type); + constraint->set_my_scope(get_my_scope()); + constraint->set_my_parent(this); + constraint->chk(); + subtype = new SubtypeConstraint(my_type->get_subtype_type()); // ignored + } + + void UnparsedMultipleInnerTypeConstraint::set_fullname(const string& p_fullname) + { + Node::set_fullname(p_fullname); + block->set_fullname(p_fullname); + if (constraint) constraint->set_fullname(p_fullname); + } + +} // namespace Common diff --git a/compiler2/Constraint.hh b/compiler2/Constraint.hh new file mode 100644 index 0000000..59d2fac --- /dev/null +++ b/compiler2/Constraint.hh @@ -0,0 +1,486 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Common_Constraint_HH +#define _Common_Constraint_HH + +#include "Setting.hh" + +namespace Asn { + class Block; +} + +namespace Common { + + /** + * \ingroup Type + * + * \defgroup Constraint Constraint specifications + * + * These classes provide a unified interface for constraints. + * + * @{ + */ + + class Constraint; + class Constraints; + + // not defined here + class Type; + class Value; + class SubtypeConstraint; + class Identifier; + + using Asn::Block; + + /** + * Class to represent Constraint. + */ + class Constraint : public Node, public Location { + public: + enum constrtype_t { + CT_ELEMENTSETSPEC, /** ElementSetSpecsConstraint */ + CT_IGNORE, /**< Constraint : used if erroneous or not yet supported */ + CT_TABLE, /**< TableConstraint */ + CT_SINGLEVALUE, /**< SingleValueConstraint */ + CT_CONTAINEDSUBTYPE, /**< ContainedSubtypeConstraint */ + CT_VALUERANGE, /**< ValueRangeConstraint */ + CT_SIZE, /**< SizeConstraint */ + CT_PERMITTEDALPHABET, /**< PermittedAlphabetConstraint */ + CT_PATTERN, /**< PatternConstraint */ + CT_SETOPERATION, /**< SetOperationConstraint */ + CT_FULLSET, /**< FullSetConstraint */ + CT_SINGLEINNERTYPE, /**< SingleInnerTypeConstraint */ + CT_NAMED, /**< NamedConstraint */ + CT_UNPARSEDMULTIPLEINNERTYPE, /**< UnparsedMultipleInnerTypeConstraint */ + CT_MULTIPLEINNERTYPE /**< MultipleInnerTypeConstraint */ + }; + protected: + constrtype_t constrtype; + Type* my_type; /**< the type to which this constraint belongs to */ + Scope* my_scope; /**< scope or NULL, if NULL then get scope from my_type */ + Constraint* my_parent; /**< the parent constraint node in AST or NULL */ + Constraints* my_cons; /**< the Constraints object or NULL, it is set if this + is the root node of a constraint tree */ + bool checked; /**< set to true by chk() */ + SubtypeConstraint* subtype; /**< NULL or set by chk() if constraint is valid, this is the root part */ + bool extendable; /**< set by chk() */ + SubtypeConstraint* extension; /**< NULL if there is no extension or not valid, set by chk() */ + + Constraint(const Constraint& p); + /// Assignment disabled + Constraint& operator=(const Constraint& p); + public: + Constraint(constrtype_t p_constrtype); + virtual ~Constraint(); + virtual Constraint* clone() const = 0; + constrtype_t get_constrtype() const { return constrtype; } + void set_my_type(Type *p_my_type) { my_type = p_my_type; } + void set_my_parent(Constraint* p_my_parent) { my_parent = p_my_parent; } + Constraint* get_my_parent() const { return my_parent; } + void set_my_scope(Scope* p_my_scope) { my_scope = p_my_scope; } + Scope* get_my_scope(); + void set_my_cons(Constraints* p_my_cons); + Constraints* get_my_cons(); + virtual void chk() = 0; + /** return the subtype constraint */ + SubtypeConstraint* get_subtype() const { return subtype; } + bool is_extendable() const { return extendable; } + SubtypeConstraint* get_extension() const { return extension; } + /** returns the name of this constraint which can be used in error messages */ + virtual const char* get_name() const = 0; + /** if this constraint is inside a FROM() constraint then we are in + a char context */ + bool in_char_context() const; + /** returns true if this constraint is inside a single or multiple inner type constraint */ + bool in_inner_constraint() const; + /** returns if this kind of constraint is ignored, when ignored the + full set is used as it's subtype value + TODO: set operations which have operands that are ignored constraints should + somehow drop or simplify their constraint, example: (inner subtype) EXCEPT (inner subtype) + */ + virtual bool is_ignored() const { return false; } + }; + + /** + * Class to represent constraints. + */ + class Constraints : public Node { + private: + vector cons; + Type *my_type; + SubtypeConstraint* subtype; /**< NULL or set by chk() if constraint is valid, this is the root part */ + bool extendable; /**< set by chk() */ + SubtypeConstraint* extension; /**< NULL if there is no extension or not valid, set by chk() */ + + Constraints(const Constraints& p); + /// Assignment disabled + Constraints& operator=(const Constraints& p); + public: + Constraints() : Node(), cons(), my_type(0), subtype(0), extendable(false), extension(0) {} + virtual ~Constraints(); + virtual Constraints *clone() const; + void add_con(Constraint *p_con); + size_t get_nof_cons() const {return cons.size();} + Constraint* get_con_byIndex(size_t p_i) const { return cons[p_i]; } + Constraint* get_tableconstraint() const; + void set_my_type(Type *p_my_type); + Type* get_my_type() const { return my_type; } + void chk(SubtypeConstraint* parent_subtype); + void chk_table(); + /* return the subtype constraint */ + SubtypeConstraint* get_subtype() const { return subtype; } + bool is_extendable() const { return extendable; } + SubtypeConstraint* get_extension() const { return extension; } + }; + + /** @} end of Constraint group */ + + + // ================================= + // ===== ElementSetSpecsConstraint + // ================================= + + /* This AST element is used only if "..." is present, otherwise it's not + created, therefore the extendable bool is always true in this constraint */ + class ElementSetSpecsConstraint : public Constraint + { + Constraint* root_constr; + Constraint* ext_constr; /* NULL if no extension addition was present */ + ElementSetSpecsConstraint(const ElementSetSpecsConstraint& p); + /// Assignment disabled + ElementSetSpecsConstraint& operator=(const ElementSetSpecsConstraint& p); + public: + ElementSetSpecsConstraint(Constraint* p_root_constr, Constraint* p_ext_constr); + virtual ~ElementSetSpecsConstraint(); + ElementSetSpecsConstraint* clone() const { return new ElementSetSpecsConstraint(*this); } + void chk(); + const char* get_name() const { return "ElementSetSpecs constraint"; } + void set_fullname(const string& p_fullname); + }; + + // ================================= + // ===== IgnoredConstraint + // ================================= + + class IgnoredConstraint : public Constraint + { + const char* my_name; + IgnoredConstraint(const IgnoredConstraint& p); + /// Assignment disabled + IgnoredConstraint& operator=(const IgnoredConstraint& p); + public: + IgnoredConstraint(const char* p_name); + IgnoredConstraint* clone() const { return new IgnoredConstraint(*this); } + void chk(); + const char* get_name() const { return my_name; } + bool is_ignored() const { return true; } + }; + + + // ================================= + // ===== SingleValueConstraint + // ================================= + + class SingleValueConstraint : public Constraint + { + Value* value; + SingleValueConstraint(const SingleValueConstraint& p); + /// Assignment disabled + SingleValueConstraint& operator=(const SingleValueConstraint& p); + public: + SingleValueConstraint(Value* p_value); + virtual ~SingleValueConstraint(); + SingleValueConstraint* clone() const { return new SingleValueConstraint(*this); } + void chk(); + const char* get_name() const { return "single value constraint"; } + void set_fullname(const string& p_fullname); + }; + + // ================================= + // ===== ContainedSubtypeConstraint + // ================================= + + class ContainedSubtypeConstraint : public Constraint + { + Type* type; + bool has_includes; /**< INCLUDES keyword was used, then this cannot be a TypeConstraint, + otherwise it can be both TypeConstraint and ContainedSubtypeConstraint */ + ContainedSubtypeConstraint(const ContainedSubtypeConstraint& p); + /// Assignment disabled + ContainedSubtypeConstraint& operator=(const ContainedSubtypeConstraint& p); + public: + ContainedSubtypeConstraint(Type* p_type, bool p_has_includes); + virtual ~ContainedSubtypeConstraint(); + ContainedSubtypeConstraint* clone() const { return new ContainedSubtypeConstraint(*this); } + void chk(); + const char* get_name() const { return "contained subtype constraint"; } + void set_fullname(const string& p_fullname); + }; + + // ================================= + // ===== RangeEndpoint + // ================================= + + class ValueRangeConstraint; + + class RangeEndpoint : public Node, public Location + { + public: + enum endpoint_t { + MIN, /**< minimum value */ + VALUE, /**< value */ + MAX /**< maximum value */ + }; + private: + endpoint_t type; /**< type of endpoint */ + Value* value; /**< a value or NULL if type!=VALUE */ + bool inclusive; /**< true if the endpoint is part of the range */ + RangeEndpoint(const RangeEndpoint& p); + RangeEndpoint& operator=(const RangeEndpoint& p); // = disabled + public: + RangeEndpoint(endpoint_t p_type); + RangeEndpoint(Value* p_value); + void set_exclusive() { inclusive = false; } + bool get_exclusive() const { return !inclusive; } + endpoint_t get_type() const { return type; } + Value* get_value() const { return value; } + ~RangeEndpoint(); + RangeEndpoint* clone() const { return new RangeEndpoint(*this); } + void chk(Type* my_type, ValueRangeConstraint* constraint); + void set_fullname(const string& p_fullname); + }; + + // ================================= + // ===== ValueRangeConstraint + // ================================= + + class ValueRangeConstraint : public Constraint + { + RangeEndpoint* lower_endpoint; + RangeEndpoint* upper_endpoint; + ValueRangeConstraint(const ValueRangeConstraint& p); + /// Assignment disabled + ValueRangeConstraint& operator=(const ValueRangeConstraint& p); + public: + ValueRangeConstraint(RangeEndpoint* p_lower, RangeEndpoint* p_upper); + virtual ~ValueRangeConstraint() { delete lower_endpoint; delete upper_endpoint; } + ValueRangeConstraint* clone() const { return new ValueRangeConstraint(*this); } + void chk(); + const char* get_name() const { return "value range constraint"; } + void set_fullname(const string& p_fullname); + }; + + // ================================= + // ===== SizeConstraint + // ================================= + + class SizeConstraint : public Constraint + { + Constraint* constraint; + SizeConstraint(const SizeConstraint& p); + /// Assignment disabled + SizeConstraint& operator=(const SizeConstraint& p); + public: + SizeConstraint(Constraint* p); + virtual ~SizeConstraint() { delete constraint; } + SizeConstraint* clone() const { return new SizeConstraint(*this); } + void chk(); + const char* get_name() const { return "size constraint"; } + void set_fullname(const string& p_fullname); + }; + + // ================================= + // ===== PermittedAlphabetConstraint + // ================================= + + class PermittedAlphabetConstraint : public Constraint + { + Constraint* constraint; + PermittedAlphabetConstraint(const PermittedAlphabetConstraint& p); + /// Assignment disabled + PermittedAlphabetConstraint& operator=(const PermittedAlphabetConstraint& p); + public: + PermittedAlphabetConstraint(Constraint* p); + virtual ~PermittedAlphabetConstraint() { delete constraint; } + PermittedAlphabetConstraint* clone() const { return new PermittedAlphabetConstraint(*this); } + void chk(); + const char* get_name() const { return "permitted alphabet constraint"; } + void set_fullname(const string& p_fullname); + }; + + // ================================= + // ===== SetOperationConstraint + // ================================= + + class SetOperationConstraint : public Constraint + { + public: + enum operationtype_t { + UNION, + INTERSECTION, + EXCEPT + }; + private: + operationtype_t operationtype; + Constraint* operand_a; + Constraint* operand_b; + SetOperationConstraint(const SetOperationConstraint& p); + /// Assignment disabled + SetOperationConstraint& operator=(const SetOperationConstraint& p); + public: + SetOperationConstraint(Constraint* p_a, operationtype_t p_optype, Constraint* p_b); + virtual ~SetOperationConstraint() { delete operand_a; delete operand_b; } + void set_first_operand(Constraint* p_a); + SetOperationConstraint* clone() const { return new SetOperationConstraint(*this); } + const char* get_operationtype_str() const; + void chk(); + const char* get_name() const { return get_operationtype_str(); } + void set_fullname(const string& p_fullname); + }; + + // ================================= + // ===== FullSetConstraint + // ================================= + + class FullSetConstraint : public Constraint + { + FullSetConstraint(const FullSetConstraint& p): Constraint(p) {} + /// Assignment disabled + FullSetConstraint& operator=(const FullSetConstraint& p); + public: + FullSetConstraint(): Constraint(CT_FULLSET) {} + FullSetConstraint* clone() const { return new FullSetConstraint(*this); } + void chk(); + const char* get_name() const { return "ALL"; } + }; + + // ================================= + // ===== PatternConstraint + // ================================= + + class PatternConstraint : public Constraint + { + Value* value; + PatternConstraint(const PatternConstraint& p); + /// Assignment disabled + PatternConstraint& operator=(const PatternConstraint& p); + public: + PatternConstraint(Value* p_value); + virtual ~PatternConstraint(); + PatternConstraint* clone() const { return new PatternConstraint(*this); } + void chk(); + const char* get_name() const { return "pattern constraint"; } + void set_fullname(const string& p_fullname); + bool is_ignored() const { return true; } + }; + + // ================================= + // ===== SingleInnerTypeConstraint + // ================================= + + class SingleInnerTypeConstraint : public Constraint + { + Constraint* constraint; + SingleInnerTypeConstraint(const SingleInnerTypeConstraint& p); + /// Assignment disabled + SingleInnerTypeConstraint& operator=(const SingleInnerTypeConstraint& p); + public: + SingleInnerTypeConstraint(Constraint* p); + virtual ~SingleInnerTypeConstraint() { delete constraint; } + SingleInnerTypeConstraint* clone() const { return new SingleInnerTypeConstraint(*this); } + void chk(); + void set_fullname(const string& p_fullname); + const char* get_name() const { return "inner type constraint"; } + bool is_ignored() const { return true; } + }; + + // ================================= + // ===== NamedConstraint + // ================================= + + class NamedConstraint : public Constraint + { + public: + enum presence_constraint_t { + PC_NONE, // presence constraint was not specified + PC_PRESENT, + PC_ABSENT, + PC_OPTIONAL + }; + private: + Identifier* id; + Constraint* value_constraint; // NULL if it was not specified + presence_constraint_t presence_constraint; + NamedConstraint(const NamedConstraint& p); + /// Assignment disabled + NamedConstraint& operator=(const NamedConstraint& p); + public: + NamedConstraint(Identifier* p_id, Constraint* p_value_constraint, presence_constraint_t p_presence_constraint); + ~NamedConstraint(); + const Identifier& get_id() const { return *id; } + Constraint* get_value_constraint() const { return value_constraint; } + presence_constraint_t get_presence_constraint() const { return presence_constraint; } + const char* get_presence_constraint_name() const; + NamedConstraint* clone() const { return new NamedConstraint(*this); } + void chk(); + void set_fullname(const string& p_fullname); + const char* get_name() const { return "named constraint"; } + bool is_ignored() const { return true; } + }; + + // ================================= + // ===== MultipleInnerTypeConstraint + // ================================= + + class MultipleInnerTypeConstraint : public Constraint + { + bool partial; // Full/Partial Specification + vector named_con_vec; + map named_con_map; // values owned by named_con_vec, filled by chk() + MultipleInnerTypeConstraint(const MultipleInnerTypeConstraint& p); + /// Assignment disabled + MultipleInnerTypeConstraint& operator=(const MultipleInnerTypeConstraint& p); + public: + MultipleInnerTypeConstraint(): Constraint(CT_MULTIPLEINNERTYPE) {} + virtual ~MultipleInnerTypeConstraint(); + MultipleInnerTypeConstraint* clone() const { return new MultipleInnerTypeConstraint(*this); } + + void set_partial(bool b) { partial = b; } + bool get_partial() const { return partial; } + void addNamedConstraint(NamedConstraint* named_con); + + void chk(); + void set_fullname(const string& p_fullname); + const char* get_name() const { return "inner type constraint"; } + bool is_ignored() const { return true; } + }; + + // ================================= + // ===== UnparsedMultipleInnerTypeConstraint + // ================================= + + class UnparsedMultipleInnerTypeConstraint : public Constraint + { + Block* block; + MultipleInnerTypeConstraint* constraint; + UnparsedMultipleInnerTypeConstraint(const UnparsedMultipleInnerTypeConstraint& p); + /// Assignment disabled + UnparsedMultipleInnerTypeConstraint& operator=(const UnparsedMultipleInnerTypeConstraint& p); + public: + UnparsedMultipleInnerTypeConstraint(Block* p_block); + virtual ~UnparsedMultipleInnerTypeConstraint(); + UnparsedMultipleInnerTypeConstraint* clone() const { return new UnparsedMultipleInnerTypeConstraint(*this); } + void chk(); + void set_fullname(const string& p_fullname); + const char* get_name() const { return "inner type constraint"; } + bool is_ignored() const { return true; } + }; + +} // namespace Common + +#endif // _Common_Constraint_HH diff --git a/compiler2/EnumItem.cc b/compiler2/EnumItem.cc new file mode 100644 index 0000000..c125b48 --- /dev/null +++ b/compiler2/EnumItem.cc @@ -0,0 +1,149 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "EnumItem.hh" +#include "Value.hh" + +namespace Common { + +// ================================= +// ===== EnumItem +// ================================= + +EnumItem::EnumItem(Identifier *p_name, Value *p_value) +: Node(), Location(), name(p_name), value(p_value) +{ + if (!p_name) FATAL_ERROR("NULL parameter: Common::EnumItem::EnumItem()"); +} + +EnumItem::EnumItem(const EnumItem& p) +: Node(p), Location(p) +{ + name=p.name->clone(); + value=p.value?p.value->clone():0; +} + +EnumItem::~EnumItem() +{ + delete name; + delete value; +} + +EnumItem *EnumItem::clone() const +{ + return new EnumItem(*this); +} + +void EnumItem::set_fullname(const string& p_fullname) +{ + Node::set_fullname(p_fullname); + if(value) value->set_fullname(p_fullname); +} + +void EnumItem::set_my_scope(Scope *p_scope) +{ + if(value) value->set_my_scope(p_scope); +} + +void EnumItem::set_value(Value *p_value) +{ + if(!p_value) FATAL_ERROR("NULL parameter: Common::EnumItem::set_value()"); + if(value) FATAL_ERROR("Common::EnumItem::set_value()"); + value=p_value; +} + +void EnumItem::set_text(const string& p_text) +{ + text = p_text; +} + +string EnumItem::get_name_hacked(Type *p_type) const +{ + if (p_type->is_asn1()) { + string hack_asnname(Identifier::name_2_asn(p_type->get_genname_own())); + hack_asnname += "-enum-"; + hack_asnname += name->get_asnname(); + return Identifier::asn_2_name(hack_asnname); + } else { + string hack_ttcnname(Identifier::name_2_ttcn(p_type->get_genname_own())); + hack_ttcnname += "_enum_"; + hack_ttcnname += name->get_ttcnname(); + return Identifier::ttcn_2_name(hack_ttcnname); + } +} + +void EnumItem::dump(unsigned level) const +{ + name->dump(level); + if(value) { + DEBUG(level, "with value:"); + value->dump(level+1); + } +} + +// ================================= +// ===== EnumItems +// ================================= + +EnumItems::EnumItems(const EnumItems& p) +: Node(p), my_scope(0) +{ + for (size_t i = 0; i < p.eis_v.size(); i++) add_ei(p.eis_v[i]->clone()); +} + +EnumItems::~EnumItems() +{ + for(size_t i = 0; i < eis_v.size(); i++) delete eis_v[i]; + eis_v.clear(); + eis_m.clear(); +} + +void EnumItems::release_eis() +{ + eis_v.clear(); + eis_m.clear(); +} + +EnumItems* EnumItems::clone() const +{ + return new EnumItems(*this); +} + +void EnumItems::set_fullname(const string& p_fullname) +{ + Node::set_fullname(p_fullname); + for (size_t i = 0; i < eis_v.size(); i++) { + EnumItem *ei = eis_v[i]; + ei->set_fullname(p_fullname + "." + ei->get_name().get_dispname()); + } +} + +void EnumItems::set_my_scope(Scope *p_scope) +{ + my_scope = p_scope; + for(size_t i = 0; i < eis_v.size(); i++) + eis_v[i]->set_my_scope(p_scope); +} + +void EnumItems::add_ei(EnumItem *p_ei) +{ + if(!p_ei) + FATAL_ERROR("NULL parameter: Common::EnumItems::add_ei()"); + eis_v.add(p_ei); + const Identifier& id = p_ei->get_name(); + const string& name = id.get_name(); + if (!eis_m.has_key(name)) eis_m.add(name, p_ei); + p_ei->set_fullname(get_fullname()+"."+id.get_dispname()); + p_ei->set_my_scope(my_scope); +} + +void EnumItems::dump(unsigned level) const +{ + for (size_t i = 0; i < eis_v.size(); i++) eis_v[i]->dump(level); +} + +} diff --git a/compiler2/EnumItem.hh b/compiler2/EnumItem.hh new file mode 100644 index 0000000..62be404 --- /dev/null +++ b/compiler2/EnumItem.hh @@ -0,0 +1,80 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef ENUM_HH_ +#define ENUM_HH_ + +#include "Setting.hh" +#include "Identifier.hh" + +namespace Common { + +/** + * Class to represent an Enumeration item. Is like a NamedValue, but + * the value can be NULL, and a(n integer) value can be assigned + * later. + */ +class EnumItem : public Node, public Location { +private: + Identifier *name; + Value *value; + string text; ///< for TEXT encoding instruction + /** Copy constructor not implemented */ + EnumItem(const EnumItem&); + /** Assignment disabled */ + EnumItem& operator=(const EnumItem&); +public: + EnumItem(Identifier *p_name, Value *p_value); + virtual ~EnumItem(); + virtual EnumItem *clone() const; + virtual void set_fullname(const string& p_fullname); + const Identifier& get_name() const { return *name; } + /// Return the name for the "enum hack" + string get_name_hacked(Type *p_type) const; + Value *get_value() const { return value; } + void set_value(Value *p_value); + const string& get_text() const { return text; } + void set_text(const string& p_text); + virtual void set_my_scope(Scope *p_scope); + virtual void dump(unsigned level) const; +}; + +/** + * Class to represent a collection of enumerated items. + */ +class EnumItems : public Node { +private: + Scope *my_scope; + vector eis_v; + /** Stores the first occurrence of EnumItem with id. The string key + * refers to the id of the ei, the value is the ei itself. */ + map eis_m; + /** Copy constructor not implemented */ + EnumItems(const EnumItems& p); + /** Assignment disabled */ + EnumItems& operator=(const EnumItems& p); +public: + EnumItems() : Node(), my_scope(0), eis_v(), eis_m() { } + virtual ~EnumItems(); + /** Clears the vector and the map, but does not delete the items */ + void release_eis(); + virtual EnumItems *clone() const; + virtual void set_fullname(const string& p_fullname); + void set_my_scope(Scope *p_scope); + void add_ei(EnumItem *p_nv); + size_t get_nof_eis() const { return eis_v.size(); } + EnumItem* get_ei_byIndex(const size_t p_i) { return eis_v[p_i]; } + bool has_ei_withName(const Identifier& p_name) const + { return eis_m.has_key(p_name.get_name()); } + EnumItem* get_ei_byName(const Identifier& p_name) const + { return eis_m[p_name.get_name()]; } + virtual void dump(unsigned level) const; +}; + +} + +#endif /* ENUM_HH_ */ diff --git a/compiler2/Identifier.cc b/compiler2/Identifier.cc new file mode 100644 index 0000000..9632a0e --- /dev/null +++ b/compiler2/Identifier.cc @@ -0,0 +1,1397 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "../common/dbgnew.hh" +#include "Identifier.hh" +#include +#include "Setting.hh" +#include "CompilerError.hh" + +namespace Common { + + // ================================= + // ===== Identifier::id_data_t + // ================================= + + struct Identifier::id_data_t { + size_t ref_count; + string name, asnname, ttcnname; + /** ASN kind of the identifier. */ + enum asn_kind_t { + ASN_UNDEF, /**< undefined */ + ASN_LOWER, /**< LOWERIDENTIFIER [a-z](-?[A-Za-z0-9]+)* */ + ASN_UPPER, /**< UPPERIDENTIFIER [A-Z](-?[A-Za-z0-9]+)* */ + ASN_ALLUPPER, /**< ALLUPPERIDENTIFIER [A-Z](-?[A-Z0-9]+)* */ + ASN_WORD, /**< WORD [A-Z](-?[A-Z]+)* */ + ASN_ampUPPER, /**< ampUPPERIDENTIFIER \\\&{UPPERIDENTIFIER} */ + ASN_ampLOWER /**< ampLOWERIDENTIFIER \\\&{LOWERIDENTIFIER} */ + } asn_kind; + static void asn_2_name(string& p_to, const string& p_from); + static void name_2_asn(string& p_to, const string& p_from); + static void ttcn_2_name(string& p_to, const string& p_from); + static void name_2_ttcn(string& p_to, const string& p_from); + id_data_t(const string& p_name) + : ref_count(1), name(p_name), asnname(), ttcnname(), asn_kind(ASN_UNDEF){} + static void delete_this(id_data_t *p_id_data_t); + /** Gets the internal (and C++) name. */ + const string& get_name() const {return name;} + /** Gets the ASN display name. */ + const string& get_asnname(); + /** Gets the TTCN display name. */ + const string& get_ttcnname(); + bool get_has_valid(id_t p_id_t); + string get_names() const; + /** True if it is a valid ASN modulereference. */ + bool isvalid_asn_modref(); + /** True if it is a valid ASN typereference. */ + bool isvalid_asn_typeref(); + /** True if it is a valid ASN valuereference. */ + bool isvalid_asn_valref(); + /** True if it is a valid ASN valuesetreference. */ + bool isvalid_asn_valsetref(); + /** True if it is a valid ASN objectclassreference. */ + bool isvalid_asn_objclassref(); + /** True if it is a valid ASN objectreference. */ + bool isvalid_asn_objref(); + /** True if it is a valid ASN objectsetreference. */ + bool isvalid_asn_objsetref(); + /** True if it is a valid ASN typefieldreference. */ + bool isvalid_asn_typefieldref(); + /** True if it is a valid ASN valuefieldreference. */ + bool isvalid_asn_valfieldref(); + /** True if it is a valid ASN valuesetfieldreference. */ + bool isvalid_asn_valsetfieldref(); + /** True if it is a valid ASN objectfieldreference. */ + bool isvalid_asn_objfieldref(); + /** True if it is a valid ASN objectsetfieldreference. */ + bool isvalid_asn_objsetfieldref(); + /** True if it is a valid ASN "word". */ + bool isvalid_asn_word(); + private: + ~id_data_t() {} + void decide_asn_kind(); + }; + + // ================================= + // ===== internal_data_t + // ================================= + + class internal_data_t { + private: + static internal_data_t *instance; + static const char* const keywords[][3]; + size_t identifier_counter; + public: + const string string_invalid; + /** Container for identifiers, indexed by ID_NAME. */ + map id_map_name; + /** Container for identifiers, indexed by ID_ASN. */ + map id_map_asn; + /** Container for identifiers, indexed by ID_TTCN. */ + map id_map_ttcn; + private: + internal_data_t(); + internal_data_t(const internal_data_t&); + ~internal_data_t(); + void add_keyword(const char* const keyword[3]); + void add_keywords(); + public: + static internal_data_t *Instance(); + /** Increases the instance counter. Initializes the keywords if + * this is the first instance. Must be called in every Identifier + * constructor. */ + void increase_counter(); + /** Decreases the instance counter. Finalizes the keywords if this + * is the last instance. Must be called in Identifier + * destructor. */ + void decrease_counter(); + }; + + // ====================================================================== + // ====================================================================== + + // ================================= + // ===== Identifier::id_data_t + // ================================= + + void Identifier::id_data_t::asn_2_name(string& p_to, const string& p_from) + { + p_to = p_from; + /* "@aaa" -> "_root_aaa" */ + if (p_to.size() > 0 && p_to[0] == '@') p_to.replace(0, 1, "_root_"); + /* "aa..bb" -> "aa.bb" */ + size_t pos = 0; + while ((pos = p_to.find(".<", pos)) < p_to.size()) { + size_t pos2 = p_to.find(">.", pos); + if (pos2 < p_to.size()) p_to.replace(pos, pos2 + 1 - pos, ""); + else break; + } + /* "-" -> "__" */ + pos = 0; + while ((pos = p_to.find('-', pos)) < p_to.size()) { + p_to.replace(pos, 1, "__"); + pos += 2; + } + /* "." -> "_" */ + pos = 0; + while ((pos = p_to.find('.', pos)) < p_to.size()) { + p_to[pos] = '_'; + pos++; + } + /* "&" -> "" */ + pos = 0; + while ((pos = p_to.find('&', pos)) < p_to.size()) + p_to.replace(pos, 1, ""); + } + + void Identifier::id_data_t::name_2_asn(string& p_to, const string& p_from) + { + p_to = p_from; + /* remove leading '_'s */ + size_t pos = 0; + while (pos < p_to.size() && p_to[pos] == '_') pos++; + if (pos > 0) p_to.replace(0, pos, ""); + /* remove trailing '_'s */ + pos = p_to.size(); + while (pos > 0 && p_to[pos - 1] == '_') pos--; + if (pos < p_to.size()) p_to.resize(pos); + /* "__" -> "-" */ + pos = 0; + while ((pos = p_to.find("__", pos)) < p_to.size()) { + p_to.replace(pos, 2, "-"); + pos++; + } + /* "_" -> "-" */ + pos = 0; + while ((pos = p_to.find('_', pos)) < p_to.size()) { + p_to[pos] = '-'; + pos++; + } + } + + void Identifier::id_data_t::ttcn_2_name(string& p_to, const string& p_from) + { + p_to = p_from; + /* "_" -> "__" */ + size_t pos = 0; + while ((pos = p_to.find('_', pos)) < p_to.size()) { + p_to.replace(pos, 1, "__"); + pos += 2; + } + } + + void Identifier::id_data_t::name_2_ttcn(string& p_to, const string& p_from) + { + p_to = p_from; + /* remove leading '_'s */ + size_t pos = 0; + while (pos < p_to.size() && p_to[pos] == '_') pos++; + if (pos > 0) p_to.replace(0, pos, ""); + /* remove trailing '_'s */ + pos = p_to.size(); + while (pos > 0 && p_to[pos - 1] == '_') pos--; + if (pos < p_to.size()) p_to.resize(pos); + /* "__" -> "_" */ + pos = 0; + while ((pos = p_to.find("__", pos)) < p_to.size()) { + p_to.replace(pos, 1, ""); + pos++; + } + } + + const string& Identifier::id_data_t::get_asnname() + { + if (asnname.empty()) name_2_asn(asnname, name); + return asnname; + } + + const string& Identifier::id_data_t::get_ttcnname() + { + if (ttcnname.empty()) name_2_ttcn(ttcnname, name); + return ttcnname; + } + + bool Identifier::id_data_t::get_has_valid(id_t p_id_t) + { + const string& inval=internal_data_t::Instance()->string_invalid; + switch(p_id_t) { + case ID_NAME: + return get_name()!=inval; + case ID_ASN: + return get_asnname()!=inval; + case ID_TTCN: + return get_ttcnname()!=inval; + default: + FATAL_ERROR("Identifier::id_data_t::get_has_valid()"); + return false; + } + } + + void Identifier::id_data_t::delete_this(id_data_t *p_id_data_t) + { + p_id_data_t->ref_count--; + if(p_id_data_t->ref_count==0) + delete p_id_data_t; + } + + string Identifier::id_data_t::get_names() const + { + const string& inval=internal_data_t::Instance()->string_invalid; + string s="(C++: `"+name+"'"; + if(!asnname.empty() && asnname!=inval) + s+=", ASN: `"+asnname+"'"; + if(!ttcnname.empty() && ttcnname!=inval) + s+=", TTCN: `"+ttcnname+"'"; + s+=")"; + return s; + } + + void Identifier::id_data_t::decide_asn_kind() + { + if(asn_kind!=ASN_UNDEF) return; + get_asnname(); + if(asnname==internal_data_t::Instance()->string_invalid) return; + if(asnname[0]=='&') { + if(asnname.size()>=2) { + if(isupper(asnname[1])) + asn_kind=ASN_ampUPPER; + else if(islower(asnname[1])) + asn_kind=ASN_ampLOWER; + } + } + else if(islower(asnname[0])) { + asn_kind=ASN_LOWER; + } + else if(isupper(asnname[0])) { + asn_kind=ASN_UPPER; + if(asnname.find_if(0, asnname.size(), islower)==asnname.size()) { + asn_kind=ASN_ALLUPPER; + if(asnname.find_if(0, asnname.size(), isdigit)==asnname.size()) { + asn_kind=ASN_WORD; + } + } + } + } + + bool Identifier::id_data_t::isvalid_asn_modref() + { + return isvalid_asn_typeref(); + } + + bool Identifier::id_data_t::isvalid_asn_typeref() + { + decide_asn_kind(); + return (asn_kind==ASN_UPPER + || asn_kind==ASN_ALLUPPER + || asn_kind==ASN_WORD); + } + + bool Identifier::id_data_t::isvalid_asn_valref() + { + decide_asn_kind(); + return (asn_kind==ASN_LOWER); + } + + bool Identifier::id_data_t::isvalid_asn_valsetref() + { + return isvalid_asn_typeref(); + } + + bool Identifier::id_data_t::isvalid_asn_objclassref() + { + decide_asn_kind(); + return (asn_kind==ASN_ALLUPPER + || asn_kind==ASN_WORD); + } + + bool Identifier::id_data_t::isvalid_asn_objref() + { + decide_asn_kind(); + return (asn_kind==ASN_LOWER); + } + + bool Identifier::id_data_t::isvalid_asn_objsetref() + { + return isvalid_asn_typeref(); + } + + bool Identifier::id_data_t::isvalid_asn_typefieldref() + { + decide_asn_kind(); + return (asn_kind==ASN_ampUPPER); + } + + bool Identifier::id_data_t::isvalid_asn_valfieldref() + { + decide_asn_kind(); + return (asn_kind==ASN_ampLOWER); + } + + bool Identifier::id_data_t::isvalid_asn_valsetfieldref() + { + decide_asn_kind(); + return (asn_kind==ASN_ampUPPER); + } + + bool Identifier::id_data_t::isvalid_asn_objfieldref() + { + decide_asn_kind(); + return (asn_kind==ASN_ampLOWER); + } + + bool Identifier::id_data_t::isvalid_asn_objsetfieldref() + { + decide_asn_kind(); + return (asn_kind==ASN_ampUPPER); + } + + bool Identifier::id_data_t::isvalid_asn_word() + { + decide_asn_kind(); + return (asn_kind==ASN_WORD); + } + + // ================================= + // ===== internal_data_t + // ================================= + + internal_data_t *internal_data_t::instance=0; + + /* format: c++ - asn - ttcn */ + const char* const internal_data_t::keywords[][3] = { + /* C++ keywords - never can be used */ + {"and", 0, 0}, + {"and_eq", 0, 0}, + {"asm", 0, 0}, + {"auto", 0, 0}, + {"bitand", 0, 0}, + {"bitor", 0, 0}, + {"bool", 0, 0}, + {"break", 0, 0}, + {"case", 0, 0}, + {"catch", 0, 0}, + {"char", 0, 0}, + {"class", 0, 0}, + {"compl", 0, 0}, + {"const", 0, 0}, + {"const_cast", 0, 0}, + {"continue", 0, 0}, + {"default", 0, 0}, + {"delete", 0, 0}, + {"do", 0, 0}, + {"double", 0, 0}, + {"dynamic_cast", 0, 0}, + {"else", 0, 0}, + {"enum", 0, 0}, + {"explicit", 0, 0}, + {"export", 0, 0}, + {"extern", 0, 0}, + {"false", 0, 0}, + {"float", 0, 0}, + {"for", 0, 0}, + {"friend", 0, 0}, + {"goto", 0, 0}, + {"if", 0, 0}, + {"inline", 0, 0}, + {"int", 0, 0}, + {"long", 0, 0}, + {"mutable", 0, 0}, + {"namespace", 0, 0}, + {"new", 0, 0}, + {"not", 0, 0}, + {"not_eq", 0, 0}, + {"operator", 0, 0}, + {"or", 0, 0}, + {"or_eq", 0, 0}, + {"private", 0, 0}, + {"protected", 0, 0}, + {"public", 0, 0}, + {"register", 0, 0}, + {"reinterpret_cast", 0, 0}, + {"return", 0, 0}, + {"short", 0, 0}, + {"signed", 0, 0}, + {"sizeof", 0, 0}, + {"static", 0, 0}, + {"static_cast", 0, 0}, + {"struct", 0, 0}, + {"switch", 0, 0}, + {"template", 0, 0}, + {"this", 0, 0}, + {"throw", 0, 0}, + {"true", 0, 0}, + {"try", 0, 0}, + {"typedef", 0, 0}, + {"typeid", 0, 0}, + {"typename", 0, 0}, + {"union", 0, 0}, + {"unsigned", 0, 0}, + {"using", 0, 0}, + {"virtual", 0, 0}, + {"void", 0, 0}, + {"volatile", 0, 0}, + {"wchar_t", 0, 0}, + {"while", 0, 0}, + {"xor", 0, 0}, + {"xor_eq", 0, 0}, + /* C++ keywords postfixed, avoiding conflicts from valid ASN/TTCN names */ + {"asm_", "asm", "asm"}, + {"auto_", "auto", "auto"}, + {"bitand_", "bitand", "bitand"}, + {"bitor_", "bitor", "bitor"}, + {"bool_", "bool", "bool"}, + {"class_", "class", "class"}, + {"compl_", "compl", "compl"}, + {"delete_", "delete", "delete"}, + {"double_", "double", "double"}, + {"enum_", "enum", "enum"}, + {"explicit_", "explicit", "explicit"}, + {"export_", "export", "export"}, + {"extern_", "extern", "extern"}, + {"friend__", "friend", "friend_"}, + {"inline_", "inline", "inline"}, + {"int_", "int", "int"}, + {"long_", "long", "long"}, + {"mutable_", "mutable", "mutable"}, + {"namespace_", "namespace", "namespace"}, + {"new_", "new", "new"}, + {"operator_", "operator", "operator"}, + {"private__", "private", "private_"}, + {"protected_", "protected", "protected"}, + {"public__", "public", "public_"}, + {"register_", "register", "register"}, + {"short_", "short", "short"}, + {"signed_", "signed", "signed"}, + {"static_", "static", "static"}, + {"struct_", "struct", "struct"}, + {"switch_", "switch", "switch"}, + {"this_", "this", "this"}, + {"throw_", "throw", "throw"}, + {"try_", "try", "try"}, + {"typedef_", "typedef", "typedef"}, + {"typeid_", "typeid", "typeid"}, + {"typename_", "typename", "typename"}, + {"unsigned_", "unsigned", "unsigned"}, + {"using_", "using", "using"}, + {"virtual_", "virtual", "virtual"}, + {"void_", "void", "void"}, + {"volatile_", "volatile", "volatile"}, + /* C++ keywords postfixed - keywords in TTCN */ + {"and__", "and", "and_"}, + {"break__", "break", "break_"}, + {"case__", "case", "case_"}, + {"catch__", "catch", "catch_"}, + {"char__", "char", "char_"}, + {"const__", "const", "const_"}, + {"continue__", "continue", "continue_"}, + {"default__", "default", "default_"}, + {"do__", "do", "do_"}, + {"else__", "else", "else_"}, + {"false__", "false", "false_"}, + {"float__", "float", "float_"}, + {"for__", "for", "for_"}, + {"goto__", "goto", "goto_"}, + {"if__", "if", "if_"}, + {"not__", "not", "not_"}, + {"or__", "or", "or_"}, + {"return__", "return", "return_"}, + {"sizeof__", "sizeof", "sizeof_"}, + {"template__", "template", "template_"}, + {"true__", "true", "true_"}, + {"union__", "union", "union_"}, + {"while__", "while", "while_"}, + {"xor__", "xor", "xor_"}, + /* reserved names of base library */ + {"CHAR", 0, 0}, + {"ERROR", 0, 0}, + {"FAIL", 0, 0}, + {"INCONC", 0, 0}, + {"FALSE", 0, 0}, + {"NONE", 0, 0}, + {"OPTIONAL", 0, 0}, + {"PASS", 0, 0}, + {"PORT", 0, 0}, + {"TIMER", 0, 0}, + {"TRUE", 0, 0}, + {"bit2hex", 0, 0}, + {"bit2int", 0, 0}, + {"bit2oct", 0, 0}, + {"bit2str", 0, 0}, + {"boolean", 0, 0}, + {"char2int", 0, 0}, + {"char2oct", 0, 0}, + {"component", 0, 0}, + {"decomp", 0, 0}, + {"float2int", 0, 0}, + {"float2str", 0, 0}, + {"hex2bit", 0, 0}, + {"hex2int", 0, 0}, + {"hex2oct", 0, 0}, + {"hex2str", 0, 0}, + {"int2bit", 0, 0}, + {"int2char", 0, 0}, + {"int2float", 0, 0}, + {"int2hex", 0, 0}, + {"int2oct", 0, 0}, + {"int2str", 0, 0}, + {"int2unichar", 0, 0}, + {"ischosen", 0, 0}, + {"ispresent", 0, 0}, + {"isvalue", 0, 0}, + {"lengthof", 0, 0}, + {"log", 0, 0}, + {"log2str", 0, 0}, + {"main", 0, 0}, + {"match", 0, 0}, + {"mod", 0, 0}, + {"oct2bit", 0, 0}, + {"oct2char", 0, 0}, + {"oct2hex", 0, 0}, + {"oct2int", 0, 0}, + {"oct2str", 0, 0}, + {"regexp", 0, 0}, + {"replace", 0, 0}, + {"rem", 0, 0}, + {"rnd", 0, 0}, + {"self", 0, 0}, + {"stderr", 0, 0}, // temporary hack + {"stdin", 0, 0}, // temporary hack + {"stdout", 0, 0}, // temporary hack + {"str2bit", 0, 0}, + {"str2float", 0, 0}, + {"str2hex", 0, 0}, + {"str2int", 0, 0}, + {"str2oct", 0, 0}, + {"substr", 0, 0}, + {"unichar2int", 0, 0}, + {"unichar2char", 0, 0}, + {"valueof", 0, 0}, + {"verdicttype", 0, 0}, + {"unichar2oct", 0, 0}, + {"oct2unichar", 0, 0}, + {"get_stringencoding", 0, 0}, + {"remove_bom", 0, 0}, + {"encode_base64", 0, 0}, + {"decode_base64", 0, 0}, + /* reserved names of base library - keywords in TTCN - valid ASN.1 */ + {"bit2hex__", "bit2hex", "bit2hex_"}, + {"bit2int__", "bit2int", "bit2int_"}, + {"bit2oct__", "bit2oct", "bit2oct_"}, + {"bit2str__", "bit2str", "bit2str_"}, + {"boolean__", "boolean", "boolean_"}, + {"char2int__", "char2int", "char2int_"}, + {"char2oct__", "char2oct", "char2oct_"}, + {"component__", "component", "component_"}, + {"decomp__", "decomp", "decomp_"}, + {"float2int__", "float2int", "float2int_"}, + {"float2str__", "float2str", "float2str_"}, + {"hex2bit__", "hex2bit", "hex2bit_"}, + {"hex2int__", "hex2int", "hex2int_"}, + {"hex2oct__", "hex2oct", "hex2oct_"}, + {"hex2str__", "hex2str", "hex2str_"}, + {"int2bit__", "int2bit", "int2bit_"}, + {"int2char__", "int2char", "int2char_"}, + {"int2float__", "int2float", "int2float_"}, + {"int2hex__", "int2hex", "int2hex_"}, + {"int2oct__", "int2oct", "int2oct_"}, + {"int2str__", "int2str", "int2str_"}, + {"int2unichar__", "int2unichar", "int2unichar_"}, + {"ischosen__", "ischosen", "ischosen_"}, + {"ispresent__", "ispresent", "ispresent_"}, + {"isvalue__", "isvalue", "isvalue_"}, + {"lengthof__", "lengthof", "lengthof_"}, + {"log__", "log", "log_"}, + {"log2str__", "log2str", "log2str_"}, + {"match__", "match", "match_"}, + {"mod__", "mod", "mod_"}, + {"oct2bit__", "oct2bit", "oct2bit_"}, + {"oct2char__", "oct2char", "oct2char_"}, + {"oct2hex__", "oct2hex", "oct2hex_"}, + {"oct2int__", "oct2int", "oct2int_"}, + {"oct2str__", "oct2str", "oct2str_"}, + {"regexp__", "regexp", "regexp_"}, + {"replace__", "replace", "replace_"}, + {"rem__", "rem", "rem_"}, + {"rnd__", "rnd", "rnd_"}, + {"self__", "self", "self_"}, + {"str2bit__", "str2bit", "str2bit_"}, + {"str2float__", "str2float", "str2float_"}, + {"str2hex__", "str2hex", "str2hex_"}, + {"str2int__", "str2int", "str2int_"}, + {"str2oct__", "str2oct", "str2oct_"}, + {"substr__", "substr", "substr_"}, + {"unichar2int__", "unichar2int", "unichar2int_"}, + {"unichar2char__", "unichar2char", "unichar2char_"}, + {"valueof__", "valueof", "valueof_"}, + {"verdicttype__", "verdicttype", "verdicttype_"}, + {"ttcn2string__", "ttcn2string", "ttcn2string_"}, + {"string2ttcn__", "string2ttcn", "string2ttcn_"}, + {"unichar2oct__", "unichar2oct", "unichar2oct_"}, + {"oct2unichar__", "oct2unichar", "oct2unichar_"}, + {"remove__bom__", "remove_bom", "remove_bom_"}, + {"encode__base64__", "encode_base64", "encode_base64_"}, + {"decode__base64__", "decode_base64", "decode_base64_"}, + {"get__stringencoding__", "get_stringencoding", "get_stringencoding_"}, + /* reserved names of base library - keywords in ASN.1 */ + {"FALSE_", 0, "FALSE"}, + {"OPTIONAL_", 0, "OPTIONAL"}, + {"TRUE_", 0, "TRUE"}, + /* reserved names of base library - not keywords */ + {"CHAR_", "CHAR", "CHAR"}, + {"ERROR_", "ERROR", "ERROR"}, + {"FAIL_", "FAIL", "FAIL"}, + {"INCONC_", "INCONC", "INCONC"}, + {"NONE_", "NONE", "NONE"}, + {"PASS_", "PASS", "PASS"}, + {"PORT_", "PORT", "PORT"}, + {"TIMER_", "TIMER", "TIMER"}, + {"main_", "main", "main"}, + {"stderr_", "stderr", "stderr"}, // temporary hack + {"stdin_", "stdin", "stdin"}, // temporary hack + {"stdout_", "stdout", "stdout"}, // temporary hack + {"TTCN3_", "TTCN3", "TTCN3"}, + /* built-in types. this is the ASN/TTCN -> C++ name mapping */ + {"ADDRESS", 0, "address"}, + {"ASN_NULL", "NULL", 0}, + {"BITSTRING", "BIT STRING", "bitstring"}, + {"BOOLEAN", "BOOLEAN", "boolean"}, + {"BMPString", "BMPString", 0}, + {"CHARSTRING", 0, "charstring"}, + {"CHARACTER_STRING", "CHARACTER STRING", 0}, + {"COMPONENT", 0, "component"}, + {"DEFAULT", 0, "default"}, + {"EMBEDDED_PDV", "EMBEDDED PDV", 0}, + {"EXTERNAL", "EXTERNAL", 0}, + {"FLOAT", "REAL", "float"}, + {"GraphicString", "GraphicString", 0}, + {"HEXSTRING", 0, "hexstring"}, + {"IA5String", "IA5String", 0}, + {"INTEGER", "INTEGER", "integer"}, + {"ISO646String", "ISO646String", 0}, + {"NumericString", "NumericString", 0}, + {"OBJID", "OBJECT IDENTIFIER", "objid"}, + {"OCTETSTRING", "OCTET STRING", "octetstring"}, + {"ObjectDescriptor", "ObjectDescriptor", 0}, + {"PrintableString", "PrintableString", 0}, + {"T61String", "T61String", 0}, + {"TeletexString", "TeletexString", 0}, + {"UTF8String", "UTF8String", 0}, + {"UniversalString", "UniversalString", 0}, + {"UNIVERSAL_CHARSTRING", 0, "universal charstring"}, + {"VERDICTTYPE", 0, "verdicttype"}, + {"VideotexString", "VideotexString", 0}, + {"VisibleString", "VisibleString", 0}, + /* reserved names of built-in types - valid ASN.1/TTCN names */ + {"ADDRESS_", "ADDRESS", "ADDRESS"}, + {"BITSTRING_", "BITSTRING", "BITSTRING"}, + {"BOOLEAN_", 0, "BOOLEAN"}, + {"BMPString_", 0, "BMPString"}, + {"CHARSTRING_", "CHARSTRING", "CHARSTRING"}, + {"COMPONENT_", "COMPONENT", "COMPONENT"}, + {"DEFAULT_", 0, "DEFAULT"}, + {"EXTERNAL_", 0, "EXTERNAL"}, + {"FLOAT_", "FLOAT", "FLOAT"}, + {"GraphicString_", 0, "GraphicString"}, + {"HEXSTRING_", "HEXSTRING", "HEXSTRING"}, + {"IA5String_", 0, "IA5String"}, + {"INTEGER_", 0, "INTEGER"}, + {"ISO646String_", 0, "ISO646String"}, + {"NumericString_", 0, "NumericString"}, + {"OBJID_", "OBJID", "OBJID"}, + {"OCTETSTRING_", "OCTETSTRING", "OCTETSTRING"}, + {"ObjectDescriptor_", 0, "ObjectDescriptor"}, + {"PrintableString_", 0, "PrintableString"}, + {"T61String_", 0, "T61String"}, + {"TeletexString_", 0, "TeletexString"}, + {"UTF8String_", 0, "UTF8String"}, + {"UniversalString_", 0, "UniversalString"}, + {"VERDICTTYPE_", "VERDICTTYPE", "VERDICTTYPE"}, + {"VideotexString_", 0, "VideotexString"}, + {"VisibleString_", 0, "VisibleString"}, + /* keywords in TTCN-3, not reserved words in C++, postfixed in TTCN */ + {"action__", "action", "action_"}, + {"activate__", "activate", "activate_"}, + {"address__", "address", "address_"}, + {"alive__", "alive", "alive_"}, + {"all__", "all", "all_"}, + {"alt__", "alt", "alt_"}, + {"altstep__", "altstep", "altstep_"}, + {"and4b__", "and4b", "and4b_"}, + {"any__", "any", "any_"}, + {"anytype__", "anytype", "anytype_"}, + {"apply__", "apply", "apply_"}, + {"bitstring__", "bitstring", "bitstring_"}, + {"call__", "call", "call_"}, + {"charstring__", "charstring", "charstring_"}, + {"check__", "check", "check_"}, + {"clear__", "clear", "clear_"}, + {"complement__", "complement", "complement_"}, + {"connect__", "connect", "connect_"}, + {"control__", "control", "control_"}, + {"create__", "create", "create_"}, + {"deactivate__", "deactivate", "deactivate_"}, + {"derefers__", "derefers", "derefers_"}, + {"disconnect__", "disconnect", "disconnect_"}, + {"display__", "display", "display_"}, + {"done__", "done", "done_"}, + {"encode__", "encode", "encode_"}, + {"enumerated__", "enumerated", "enumerated_"}, + {"error__", "error", "error_"}, + {"except__", "except", "except_"}, + {"exception__", "exception", "exception_"}, + {"execute__", "execute", "execute_"}, + {"extends__", "extends", "extends_"}, + {"extension__", "extension", "extension_"}, + {"external__", "external", "external_"}, + {"fail__", "fail", "fail_"}, + {"from__", "from", "from_"}, + {"function__", "function", "function_"}, + {"getcall__", "getcall", "getcall_"}, + {"getreply__", "getreply", "getreply_"}, + {"getverdict__", "getverdict", "getverdict_"}, + {"group__", "group", "group_"}, + {"halt__", "halt", "halt_"}, + {"hexstring__", "hexstring", "hexstring_"}, + {"ifpresent__", "ifpresent", "ifpresent_"}, + {"import__", "import", "import_"}, + {"in__", "in", "in_"}, + {"inconc__", "inconc", "inconc_"}, + {"infinity__", "infinity", "infinity_"}, + {"inout__", "inout", "inout_"}, + {"integer__", "integer", "integer_"}, + {"interleave__", "interleave", "interleave_"}, + {"kill__", "kill", "kill_"}, + {"killed__", "killed", "killed_"}, + {"label__", "label", "label_"}, + {"language__", "language", "language_"}, + {"length__", "length", "length_"}, + {"map__", "map", "map_"}, + {"message__", "message", "message_"}, + {"mixed__", "mixed", "mixed_"}, + {"modifies__", "modifies", "modifies_"}, + {"module__", "module", "module_"}, + {"modulepar__", "modulepar", "modulepar_"}, + {"mtc__", "mtc", "mtc_"}, + {"noblock__", "noblock", "noblock_"}, + {"none__", "none", "none_"}, + {"not4b__", "not4b", "not4b_"}, + {"nowait__", "nowait", "nowait_"}, + {"null__", "null", "null_"}, + {"objid__", "objid", "objid_"}, + {"octetstring__", "octetstring", "octetstring_"}, + {"of__", "of", "of_"}, + {"omit__", "omit", "omit_"}, + {"on__", "on", "on_"}, + {"optional__", "optional", "optional_"}, + {"or4b__", "or4b", "or4b_"}, + {"out__", "out", "out_"}, + {"override__", "override", "override_"}, + {"param__", "param", "param_"}, + {"pass__", "pass", "pass_"}, + {"pattern__", "pattern", "pattern_"}, + {"permutation__", "permutation", "permutation_"}, + {"port__", "port", "port_"}, + {"procedure__", "procedure", "procedure_"}, + {"raise__", "raise", "raise_"}, + {"read__", "read", "read_"}, + {"receive__", "receive", "receive_"}, + {"record__", "record", "record_"}, + {"recursive__", "recursive", "recursive_"}, + {"refers__", "refers", "refers_"}, + {"repeat__", "repeat", "repeat_"}, + {"reply__", "reply", "reply_"}, + {"running__", "running", "running_"}, + {"runs__", "runs", "runs_"}, + {"select__", "select", "select_"}, + {"send__", "send", "send_"}, + {"sender__", "sender", "sender_"}, + {"set__", "set", "set_"}, + {"setverdict__", "setverdict", "setverdict_"}, + {"signature__", "signature", "signature_"}, + {"start__", "start", "start_"}, + {"stop__", "stop", "stop_"}, + {"subset__", "subset", "subset_"}, + {"superset__", "superset", "superset_"}, + {"system__", "system", "system_"}, + {"testcase__", "testcase", "testcase_"}, + {"timeout__", "timeout", "timeout_"}, + {"timer__", "timer", "timer_"}, + {"to__", "to", "to_"}, + {"trigger__", "trigger", "trigger_"}, + {"type__", "type", "type_"}, + {"universal__", "universal", "universal_"}, + {"unmap__", "unmap", "unmap_"}, + {"value__", "value", "value_"}, + {"present__", "present", "present_"}, + {"var__", "var", "var_"}, + {"variant__", "variant", "variant_"}, + {"with__", "with", "with_"}, + {"xor4b__", "xor4b", "xor4b_"}, + /* other names that need to be mapped in a non-uniform manner */ + /* major and minor are macros on some platforms; avoid generating + * a potentially troublesome C++ identifier */ + {"major_", "major", "major"}, + {"minor_", "minor", "minor"}, + /* internal / error */ + {"", "", ""}, + {"TTCN_internal_", "", ""}, + /* the last must be all zeros */ + {0, 0, 0} + }; // keywords + + internal_data_t::internal_data_t() + : identifier_counter(0), string_invalid(""), id_map_name(), + id_map_asn(), id_map_ttcn() + { + } + + internal_data_t::~internal_data_t() + { + for(size_t i=0; iname)) { + conflict=true; + id_data_name=id_map_name[id_data->name]; + } + else { + id_map_name.add(id_data->name, id_data); + id_data->ref_count++; + } + + if(keyword[1]==0) { + id_data->asnname=string_invalid; + } + else { + // copy the string if possible to avoid memory allocation + if (id_data->name == keyword[1]) id_data->asnname = id_data->name; + else id_data->asnname = keyword[1]; + if(id_map_asn.has_key(id_data->asnname)) { + conflict=true; + id_data_asn=id_map_asn[id_data->asnname]; + } + else { + id_map_asn.add(id_data->asnname, id_data); + id_data->ref_count++; + } + } + + if(keyword[2]==0) { + id_data->ttcnname=string_invalid; + } + else { + // copy the string if possible to avoid memory allocation + if (id_data->name == keyword[2]) id_data->ttcnname = id_data->name; + else if (id_data->asnname == keyword[2]) + id_data->ttcnname = id_data->asnname; + else id_data->ttcnname = keyword[2]; + if(id_map_ttcn.has_key(id_data->ttcnname)) { + conflict=true; + id_data_ttcn=id_map_ttcn[id_data->ttcnname]; + } + else { + id_map_ttcn.add(id_data->ttcnname, id_data); + id_data->ref_count++; + } + } + + if(conflict) { + Location loc; + loc.error + ("This pre-defined identifier: %s", + id_data->get_names().c_str()); + loc.error + ("conflicts with previous:"); + if(id_data_name) + loc.error + ("[C++:] %s", + id_data_name->get_names().c_str()); + if(id_data_asn) + loc.error + ("[ASN:] %s", + id_data_asn->get_names().c_str()); + if(id_data_ttcn) + loc.error + ("[TTCN:] %s", + id_data_ttcn->get_names().c_str()); + } // if conflict + Identifier::id_data_t::delete_this(id_data); + } + + void internal_data_t::add_keywords() + { + { + Location loc; + Error_Context cntx(&loc, "While adding keywords"); + for(size_t i=0; keywords[i][0]; i++) + add_keyword(keywords[i]); + } + /* Perhaps it were good to read a file which contains + user-defined mappings :) */ + } + + internal_data_t *internal_data_t::Instance() + { + if(!instance) { + instance=new internal_data_t(); + instance->add_keywords(); + } + return instance; + } + + void internal_data_t::increase_counter() + { + identifier_counter++; + } + + void internal_data_t::decrease_counter() + { + identifier_counter--; + if(identifier_counter==0) { + delete instance; + instance=0; + } // if last Identifier instance + } + + // ================================= + // ===== Identifier + // ================================= + + bool Identifier::is_reserved_word(const string& p_name, id_t p_id_t) + { + if (p_name.empty()) + FATAL_ERROR("Identifier::is_reserved_word(): empty name"); + internal_data_t *d = internal_data_t::Instance(); + switch (p_id_t) { + case ID_NAME: + if (d->id_map_name.has_key(p_name)) { + id_data_t *id_data_p = d->id_map_name[p_name]; + if (id_data_p->asnname == d->string_invalid && + id_data_p->ttcnname == d->string_invalid) return true; + else return false; + } else return false; + case ID_ASN: + if (p_name[0] == '&' || d->id_map_asn.has_key(p_name)) return false; + else { + string name; + id_data_t::asn_2_name(name, p_name); + if (d->id_map_name.has_key(name)) { + id_data_t *id_data_p = d->id_map_name[name]; + if (id_data_p->asnname.empty()) { + id_data_p->asnname = p_name; + d->id_map_asn.add(p_name, id_data_p); + id_data_p->ref_count++; + return false; + } else if (id_data_p->asnname == p_name) return false; + else return true; + } else return false; + } + case ID_TTCN: + if (d->id_map_ttcn.has_key(p_name)) return false; + else { + string name; + id_data_t::ttcn_2_name(name, p_name); + if (d->id_map_name.has_key(name)) { + id_data_t *id_data_p = d->id_map_name[name]; + if (id_data_p->ttcnname.empty()) { + id_data_p->ttcnname = p_name; + d->id_map_ttcn.add(p_name, id_data_p); + id_data_p->ref_count++; + return false; + } else if (id_data_p->ttcnname == p_name) return false; + else return true; + } else return false; + } + default: + FATAL_ERROR("Identifier::is_reserved_word(): invalid language"); + return false; + } + } + + string Identifier::asn_2_name(const string& p_name) + { + internal_data_t *d = internal_data_t::Instance(); + if (d->id_map_asn.has_key(p_name)) { + id_data_t *id_data_p = d->id_map_asn[p_name]; + if (id_data_p->name.empty()) { + id_data_t::asn_2_name(id_data_p->name, p_name); + d->id_map_name.add(id_data_p->name, id_data_p); + id_data_p->ref_count++; + } + return id_data_p->name; + } else { + string name; + id_data_t::asn_2_name(name, p_name); + if (d->id_map_name.has_key(name)) { + id_data_t *id_data_p = d->id_map_name[name]; + if (id_data_p->asnname.empty()) { + id_data_p->asnname = p_name; + d->id_map_asn.add(p_name, id_data_p); + id_data_p->ref_count++; + } + } + return name; + } + } + + string Identifier::name_2_asn(const string& p_name) + { + internal_data_t *d = internal_data_t::Instance(); + if (d->id_map_name.has_key(p_name)) { + id_data_t *id_data_p = d->id_map_name[p_name]; + if (id_data_p->asnname.empty()) { + id_data_t::name_2_asn(id_data_p->asnname, p_name); + d->id_map_asn.add(id_data_p->asnname, id_data_p); + id_data_p->ref_count++; + } + return id_data_p->asnname; + } else { + string asnname; + id_data_t::name_2_asn(asnname, p_name); + if (d->id_map_asn.has_key(asnname)) { + id_data_t *id_data_p = d->id_map_asn[asnname]; + if (id_data_p->name.empty()) { + id_data_p->name = p_name; + d->id_map_name.add(p_name, id_data_p); + id_data_p->ref_count++; + } + } + return asnname; + } + } + + string Identifier::ttcn_2_name(const string& p_name) + { + internal_data_t *d = internal_data_t::Instance(); + if (d->id_map_ttcn.has_key(p_name)) { + id_data_t *id_data_p = d->id_map_ttcn[p_name]; + if (id_data_p->name.empty()) { + id_data_t::ttcn_2_name(id_data_p->name, p_name); + d->id_map_name.add(id_data_p->name, id_data_p); + id_data_p->ref_count++; + } + return id_data_p->name; + } else { + string name; + id_data_t::ttcn_2_name(name, p_name); + if (d->id_map_name.has_key(name)) { + id_data_t *id_data_p = d->id_map_name[name]; + if (id_data_p->ttcnname.empty()) { + id_data_p->ttcnname = p_name; + d->id_map_ttcn.add(p_name, id_data_p); + id_data_p->ref_count++; + } + } + return name; + } + } + + string Identifier::name_2_ttcn(const string& p_name) + { + internal_data_t *d = internal_data_t::Instance(); + if (d->id_map_name.has_key(p_name)) { + id_data_t *id_data_p = d->id_map_name[p_name]; + if (id_data_p->ttcnname.empty()) { + id_data_t::name_2_ttcn(id_data_p->ttcnname, p_name); + d->id_map_ttcn.add(id_data_p->ttcnname, id_data_p); + id_data_p->ref_count++; + } + return id_data_p->ttcnname; + } else { + string ttcnname; + id_data_t::name_2_ttcn(ttcnname, p_name); + if (d->id_map_ttcn.has_key(ttcnname)) { + id_data_t *id_data_p = d->id_map_ttcn[ttcnname]; + if (id_data_p->name.empty()) { + id_data_p->name = p_name; + d->id_map_name.add(p_name, id_data_p); + id_data_p->ref_count++; + } + } + return ttcnname; + } + } + + Identifier::Identifier(id_t p_id_t, const string& p_name, bool dontreg) + : id_data(0), origin(p_id_t) + { + if (p_name.empty()) FATAL_ERROR("Identifier::Identifier(): empty name"); + internal_data_t *d=internal_data_t::Instance(); + d->increase_counter(); + switch(p_id_t) { + case ID_NAME: + if(d->id_map_name.has_key(p_name)) { + id_data=d->id_map_name[p_name]; + id_data->ref_count++; + } + else { + id_data=new id_data_t(p_name); + if(!dontreg) { + d->id_map_name.add(p_name, id_data); + id_data->ref_count++; + } + } + break; + case ID_ASN: + if(d->id_map_asn.has_key(p_name)) { + id_data=d->id_map_asn[p_name]; + id_data->ref_count++; + } + else if(p_name[0]=='&') { // special amp-identifiers (&) + string p_name2=p_name.substr(1); + string name2; + if(d->id_map_asn.has_key(p_name2)) + name2=d->id_map_asn[p_name2]->get_name(); + else + id_data_t::asn_2_name(name2, p_name2); + id_data=new id_data_t(name2); + id_data->asnname=p_name; + id_data->ttcnname=d->string_invalid; + if(!dontreg) { + d->id_map_asn.add(p_name, id_data); + id_data->ref_count++; + } + /* this id_data should NOT be added to id_map_name. */ + } // if &identifier + else { + string name; + id_data_t::asn_2_name(name, p_name); + if(!dontreg && d->id_map_name.has_key(name)) { + id_data=d->id_map_name[name]; + id_data->ref_count++; + if(id_data->asnname.empty()) { + id_data->asnname=p_name; + if(!dontreg) { + d->id_map_asn.add(p_name, id_data); + id_data->ref_count++; + } + } + else if(id_data->asnname!=p_name) { + Location loc; + loc.error + ("The ASN identifier `%s' clashes with this id: %s", + p_name.c_str(), id_data->get_names().c_str()); + } + } + else { + id_data=new id_data_t(name); + id_data->asnname=p_name; + if(!dontreg) { + d->id_map_name.add(name, id_data); + d->id_map_asn.add(p_name, id_data); + id_data->ref_count+=2; + } + } + } + break; + case ID_TTCN: + if(d->id_map_ttcn.has_key(p_name)) { + id_data=d->id_map_ttcn[p_name]; + id_data->ref_count++; + } + else { + string name; + id_data_t::ttcn_2_name(name, p_name); + if(!dontreg && d->id_map_name.has_key(name)) { + id_data=d->id_map_name[name]; + id_data->ref_count++; + if(id_data->ttcnname.empty()) { + id_data->ttcnname=p_name; + if(!dontreg) { + d->id_map_ttcn.add(p_name, id_data); + id_data->ref_count++; + } + } + else if(id_data->ttcnname!=p_name) { + Location loc; + loc.error + ("The TTCN identifier `%s' clashes with this id: %s", + p_name.c_str(), id_data->get_names().c_str()); + } + } + else { + id_data=new id_data_t(name); + id_data->ttcnname=p_name; + if(!dontreg) { + d->id_map_name.add(name, id_data); + d->id_map_ttcn.add(p_name, id_data); + id_data->ref_count+=2; + } + } + } + break; + default: + FATAL_ERROR("Identifier::Identifier()"); + } // switch p_id_t + } + + Identifier::Identifier(const Identifier& p) + : id_data(p.id_data), origin(p.origin) + { + internal_data_t::Instance()->increase_counter(); + id_data->ref_count++; + } + + Identifier::~Identifier() + { + id_data_t::delete_this(id_data); + /* I don't want to free the id_data structs here. They will be + deleted in decrease_counter() when the maps are destructed. */ + internal_data_t::Instance()->decrease_counter(); + } + + Identifier& Identifier::operator=(const Identifier& p) + { + if(&p!=this) { + id_data_t::delete_this(id_data); + id_data=p.id_data; + id_data->ref_count++; + origin=p.origin; + } + return *this; + } + + bool Identifier::operator==(const Identifier& p) const + { + return id_data->name==p.id_data->name; + } + + bool Identifier::operator<(const Identifier& p) const + { + return id_data->namename; + } + + const string& Identifier::get_name() const + { + return id_data->get_name(); + } + + const string& Identifier::get_dispname() const + { + switch(origin) { + case ID_NAME: + return id_data->get_name(); + case ID_ASN: + return id_data->get_asnname(); + case ID_TTCN: + return id_data->get_ttcnname(); + default: + FATAL_ERROR("Identifier::get_dispname()"); + return id_data->get_name(); + } + } + + const string& Identifier::get_asnname() const + { + return id_data->get_asnname(); + } + + const string& Identifier::get_ttcnname() const + { + return id_data->get_ttcnname(); + } + + bool Identifier::get_has_valid(id_t p_id_t) const + { + return id_data->get_has_valid(p_id_t); + } + + string Identifier::get_names() const + { + return id_data->get_names(); + } + + bool Identifier::isvalid_asn_modref() const + { + return id_data->isvalid_asn_modref(); + } + + bool Identifier::isvalid_asn_typeref() const + { + return id_data->isvalid_asn_typeref(); + } + + bool Identifier::isvalid_asn_valref() const + { + return id_data->isvalid_asn_valref(); + } + + bool Identifier::isvalid_asn_valsetref() const + { + return id_data->isvalid_asn_valsetref(); + } + + bool Identifier::isvalid_asn_objclassref() const + { + return id_data->isvalid_asn_objclassref(); + } + + bool Identifier::isvalid_asn_objref() const + { + return id_data->isvalid_asn_objref(); + } + + bool Identifier::isvalid_asn_objsetref() const + { + return id_data->isvalid_asn_objsetref(); + } + + bool Identifier::isvalid_asn_typefieldref() const + { + return id_data->isvalid_asn_typefieldref(); + } + + bool Identifier::isvalid_asn_valfieldref() const + { + return id_data->isvalid_asn_valfieldref(); + } + + bool Identifier::isvalid_asn_valsetfieldref() const + { + return id_data->isvalid_asn_valsetfieldref(); + } + + bool Identifier::isvalid_asn_objfieldref() const + { + return id_data->isvalid_asn_objfieldref(); + } + + bool Identifier::isvalid_asn_objsetfieldref() const + { + return id_data->isvalid_asn_objsetfieldref(); + } + + bool Identifier::isvalid_asn_word() const + { + return id_data->isvalid_asn_word(); + } + + void Identifier::dump(unsigned level) const + { + DEBUG(level, "Identifier: %s", id_data->get_names().c_str()); + } + + const Identifier underscore_zero(Identifier::ID_TTCN, string("_0")); + +} // namespace Common diff --git a/compiler2/Identifier.hh b/compiler2/Identifier.hh new file mode 100644 index 0000000..b0ee3e8 --- /dev/null +++ b/compiler2/Identifier.hh @@ -0,0 +1,118 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Common_Identifier_HH +#define _Common_Identifier_HH + +#include "string.hh" +#include "map.hh" + +namespace Common { + + /** + * \addtogroup AST + * + * @{ + */ + + /** + * This is a universal identifier class which can handle all + * reserved keywords. It contains also the name mappings. It is + * effective because of using reference counter. + */ + class Identifier { + public: + enum id_t { + ID_NAME, /**< internal name == C++ (generated) name */ + ID_ASN, /**< ASN.1 display name */ + ID_TTCN /**< TTCN-3 display name */ + }; + struct id_data_t; + /** Returns whether \a p_name is a reserved word in the language + * identified by \a p_id_t */ + static bool is_reserved_word(const string& p_name, id_t p_id_t); + /** Converts ASN.1 name \a p_name to internal (C++) name */ + static string asn_2_name(const string& p_name); + /** Converts internal (C++) name \a p_name to ASN.1 name */ + static string name_2_asn(const string& p_name); + /** Converts TTCN-3 name \a p_from to internal (C++) name */ + static string ttcn_2_name(const string& p_name); + /** Converts internal (C++) name \a p_from to TTCN-3 name */ + static string name_2_ttcn(const string& p_name); + private: + id_data_t *id_data; + id_t origin; + public: + /** Creates a new identifier with origin \a p_id_t and name \a + * p_name. If \a dontreg is true, then this new identifier will + * not be registered in the mapping tables. */ + Identifier(id_t p_id_t, const string& p_name, bool dontreg=false); + Identifier(const Identifier& p); + ~Identifier(); + + Identifier *clone() const { return new Identifier(*this); } + Identifier& operator=(const Identifier& p); + bool operator==(const Identifier& p) const; + inline bool operator!=(const Identifier& p) const + { return !(*this == p); } + bool operator<(const Identifier& p) const; + + /** Gets the origin. */ + id_t get_origin() const { return origin; } + /** Gets the internal (and C++) name. */ + const string& get_name() const; + /** Gets the display name according to its origin. */ + const string& get_dispname() const; + /** Gets the ASN display name. */ + const string& get_asnname() const; + /** Gets the TTCN display name. */ + const string& get_ttcnname() const; + /** Returns false if this identifier does not have a valid name + * for the requested purpose. */ + bool get_has_valid(id_t p_id_t) const; + /** Gets each valid/set name. */ + string get_names() const; + + /** True if it is a valid ASN modulereference. */ + bool isvalid_asn_modref() const; + /** True if it is a valid ASN typereference. */ + bool isvalid_asn_typeref() const; + /** True if it is a valid ASN valuereference. */ + bool isvalid_asn_valref() const; + /** True if it is a valid ASN valuesetreference. */ + bool isvalid_asn_valsetref() const; + /** True if it is a valid ASN objectclassreference. */ + bool isvalid_asn_objclassref() const; + /** True if it is a valid ASN objectreference. */ + bool isvalid_asn_objref() const; + /** True if it is a valid ASN objectsetreference. */ + bool isvalid_asn_objsetref() const; + /** True if it is a valid ASN typefieldreference. */ + bool isvalid_asn_typefieldref() const; + /** True if it is a valid ASN valuefieldreference. */ + bool isvalid_asn_valfieldref() const; + /** True if it is a valid ASN valuesetfieldreference. */ + bool isvalid_asn_valsetfieldref() const; + /** True if it is a valid ASN objectfieldreference. */ + bool isvalid_asn_objfieldref() const; + /** True if it is a valid ASN objectsetfieldreference. */ + bool isvalid_asn_objsetfieldref() const; + /** True if it is a valid ASN "word". */ + bool isvalid_asn_word() const; + + void dump(unsigned level) const; + }; + + /// Identifier to represent the contained type of a record-of + /// as a pseudo-component when checking attribute qualifiers. + extern const Identifier underscore_zero; + + /** @} end of AST group */ + +} // namespace Common + +#endif // _Common_Identifier_HH diff --git a/compiler2/Int.cc b/compiler2/Int.cc new file mode 100644 index 0000000..3c1bee7 --- /dev/null +++ b/compiler2/Int.cc @@ -0,0 +1,547 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "../common/dbgnew.hh" +#include "Int.hh" +#include "string.hh" +#include "error.h" +#include "Setting.hh" + +#include + +#include +#include +#include +#include + +// We cannot check without using a "./configure" script or such if we have +// llabs() or not. Define our own function instead. +inline long long ll_abs(long long x) { return ((x >= 0) ? (x) : (-x)); } + +namespace Common { + +string Int2string(const Int& i) +{ + char *s = NULL; + s = mprintf("%lld", i); + string str(s); + Free(s); + return str; +} + +Int string2Int(const char *s, const Location& loc) +{ + errno = 0; + Int i = strtoll(s, NULL, 10); + switch (errno) { + case ERANGE: { + if (loc.get_filename() != NULL) { + loc.error("Overflow when converting `%s' to integer value: %s", s, + strerror(errno)); + } else { + FATAL_ERROR("Overflow when converting `%s' to integer value: %s", s, + strerror(errno)); + } + break; } + case 0: + break; + default: + FATAL_ERROR("Unexpected error when converting `%s' to integer: %s", s, + strerror(errno)); + } + return i; +} + +int_val_t::int_val_t() : native_flag(true) +{ + val.openssl = NULL; +} + +int_val_t::int_val_t(const int_val_t& v) +{ + native_flag = v.is_native(); + if (native_flag) val.native = v.get_val(); + else val.openssl = BN_dup(v.get_val_openssl()); +} + +int_val_t::int_val_t(const char *s, const Location& loc) +{ + BIGNUM *n = NULL; + if (!BN_dec2bn(&n, *s == '+' ? s + 1 : s)) + loc.error("Unexpected error when converting `%s' to integer", s); + if (BN_num_bits(n) > (int)sizeof(long long) * 8 - 1) { + native_flag = false; + val.openssl = n; + } else { + native_flag = true; + val.native = string2Int(s, loc); + BN_free(n); + } +} + +int_val_t::~int_val_t() +{ + if (!native_flag) BN_free(val.openssl); +} + +string int_val_t::t_str() const +{ + char *tmp = NULL; + if (native_flag) { + tmp = mprintf("%lld", val.native); + string s(tmp); + Free(tmp); + return s; + } else { + if (!(tmp = BN_bn2dec(val.openssl))) + FATAL_ERROR("int_val_t::t_str()"); + string s(tmp); + OPENSSL_free(tmp); + return s; + } +} + +BIGNUM *int_val_t::to_openssl() const +{ + BIGNUM *big = NULL; + if (native_flag) { + string str = Int2string(val.native); + if (!BN_dec2bn(&big, str.c_str())) FATAL_ERROR("int_val_t::to_openssl()"); + } else { + big = BN_dup(val.openssl); + if (!big) FATAL_ERROR("int_val_t::to_openssl()"); + } + return big; +} + +bool int_val_t::operator==(Int right) const +{ + if (!native_flag) return false; + return val.native == right; +} + +bool int_val_t::operator==(const int_val_t& v) const +{ + if (native_flag != v.is_native()) return false; + if (native_flag) return val.native == v.get_val(); + return !BN_cmp(val.openssl, v.get_val_openssl()); +} + +bool int_val_t::operator<(const int_val_t& v) const +{ + if (native_flag) { + if (v.is_native()) { + return val.native < v.get_val(); + } else { + BIGNUM *this_big = to_openssl(); + if (!this_big) FATAL_ERROR("int_val_t::operator<(int_val_t& v)"); + int this_equ = BN_cmp(this_big, v.get_val_openssl()); + BN_free(this_big); + return this_equ == -1; + } + } else { + if (v.is_native()) { + BIGNUM *v_big = v.to_openssl(); + if (!v_big) FATAL_ERROR("int_val_t::operator<(int_val_t& v)"); + int v_equ = BN_cmp(val.openssl, v_big); + BN_free(v_big); + return v_equ == -1; + } else { + return BN_cmp(val.openssl, v.val.openssl) == -1; + } + } +} + +int_val_t int_val_t::operator-() const +{ + if (native_flag) { + if (val.native == LLONG_MIN) { + BIGNUM *result = int_val_t(LLONG_MIN).to_openssl(); + BN_set_negative(result, 0); + return int_val_t(result); + } else { + return int_val_t(-val.native); + } + } else { + BIGNUM *llong_max_plus_one = int_val_t(LLONG_MIN).to_openssl(); + BN_set_negative(llong_max_plus_one, 0); + int cmp = BN_cmp(val.openssl, llong_max_plus_one); + BN_free(llong_max_plus_one); + if (cmp == 0) { + return int_val_t(LLONG_MIN); + } else { + BIGNUM *result = BN_dup(val.openssl); + BN_set_negative(result, !BN_is_negative(result)); + return int_val_t(result); + } + } +} + +int_val_t int_val_t::operator+(const int_val_t& right) const +{ + // a + b = a add b + // a + -b = a sub b + // -a + b = b sub a + // -a + -b = -(a add b) + // Use only inline functions and BN_* directly. Call out for operator- in + // the beginning. + bool a_neg = is_negative(); + bool b_neg = right.is_negative(); + bool r_neg = a_neg && b_neg; + if (!a_neg && b_neg) return operator-(-right); + if (a_neg && !b_neg) return right.operator-(-(*this)); + if (native_flag) { + long long result_; + if (right.is_native()) { + unsigned long long result = val.native + right.get_val(); + result_ = val.native + right.get_val(); + if (static_cast(result) != result_ || + (!r_neg && result_ < 0) || (r_neg && result_ > 0)) { + // We can safely assume that the sum of two non-negative long long + // values fit in an unsigned long long. limits.h says: + // # ifndef ULLONG_MAX + // # define ULLONG_MAX (LLONG_MAX * 2ULL + 1) + // # endif + // This is the most complicated case. We cannot be sure that + // sizeof(BN_ULONG) == sizeof(long long). First convert the long long + // to string and feed BN_dec2bn. + BIGNUM *left_ = to_openssl(); + BIGNUM *right_ = right.to_openssl(); + BN_add(left_, left_, right_); + BN_free(right_); + return int_val_t(left_); + } else { + return int_val_t(result_); + } + } else { + // long long (>= 0) + BIGNUM == BIGNUM. + BIGNUM *result = BN_new(); + BIGNUM *left_ = to_openssl(); + BN_add(result, left_, right.get_val_openssl()); + return int_val_t(result); + } + } else { + // BIGNUM + long long (>= 0) == BIGNUM. + BIGNUM *result = BN_new(); + BIGNUM *right_; + right_ = right.is_native() ? right.to_openssl() : right.get_val_openssl(); + BN_add(result, val.openssl, right_); + if (right.is_native()) + BN_free(right_); + return int_val_t(result); + } +} + +int_val_t int_val_t::operator-(const int_val_t& right) const +{ + // a - b = a sub b + // -a - b = -(a add b) + // a - -b = a add b + // -a - -b = -a add b = b sub a + bool a_neg = is_negative(); + bool b_neg = right.is_negative(); + if (!a_neg && b_neg) return operator+(-right); + if (a_neg && !b_neg) return -right.operator+(-(*this)); + if (native_flag) { + if (right.is_native()) { + // Since both operands are non-negative the most negative result of a + // subtraction can be -LLONG_MAX and according to limits.h: + // # ifndef LLONG_MIN + // # define LLONG_MIN (-LLONG_MAX-1) + // # endif + return int_val_t(val.native - right.get_val()); + } else { + BIGNUM *left_bn = to_openssl(); + BN_sub(left_bn, left_bn, right.get_val_openssl()); + // The result can be small enough to fit in long long. The same is true + // for division. Back conversion is a really costly operation using + // strings all the time. TODO Improve it. + if (BN_num_bits(left_bn) <= (int)sizeof(long long) * 8 - 1) { + char *result_str = BN_bn2dec(left_bn); + Int result_ll = string2Int(result_str, Location()); + OPENSSL_free(result_str); + BN_free(left_bn); + return int_val_t(result_ll); + } else { + return int_val_t(left_bn); + } + } + } else { + BIGNUM *result = BN_new(); + BIGNUM *right_bn; + right_bn = right.is_native() ? right.to_openssl() : + right.get_val_openssl(); + BN_sub(result, val.openssl, right_bn); + if (right.is_native()) BN_free(right_bn); + if (BN_num_bits(result) <= (int)sizeof(long long) * 8 - 1) { + char *result_str = BN_bn2dec(result); + Int result_ll = string2Int(result_str, Location()); + OPENSSL_free(result_str); + return int_val_t(result_ll); + } else { + return int_val_t(result); + } + } +} + +int_val_t int_val_t::operator*(const int_val_t& right) const +{ + if ((native_flag && val.native == 0LL) || + (right.native_flag && right.val.native == 0LL)) + return int_val_t(0LL); + if (native_flag) { + if (right.native_flag) { + // 2^15 is used as a simple heuristic. + // TODO: Improve. + if (ll_abs(val.native) < 32768LL && ll_abs(right.val.native) < 32768LL) { + return int_val_t(val.native * right.val.native); + } else { + BIGNUM *left_bn = to_openssl(); + BIGNUM *right_bn = right.to_openssl(); + BN_CTX *ctx = BN_CTX_new(); + BN_CTX_init(ctx); + BN_mul(left_bn, left_bn, right_bn, ctx); + BN_CTX_free(ctx); + BN_free(right_bn); + if (BN_num_bits(left_bn) < (int)sizeof(long long) * 8) { + BN_free(left_bn); + return int_val_t(val.native * right.val.native); + } else { + return int_val_t(left_bn); + } + } + } else { + BIGNUM *this_bn = to_openssl(); + BN_CTX *ctx = BN_CTX_new(); + BN_CTX_init(ctx); + BN_mul(this_bn, this_bn, right.get_val_openssl(), ctx); + BN_CTX_free(ctx); + return int_val_t(this_bn); + } + } else { + BIGNUM *result = BN_new(); + BIGNUM *right_bn; + BN_CTX *ctx = BN_CTX_new(); + BN_CTX_init(ctx); + right_bn = right.native_flag ? right.to_openssl() + : right.get_val_openssl(); + BN_mul(result, val.openssl, right_bn, ctx); + BN_CTX_free(ctx); + if (right.native_flag) BN_free(right_bn); + return int_val_t(result); + } +} + +int_val_t int_val_t::operator/(const int_val_t& right) const +{ + if (native_flag && val.native == 0LL) + return int_val_t(0LL); + if (right.is_native() && right.get_val() == 0LL) + FATAL_ERROR("Division by zero after semantic check"); + if (native_flag) { + if (right.native_flag) { + return int_val_t(val.native / right.get_val()); + } else { + BIGNUM *left_bn = to_openssl(); + BN_CTX *ctx = BN_CTX_new(); + BN_CTX_init(ctx); + BN_div(left_bn, NULL, left_bn, right.get_val_openssl(), ctx); + BN_CTX_free(ctx); + if (BN_num_bits(left_bn) <= (int)sizeof(long long) * 8 - 1) { + char *result_str = BN_bn2dec(left_bn); + Int result_ll = string2Int(result_str, Location()); + OPENSSL_free(result_str); + BN_free(left_bn); + return int_val_t(result_ll); + } else { + return int_val_t(left_bn); + } + } + } else { + BIGNUM *result = BN_new(); + BIGNUM *right_bn; + BN_CTX *ctx = BN_CTX_new(); + BN_CTX_init(ctx); + right_bn = right.is_native() ? right.to_openssl() : + right.get_val_openssl(); + BN_div(result, NULL, val.openssl, right_bn, ctx); + BN_CTX_free(ctx); + if (BN_num_bits(result) <= (int)sizeof(long long) * 8 - 1) { + char *result_str = BN_bn2dec(result); + Int result_ll = string2Int(result_str, Location()); + OPENSSL_free(result_str); + return int_val_t(result_ll); + } else { + if (right.is_native()) + BN_free(right_bn); + return int_val_t(result); + } + } +} + +int_val_t int_val_t::operator&(Int right) const +{ + // TODO Right can be int_val_t. Now it works only if right fits in + // BN_ULONG. If it's not true right must be converted to BIGNUM and the + // bits should be set with BN_is_bit_set/BN_set_bit. + BN_ULONG right_bn_ulong = (BN_ULONG)right; + if (right != (long long)right_bn_ulong) + FATAL_ERROR("Bitmask is too big"); + if (native_flag) { + return int_val_t(val.native & right); + } else { + BIGNUM *tmp = BN_dup(val.openssl); + BN_mask_bits(tmp, sizeof(BN_ULONG) * 8); + BN_ULONG word = BN_get_word(tmp); + BN_free(tmp); + return int_val_t(word & right_bn_ulong); + } +} + +int_val_t int_val_t::operator>>(Int right) const +{ + if (native_flag) { + // Shifting right (or left) with a number greater or equal to the bits of + // the type of the left operand has an undefined behaviour. + // http://bytes.com/groups/c/495137-right-shift-weird-result-why + Int shifted_value = right >= static_cast(sizeof(Int) * 8) ? 0 : + val.native >> right; + return int_val_t(shifted_value); + } else { + BIGNUM *result = BN_new(); + BN_rshift(result, val.openssl, right); + if (BN_num_bits(result) < (int)sizeof(long long) * 8 - 1) { + char *result_str = BN_bn2dec(result); + Int result_ll = string2Int(result_str, Location()); + OPENSSL_free(result_str); + BN_free(result); + return int_val_t(result_ll); + } else { + return int_val_t(result); + } + } +} + +const Int& int_val_t::get_val() const +{ + if (!native_flag) FATAL_ERROR("Invalid conversion of a large integer value"); + return val.native; +} + +BIGNUM *int_val_t::get_val_openssl() const +{ + if (native_flag) FATAL_ERROR("Invalid conversion of a large integer value"); + return val.openssl; +} + +Real int_val_t::to_real() const +{ + if (native_flag) { + return (double)val.native; + } else { + char *result_str = BN_bn2dec(val.openssl); + Real result = 0.0; + // Use fixed-point notation. The mantissa is usually at most 52-bits. + // Bigger integer values will be rounded. + if (sscanf(result_str, "%lf", &result) != 1) + FATAL_ERROR("Conversion of integer value `%s' to float failed", + result_str); // No deallocation, it'll crash anyway... + OPENSSL_free(result_str); + return result; + } +} + +int_val_t& int_val_t::operator=(const int_val_t& right) +{ + if (!native_flag) BN_free(val.openssl); + native_flag = right.native_flag; + if (native_flag) val.native = right.get_val(); + else val.openssl = BN_dup(right.get_val_openssl()); + return *this; +} + +int_val_t& int_val_t::operator<<=(Int right) +{ + // It makes no sense to support negative operands. GCC returns constant "0" + // with "warning: left shift count is negative" for these shifts. + // BN_set_word is not enough since sizeof(BN_ULONG) != sizeof(long long). + // In TTCN-3 <<= right means >>= -right. + if (right < 0) FATAL_ERROR("The second operand of bitwise shift operators " + "cannot be negative"); + if (right == 0) return *this; + if (native_flag) { + BIGNUM *result = BN_new(); + BN_dec2bn(&result, Int2string(val.native).c_str()); + BN_lshift(result, result, right); + if (BN_num_bits(result) > (int)sizeof(long long) * 8 - 1) { + val.openssl = result; + native_flag = false; + } else { + val.native <<= right; + BN_free(result); + } + } else { + BN_lshift(val.openssl, val.openssl, right); + } + return *this; +} + +int_val_t& int_val_t::operator>>=(Int right) +{ + if (right < 0) FATAL_ERROR("The second operand of bitwise shift operators " + "cannot be negative"); + if (right == 0) return *this; + if (native_flag) { + val.native >>= right; + } else { + BN_rshift(val.openssl, val.openssl, right); + if (BN_num_bits(val.openssl) <= (int)sizeof(long long) * 8 - 1) { + char *result_str = BN_bn2dec(val.openssl); + Int result_ll = string2Int(result_str, Location()); + OPENSSL_free(result_str); + native_flag = true; + BN_free(val.openssl); + val.native = result_ll; + } + } + return *this; +} + +int_val_t& int_val_t::operator+=(Int right) +{ + // Unfortunately we have to check the sign of the "right" operand and + // perform addition or subtraction accordingly. + if (right == 0) return *this; + bool neg = right < 0; + if (native_flag) { + BIGNUM *result = BN_new(); + BN_set_word(result, (BN_ULONG)val.native); + if (neg) BN_sub_word(result, (BN_ULONG)right); + else BN_add_word(result, (BN_ULONG)right); + if (BN_num_bits(result) > (int)sizeof(long long) * 8 - 1) { + val.openssl = result; + native_flag = false; + } else { + val.native += right; + BN_free(result); + } + } else { + if (neg) BN_sub_word(val.openssl, (BN_ULONG)right); + else BN_add_word(val.openssl, (BN_ULONG)right); + if (BN_num_bits(val.openssl) <= (int)sizeof(long long) * 8 - 1) { + // TODO BN_ULONG != long long. + BN_ULONG tmp = BN_get_word(val.openssl); + if (BN_is_negative(val.openssl)) tmp *= -1; + BN_free(val.openssl); + val.native = tmp; + native_flag = true; + } + } + return *this; +} + +} // Common diff --git a/compiler2/Int.hh b/compiler2/Int.hh new file mode 100644 index 0000000..9f25995 --- /dev/null +++ b/compiler2/Int.hh @@ -0,0 +1,104 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef Int_HH_ +#define Int_HH_ + +#include "Real.hh" +#include "string.hh" + +#include + +#include + +// Better together. +#if !defined(LLONG_MAX) || !defined(LLONG_MIN) +#define LLONG_MAX 9223372036854775807LL +#define LLONG_MIN (-LLONG_MAX-1) +#else +#if __GNUC__ < 3 +#undef LLONG_MIN +#define LLONG_MIN ((long long)(-LLONG_MAX-1)) +#endif +#endif + +namespace Common { + +class Location; + +typedef long long Int; +typedef int RInt; + +// Converts the Common::Int value to string. +string Int2string(const Int& i); + +// Converts the string value to Common::Int. Throws Error_Int if conversion +// is not possible (e.g. value is out of range, or s is not a valid integer +// representation). +Int string2Int(const char *s, const Location& loc); +inline Int string2Int(const string& s, const Location& loc) + { return string2Int(s.c_str(), loc); } + +class int_val_t +{ +private: + bool native_flag; + union { + Int native; + BIGNUM *openssl; + } val; + // Hide all BIGNUM related stuff here. + BIGNUM *to_openssl() const; + BIGNUM *get_val_openssl() const; + explicit int_val_t(BIGNUM *v) : native_flag(false), val() { val.openssl = v; } + +public: + int_val_t(); + int_val_t(const int_val_t& v); + int_val_t(const char *s, const Location& loc); + explicit int_val_t(Int v) : native_flag(true), val() { val.native = v; } + ~int_val_t(); + string t_str() const; + int_val_t operator-() const; + int_val_t operator>>(Int right) const; + int_val_t operator+(const int_val_t& right) const; + int_val_t operator-(const int_val_t& right) const; + inline int_val_t operator+(Int right) const { return operator+(int_val_t(right)); } + inline int_val_t operator-(Int right) const { return operator-(int_val_t(right)); } + int_val_t operator*(const int_val_t& right) const; + int_val_t operator/(const int_val_t& right) const; + int_val_t operator&(Int right) const; + bool operator<(const int_val_t& right) const; + inline bool operator<(Int right) const { return *this < int_val_t(right); } + inline bool operator>(Int right) const { return *this > int_val_t(right); } + inline bool operator>(const int_val_t& right) const { return *this != right && !(*this < right); } + inline bool operator<=(Int right) const { return *this == right || *this < right; } + inline bool operator>=(Int right) const { return *this == right || *this > right; } + inline bool operator<=(const int_val_t& right) const { return *this == right || *this < right; } + inline bool operator>=(const int_val_t& right) const { return *this == right || *this > right; } + inline bool operator!=(Int right) const { return !(*this == right); } + inline bool operator!=(const int_val_t& right) const { return !(*this == right); } + bool operator==(const int_val_t& right) const; + bool operator==(Int right) const; + int_val_t& operator=(const int_val_t& right); + int_val_t& operator+=(Int right); + int_val_t& operator<<=(Int right); + int_val_t& operator>>=(Int right); + const Int& get_val() const; + Real to_real() const; + inline bool is_native_fit() const + // It seems to give correct results (-2147483648..2147483647). + { return native_flag && val.native == static_cast(val.native); } + inline bool is_native() const { return native_flag; } + inline bool is_openssl() const { return !native_flag; } + inline bool is_negative() const + { return native_flag ? val.native < 0 : BN_is_negative(val.openssl); } +}; + +} // Common + +#endif // Int_HH_ diff --git a/compiler2/Makefile b/compiler2/Makefile new file mode 100644 index 0000000..e5a1833 --- /dev/null +++ b/compiler2/Makefile @@ -0,0 +1,192 @@ +############################################################################### +# 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 +############################################################################### +# Makefile for the integrated (TTCN-3 and ASN.1) compiler +# and the makefile generator + +TOP := .. +include $(TOP)/Makefile.cfg + +ifeq ($(USAGE_STATS), yes) +SOLARIS_LIBS := -lresolv -lsocket -lnsl +SOLARIS8_LIBS := -lresolv -lsocket -lnsl +LINUX_LIBS := -lpthread -lrt +endif + +ifeq ($(findstring g++, $(CXX)), g++) + CXXFLAGS += -fno-exceptions +endif + +ifdef REGEX_DIR + CPPFLAGS += -I$(REGEX_DIR)/include +endif + +ifdef OPENSSL_DIR +ifneq ($(OPENSSL_DIR), default) + CPPFLAGS += -I$(OPENSSL_DIR)/include + LDFLAGS += -L$(OPENSSL_DIR)/lib +endif +endif + +ifdef XMLDIR +ifeq ($(XMLDIR), default) + XMLDIR := /usr + # do not add -L/usr/lib to LDFLAGS, it's redundant +else + LDFLAGS += -L$(XMLDIR)/lib +endif + + CPPFLAGS += -I$(XMLDIR)/include/libxml2 +endif + +ifdef SRCDIR + CPPFLAGS += -Iasn1 +endif + +# Too many "comparison between signed and unsigned" +CCFLAGS += -Wno-sign-compare + +ifndef MINGW +TARGETS := compiler$(EXESUFFIX) ttcn3_makefilegen$(EXESUFFIX) tcov2lcov$(EXESUFFIX) +MANPAGES := compiler.1 ttcn3_makefilegen.1 +else +TARGETS := compiler$(EXESUFFIX) +MANPAGES := compiler.1 +MAYBE_PDFS := $(MANPAGES:.1=.pdf) +endif + +PDFS := $(MANPAGES:.1=.pdf) + +COMPILER_SOURCES := encdec.c enum.c functionref.c record.c record_of.c union.c \ +PredefFunc.cc AST.cc Code.cc Constraint.cc CompilerError.cc \ +CompField.cc CompType.cc EnumItem.cc Identifier.cc Int.cc \ +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 + +TCOV2LCOV_SOURCES := tcov2lcov.cc + +SOURCES := $(COMPILER_SOURCES) $(MFGEN_SOURCES) $(TCOV2LCOV_SOURCES) + +# All sources are static in this directory +STATIC_SOURCES := $(SOURCES) + +COMPILER_OBJECTS := $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(COMPILER_SOURCES))) + +MFGEN_OBJECTS := $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(MFGEN_SOURCES))) + +TCOV2LCOV_OBJECTS := $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(TCOV2LCOV_SOURCES))) + +OBJECTS := $(COMPILER_OBJECTS) $(MFGEN_OBJECTS) $(TCOV2LCOV_OBJECTS) + +# Used by both the compiler and makefilegen +COMMON_OBJECTS := $(addprefix ../common/, memory.o path.o userinfo.o JSON_Tokenizer.o) + +TCOV2LCOV_COMMON_OBJECTS := ../common/memory.o + +ifeq ($(LICENSING), yes) + COMMON_OBJECTS += ../common/license.o + TCOV2LCOV_COMMON_OBJECTS += ../common/license.o +endif + +ifdef REGEX_DIR + COMMON_OBJECTS += $(REGEX_DIR)/lib/regex.o +endif + +COMPILER_COMMON_OBJECTS := $(COMMON_OBJECTS) \ +$(addprefix ../common/, new.o pattern_la.o pattern_p.o pattern_uni.o Quadruple.o ModuleVersion.o) + +ifeq ($(USAGE_STATS), yes) +COMPILER_COMMON_OBJECTS += ../common/usage_stats.o +endif + +MFGEN_COMMON_OBJECTS := $(COMMON_OBJECTS) ../common/new.o + +DEPFILES := $(patsubst %.cc,%.d,$(patsubst %.c,%.d,$(COMPILER_SOURCES) \ +$(MFGEN_SOURCES))) + +SUBDIRS := asn1 ttcn3 + +.PHONY: asn1_dir ttcn3_dir + +all run: $(TARGETS) + +asn1/libasn1_compiler.a: asn1_dir ; + +ttcn3/libttcn3_compiler.a: ttcn3_dir ; + +asn1_dir: + $(MAKE) -C asn1 + +ttcn3_dir: + $(MAKE) -C ttcn3 + +pdf: $(PDFS) + +install: $(TARGETS) $(MAYBE_PDFS) +ifeq ($(DEBUG), no) + $(STRIP) $(TARGETS) +endif + mkdir -p $(BINDIR) + cp $(TARGETS) $(BINDIR) +ifdef MINGW + mkdir -p $(MANDIR) + cp $(PDFS) $(MANDIR) +else + cp tcov.xsd tcov.xsl $(INCDIR) + cp titanver $(BINDIR) + chmod a+x $(BINDIR)/titanver + $(RM) $(BINDIR)/ttcn3_compiler$(EXESUFFIX) \ + $(BINDIR)/asn1_compiler$(EXESUFFIX) $(BINDIR)/makefilegen$(EXESUFFIX) + ln -s compiler$(EXESUFFIX) $(BINDIR)/ttcn3_compiler$(EXESUFFIX) + ln -s compiler$(EXESUFFIX) $(BINDIR)/asn1_compiler$(EXESUFFIX) + ln -s ttcn3_makefilegen$(EXESUFFIX) $(BINDIR)/makefilegen$(EXESUFFIX) + mkdir -p $(MANDIR)/man1 + cp $(MANPAGES) $(MANDIR)/man1 + $(RM) $(MANDIR)/man1/ttcn3_compiler.1 $(MANDIR)/man1/asn1_compiler.1 \ + $(MANDIR)/man1/makefilegen.1 + ln -s compiler.1 $(MANDIR)/man1/ttcn3_compiler.1 + ln -s compiler.1 $(MANDIR)/man1/asn1_compiler.1 + ln -s ttcn3_makefilegen.1 $(MANDIR)/man1/makefilegen.1 +endif + +# The compiler always links to OpenSSL (even without LICENSING) +# because it uses bignums. +compiler$(EXESUFFIX): asn1/libasn1_compiler.a ttcn3/libttcn3_compiler.a \ +$(COMPILER_OBJECTS) $(COMPILER_COMMON_OBJECTS) + $(CXX) $(LDFLAGS) -o $@ $(COMPILER_OBJECTS) $(COMPILER_COMMON_OBJECTS) \ + asn1/libasn1_compiler.a ttcn3/libttcn3_compiler.a \ + -lcrypto $(RSLICLIB) $(MINGW_LIBS) $($(PLATFORM)_LIBS) + +ttcn3_makefilegen$(EXESUFFIX): $(MFGEN_OBJECTS) $(MFGEN_COMMON_OBJECTS) \ +ttcn3/ttcn3_preparser.lex.o asn1/asn1_preparser.lex.o + $(CXX) $(LDFLAGS) -o $@ $^ -lxml2 $(LICENSE_LIBS) $(MINGW_LIBS) + +tcov2lcov$(EXESUFFIX): $(TCOV2LCOV_OBJECTS) $(TCOV2LCOV_COMMON_OBJECTS) + $(CXX) $(LDFLAGS) -o $@ $^ -lxml2 $(LICENSE_LIBS) $(MINGW_LIBS) + +include ../Makefile.genrules + +# Target-specific variable alteration +# Target-specific += causes make 3.79.1 to crash, hence this old style +makefile.o: CPPFLAGS := $(CPPFLAGS) -DCXX='"$(CXX)"' + +# Pre-seed dependencies. Value.cc and Valuestuff.cc include asn1/asn1p.tab.hh +# However, if asn1/asn1p.y is modified, these files are not rebuilt because +# the Value.d contains a dependency on asn1/asn1p.tab.hh, which is not yet +# regenerated. +# +# 1. asn1/asn1p.y is modified +# 2. "make" checks dependencies of Value.o; decides nothing to do +# 3. "make -C asn1" rebuilds asn1p.y, updating asn1p.tab.hh +# 4. Value.o is now out of date +# 5. "make" issued a second time decides that Value.o is out of date +Value.d Value.o : asn1/asn1p.tab.hh +Valuestuff.d Valuestuff.o : asn1/asn1p.tab.hh +Constraint.d Constraint.o : asn1/asn1p.tab.hh diff --git a/compiler2/PredefFunc.cc b/compiler2/PredefFunc.cc new file mode 100644 index 0000000..9b0f083 --- /dev/null +++ b/compiler2/PredefFunc.cc @@ -0,0 +1,1103 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "PredefFunc.hh" +#include "error.h" +#include "Int.hh" +#include "Real.hh" +#include "Setting.hh" +#include "string.hh" +#include "ustring.hh" +#include "CompilerError.hh" +#include +#include +#include +#include +#include "../common/memory.h" +#include "../common/pattern.hh" +#include + +// used by regex +#define ERRMSG_BUFSIZE 512 + +namespace Common { + + static const char utf32be[] = {'0','0','0','0','F','E','F','F',0}; + static const char utf32le[] = {'F','F','F','E','0','0','0','0',0}; + static const char utf16be[] = {'F','E','F','F',0}; + static const char utf16le[] = {'F','F','F','E',0}; + static const char utf8[] = {'E','F','B','B','B','F',0}; + + static inline unsigned char get_bit_value(char c, unsigned char bit_value) + { + switch (c) { + case '0': + return 0; + case '1': + return bit_value; + default: + FATAL_ERROR("Invalid binary digit (%c) in bitstring value", c); + return 0; + } + } + + char toupper (const char c) + { + if (('A' <= c && 'F' >= c) || + ('0' <= c && '9' >= c)) return c; + switch (c) + { + case 'a' : return 'A'; + case 'b' : return 'B'; + case 'c' : return 'C'; + case 'd' : return 'D'; + case 'e' : return 'E'; + case 'f' : return 'F'; + default: + FATAL_ERROR("%c cannot be converted to hex character", c); + break; + } + } + + char hexdigit_to_char(unsigned char hexdigit) + { + if (hexdigit < 10) return '0' + hexdigit; + else if (hexdigit < 16) return 'A' + hexdigit - 10; + else { + FATAL_ERROR("hexdigit_to_char(): invalid argument: %d", hexdigit); + return '\0'; // to avoid warning + } + } + + unsigned char char_to_hexdigit(char c) + { + if (c >= '0' && c <= '9') return c - '0'; + else if (c >= 'A' && c <= 'F') return c - 'A' + 10; + else if (c >= 'a' && c <= 'f') return c - 'a' + 10; + else { + FATAL_ERROR("char_to_hexdigit(): invalid argument: %c", c); + return 0; // to avoid warning + } + } + + string uchar2str(unsigned char uchar) + { + char str[2]; + str[0] = hexdigit_to_char(uchar / 16); + str[1] = hexdigit_to_char(uchar % 16); + return string(2, str); + } + + unsigned char str2uchar(const char& c1, const char& c2) + { + unsigned char uc = 0; + uc = char_to_hexdigit(c1); + uc <<= 4; + uc += char_to_hexdigit(c2); + return uc; + } + + int_val_t rem(const int_val_t& left, const int_val_t& right) + { + return (left - right * (left / right)); + } + + int_val_t mod(const int_val_t& left, const int_val_t& right) + { + int_val_t r = right < 0 ? -right : right; + if (left > 0) { + return rem(left, r); + } else { + int_val_t result = rem(left, r); + return result == 0 ? result : result + r; + } + } + + string* to_uppercase(const string& value) + { + string *s = new string(value); + for (size_t i = 0; i < s->size(); i++) { + char& c=(*s)[i]; + if (c >= 'a' && c <= 'z') c = c - 'a' + 'A'; + } + return s; + } + + string* not4b_bit(const string& bstr) + { + string *s=new string(bstr); + for(size_t i=0; isize(); i++) { + char& c=(*s)[i]; + switch(c) { + case '0': c='1'; break; + case '1': c='0'; break; + default: + FATAL_ERROR("not4b_bit(): Invalid char in bitstring."); + } // switch c + } // for i + return s; + } + + string* not4b_hex(const string& hstr) + { + string *s=new string(hstr); + for(size_t i=0; isize(); i++) { + char& c=(*s)[i]; + switch(c) { + case '0': c='F'; break; + case '1': c='E'; break; + case '2': c='D'; break; + case '3': c='C'; break; + case '4': c='B'; break; + case '5': c='A'; break; + case '6': c='9'; break; + case '7': c='8'; break; + case '8': c='7'; break; + case '9': c='6'; break; + case 'A': c='5'; break; + case 'B': c='4'; break; + case 'C': c='3'; break; + case 'D': c='2'; break; + case 'E': c='1'; break; + case 'F': c='0'; break; + case 'a': c='5'; break; + case 'b': c='4'; break; + case 'c': c='3'; break; + case 'd': c='2'; break; + case 'e': c='1'; break; + case 'f': c='0'; break; + default: + FATAL_ERROR("not4b_hex(): Invalid char in hexstring."); + } // switch c + } // for i + return s; + } + + string* and4b(const string& left, const string& right) + { + string *s=new string(left); + for(size_t i=0; isize(); i++) { + char& c=(*s)[i]; + c=hexdigit_to_char(char_to_hexdigit(c) & char_to_hexdigit(right[i])); + } // for i + return s; + } + + string* or4b(const string& left, const string& right) + { + string *s=new string(left); + for(size_t i=0; isize(); i++) { + char& c=(*s)[i]; + c=hexdigit_to_char(char_to_hexdigit(c) | char_to_hexdigit(right[i])); + } // for i + return s; + } + + string* xor4b(const string& left, const string& right) + { + string *s=new string(left); + for(size_t i=0; isize(); i++) { + char& c=(*s)[i]; + c=hexdigit_to_char(char_to_hexdigit(c) ^ char_to_hexdigit(right[i])); + } // for i + return s; + } + + string* shift_left(const string& value, const Int& count) + { + if (count > 0) { + string *s = new string; + if (count < static_cast(value.size())) *s = value.substr(count); + s->resize(value.size(), '0'); + return s; + } else if (count < 0) return shift_right(value, -count); + else return new string(value); + } + + string* shift_right(const string& value, const Int& count) + { + if (count > 0) { + string *s = new string; + if (count < static_cast(value.size())) { + s->resize(count, '0'); + *s += value.substr(0, value.size()-count); + } else s->resize(value.size(), '0'); + return s; + } else if (count < 0) return shift_left(value, -count); + else return new string(value); + } + + string* rotate_left(const string& value, const Int& p_count) + { + size_t size = value.size(); + if (size == 0) return new string(value); + else if (p_count < 0) return rotate_right(value, -p_count); + size_t count = p_count % size; + if (count == 0) return new string(value); + else return new string(value.substr(count) + value.substr(0, count)); + } + + string* rotate_right(const string& value, const Int& p_count) + { + size_t size = value.size(); + if (size == 0) return new string(value); + else if (p_count < 0) return rotate_left(value, -p_count); + size_t count = p_count % size; + if (count == 0) return new string(value); + else return new string(value.substr(size - count) + + value.substr(0, size - count)); + } + + + ustring* rotate_left(const ustring& value, const Int& p_count) + { + size_t size = value.size(); + if (size == 0) return new ustring(value); + else if (p_count < 0) return rotate_right(value, -p_count); + size_t count = p_count % size; + if (count == 0) return new ustring(value); + else return new ustring(value.substr(count) + value.substr(0, count)); + } + + ustring* rotate_right(const ustring& value, const Int& p_count) + { + size_t size = value.size(); + if (size == 0) return new ustring(value); + else if (p_count < 0) return rotate_left(value, -p_count); + size_t count = p_count % size; + if (count == 0) return new ustring(value); + else return new ustring(value.substr(size - count) + + value.substr(0, size - count)); + } + + int_val_t* bit2int(const string& bstr) + { + size_t nof_bits = bstr.size(); + // skip the leading zeros + size_t start_index = 0; + while (start_index < nof_bits && bstr[start_index] == '0') start_index++; + int_val_t *ret_val = new int_val_t((Int)0); + for (size_t i = start_index; i < nof_bits; i++) { + *ret_val <<= 1; + if (bstr[i] == '1') *ret_val += 1; + } + return ret_val; + } + + int_val_t* hex2int(const string& hstr) + { + size_t nof_digits = hstr.size(); + size_t start_index = 0; + // Skip the leading zeros. + while (start_index < nof_digits && hstr[start_index] == '0') + start_index++; + int_val_t *ret_val = new int_val_t((Int)0); + for (size_t i = start_index; i < nof_digits; i++) { + *ret_val <<= 4; + *ret_val += char_to_hexdigit(hstr[i]); + } + return ret_val; + } + + Int unichar2int(const ustring& ustr) + { + if (ustr.size() != 1) FATAL_ERROR("unichar2int(): invalid argument"); + const ustring::universal_char& uchar = ustr.u_str()[0]; + Int ret_val = (uchar.group << 24) | (uchar.plane << 16) | (uchar.row << 8) | + uchar.cell; + return ret_val; + } + + string *int2bit(const int_val_t& value, const Int& length) + { + if (length < 0) FATAL_ERROR("int2bit(): negative length"); + size_t string_length = static_cast(length); + if (static_cast(string_length) != length || + string_length > string::max_string_len) + FATAL_ERROR("int2bit(): length is too large"); + if (value < 0) FATAL_ERROR("int2bit(): negative value"); + string *bstr = new string; + bstr->resize(string_length); + int_val_t tmp_value = value; + for (size_t i = 1; i <= string_length; i++) { + (*bstr)[string_length - i] = (tmp_value & 1).get_val() ? '1' : '0'; + tmp_value >>= 1; + } + if (tmp_value != 0) + FATAL_ERROR("int2bit(): %s does not fit in %lu bits", \ + value.t_str().c_str(), (unsigned long)string_length); + return bstr; + } + + static const char hdigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + string *int2hex(const int_val_t& value, const Int& length) + { + if (length < 0) + FATAL_ERROR("int2hex(): negative length"); + size_t string_length = static_cast(length); + if (static_cast(string_length) != length || + string_length > string::max_string_len) + FATAL_ERROR("int2hex(): length is too large"); + if (value < 0) FATAL_ERROR("int2hex(): negative value"); + string *hstr = new string; + hstr->resize(string_length); + int_val_t tmp_value = value; + for (size_t i = 1; i <= string_length; i++) { + (*hstr)[string_length - i] = hdigits[(tmp_value & 0x0f).get_val()]; + tmp_value >>= 4; + } + if (tmp_value != 0) { + FATAL_ERROR("int2hex(): %s does not fit in %lu hexadecimal digits", + value.t_str().c_str(), (unsigned long)string_length); + } + return hstr; + } + + ustring *int2unichar(const Int& value) + { + if (value < 0 || value > 2147483647) + FATAL_ERROR("int2unichar(): invalid argument"); + unsigned char group = (value >> 24) & 0xFF, + plane = (value >> 16) & 0xFF, + row = (value >> 8) & 0xFF, + cell = value & 0xFF; + return new ustring(group, plane, row, cell); + } + + string *oct2char(const string& ostr) + { + string *cstr = new string; + size_t ostr_size = ostr.size(); + if (ostr_size % 2) + FATAL_ERROR("oct2char(): argument has odd length: %lu", + (unsigned long) ostr_size); + size_t cstr_size = ostr_size / 2; + cstr->resize(cstr_size); + const char *ostr_ptr = ostr.c_str(); + for (size_t i = 0; i < cstr_size; i++) { + unsigned char c = 16 * char_to_hexdigit(ostr_ptr[2 * i]) + + char_to_hexdigit(ostr_ptr[2 * i + 1]); + if (c > 127) FATAL_ERROR("oct2char(): resulting charstring contains " \ + "non-ascii character: %d", c); + (*cstr)[i] = c; + } + return cstr; + } + + string *char2oct(const string& cstr) + { + string *ostr = new string; + size_t cstr_size = cstr.size(); + ostr->resize(cstr_size * 2, '0'); + const char *cstr_ptr = cstr.c_str(); + for (size_t i = 0; i < cstr_size; i++) { + unsigned char c = cstr_ptr[i]; + (*ostr)[2 * i] = hexdigit_to_char(c / 16); + (*ostr)[2 * i + 1] = hexdigit_to_char(c % 16); + } + return ostr; + } + + string *bit2hex(const string& bstr) + { + size_t size=bstr.size(); + size_t hsize=(size+3)/4; + string *hstr = new string; + string *bstr4=NULL; + if(size%4) { + bstr4=new string; + bstr4->resize(hsize*4,'0'); + bstr4->replace(4-(size%4),size,bstr); + } + hstr->resize(hsize,'0'); + string b4(4,"0000"); + for(size_t i=0;isubstr(i*4,4); + else b4=bstr.substr(i*4,4); + if(b4[0]=='1')u=8;else u=0; + if(b4[1]=='1')u+=4; + if(b4[2]=='1')u+=2; + if(b4[3]=='1')u++; + (*hstr)[i]=hdigits[u]; + } + if(bstr4!=NULL)delete bstr4; + return hstr; + } + + string *hex2oct(const string& hstr) + { + if(hstr.size()%2==0)return new string(hstr); + else { + string *ostr=new string("0"); + (*ostr)+=hstr; + return ostr; + } + } + + string *asn_hex2oct(const string& hstr) + { + string *ostr = new string(hstr); + size_t size = ostr->size(); + if (size % 2) ostr->resize(size + 1, '0'); + return ostr; + } + + string *bit2oct(const string& bstr) + { + string *s1,*s2; + s1=bit2hex(bstr); + s2=hex2oct(*s1); + delete s1; + return s2; + } + + string *asn_bit2oct(const string& bstr) + { + size_t size = bstr.size(); + string *ostr = new string; + ostr->resize(((size+7)/8)*2); + for(size_t i=0, j=0; iresize(4*size); + for(size_t i=0; ireplace(4*i, 4, "0000"); + break; + case '1': + bstr->replace(4*i, 4, "0001"); + break; + case '2': + bstr->replace(4*i, 4, "0010"); + break; + case '3': + bstr->replace(4*i, 4, "0011"); + break; + case '4': + bstr->replace(4*i, 4, "0100"); + break; + case '5': + bstr->replace(4*i, 4, "0101"); + break; + case '6': + bstr->replace(4*i, 4, "0110"); + break; + case '7': + bstr->replace(4*i, 4, "0111"); + break; + case '8': + bstr->replace(4*i, 4, "1000"); + break; + case '9': + bstr->replace(4*i, 4, "1001"); + break; + case 'A': + case 'a': + bstr->replace(4*i, 4, "1010"); + break; + case 'B': + case 'b': + bstr->replace(4*i, 4, "1011"); + break; + case 'C': + case 'c': + bstr->replace(4*i, 4, "1100"); + break; + case 'D': + case 'd': + bstr->replace(4*i, 4, "1101"); + break; + case 'E': + case 'e': + bstr->replace(4*i, 4, "1110"); + break; + case 'F': + case 'f': + bstr->replace(4*i, 4, "1111"); + break; + default: + FATAL_ERROR("Common::hex2bit(): invalid hexadecimal " + "digit in hexstring value"); + } + } + return bstr; + } + + int_val_t* float2int(const Real& value, const Location& loc) + { + // We shouldn't mimic generality with `Int'. + if (value >= (Real)LLONG_MIN && value <= (Real)LLONG_MAX) + return new int_val_t((Int)value); + char buf[512] = ""; + snprintf(buf, 511, "%f", value); + char *dot = strchr(buf, '.'); + if (!dot) FATAL_ERROR("Conversion of float value `%f' to integer failed", value); + else memset(dot, 0, sizeof(buf) - (dot - buf)); + return new int_val_t(buf, loc); + } + +/* TTCN-3 float values that have absolute value smaller than this are + displayed in exponential notation. Same as in core/Float.hh */ +#ifndef MIN_DECIMAL_FLOAT +#define MIN_DECIMAL_FLOAT 1.0E-4 +#endif +/* TTCN-3 float values that have absolute value larger or equal than + this are displayed in exponential notation. Same as in + core/Float.hh */ +#ifndef MAX_DECIMAL_FLOAT +#define MAX_DECIMAL_FLOAT 1.0E+10 +#endif + + string *float2str(const Real& value) + { + char str_buf[64]; + if ( (value > -MAX_DECIMAL_FLOAT && value <= -MIN_DECIMAL_FLOAT) + || (value >= MIN_DECIMAL_FLOAT && value < MAX_DECIMAL_FLOAT) + || (value == 0.0)) + snprintf(str_buf,64,"%f",value); + else snprintf(str_buf,64,"%e",value); + return new string(str_buf); + } + + string* regexp(const string& instr, const string& expression, + const Int& groupno) + { + string *retval=0; + + if(groupno<0) { + FATAL_ERROR("regexp(): groupno must be a non-negative integer"); + return retval; + } + // do not report the warnings again + // they were already reported while checking the operands + unsigned orig_verb_level = verb_level; + verb_level &= ~(1|2); + char *posix_str=TTCN_pattern_to_regexp(expression.c_str()); + verb_level = orig_verb_level; + if(posix_str==NULL) { + FATAL_ERROR("regexp(): Cannot convert pattern `%s' to POSIX-equivalent.", + expression.c_str()); + return retval; + } + + regex_t posix_regexp; + int ret_val=regcomp(&posix_regexp, posix_str, REG_EXTENDED); + Free(posix_str); + if(ret_val!=0) { + /* regexp error */ + char msg[ERRMSG_BUFSIZE]; + regerror(ret_val, &posix_regexp, msg, sizeof(msg)); + FATAL_ERROR("regexp(): regcomp() failed: %s", msg); + return retval; + } + + size_t nmatch=groupno+1; + if(nmatch>posix_regexp.re_nsub) { + FATAL_ERROR("regexp(): requested groupno is %lu, but this expression " + "contains only %lu group(s).", (unsigned long) (nmatch - 1), + (unsigned long) posix_regexp.re_nsub); + return retval; + } + regmatch_t* pmatch=(regmatch_t*)Malloc((nmatch+1)*sizeof(regmatch_t)); + ret_val=regexec(&posix_regexp, instr.c_str(), nmatch+1, pmatch, 0); + if(ret_val==0) { + if(pmatch[nmatch].rm_so != -1 && pmatch[nmatch].rm_eo != -1) + retval = new string(instr.substr(pmatch[nmatch].rm_so, + pmatch[nmatch].rm_eo - pmatch[nmatch].rm_so)); + else retval=new string(); + } + Free(pmatch); + if(ret_val!=0) { + if(ret_val==REG_NOMATCH) { + regfree(&posix_regexp); + retval=new string(); + } + else { + /* regexp error */ + char msg[ERRMSG_BUFSIZE]; + regerror(ret_val, &posix_regexp, msg, sizeof(msg)); + FATAL_ERROR("regexp(): regexec() failed: %s", msg); + } + } + else regfree(&posix_regexp); + + return retval; + } + + ustring* regexp(const ustring& instr, const ustring& expression, + const Int& groupno) + { + ustring *retval=0; + + if(groupno<0) { + FATAL_ERROR("regexp(): groupno must be a non-negative integer"); + return retval; + } + // do not report the warnings again + // they were already reported while checking the operands + unsigned orig_verb_level = verb_level; + verb_level &= ~(1|2); + int* user_groups; + char *posix_str = TTCN_pattern_to_regexp_uni( + expression.get_stringRepr_for_pattern().c_str(), &user_groups); + if (user_groups == 0) + FATAL_ERROR("regexp(): Cannot find any groups in the second argument."); + verb_level = orig_verb_level; + if(posix_str==NULL) { + FATAL_ERROR("regexp(): Cannot convert pattern `%s' to POSIX-equivalent.", + expression.get_stringRepr().c_str()); + return retval; + } + + regex_t posix_regexp; + int ret_val=regcomp(&posix_regexp, posix_str, REG_EXTENDED); + Free(posix_str); + if(ret_val!=0) { + /* regexp error */ + char msg[ERRMSG_BUFSIZE]; + regerror(ret_val, &posix_regexp, msg, sizeof(msg)); + FATAL_ERROR("regexp(): regcomp() failed: %s", msg); + return retval; + } + + size_t nmatch=user_groups[groupno+1]+1; + if(nmatch>posix_regexp.re_nsub) { + FATAL_ERROR("regexp(): requested groupno is %lu, but this expression " + "contains only %lu group(s).", (unsigned long) (groupno), + (unsigned long) user_groups[0]); + return retval; + } + + Free(user_groups); + + regmatch_t* pmatch = (regmatch_t*)Malloc((nmatch+1)*sizeof(regmatch_t)); + char* tmp = instr.convert_to_regexp_form(); + string instr_conv(tmp); + Free(tmp); + ret_val = regexec(&posix_regexp, instr_conv.c_str(), nmatch+1, pmatch, 0); + if(ret_val == 0) { + if(pmatch[nmatch].rm_so != -1 && pmatch[nmatch].rm_eo != -1) { + retval = new ustring( + instr_conv.substr(pmatch[nmatch].rm_so, + pmatch[nmatch].rm_eo - pmatch[nmatch].rm_so) + .convert_stringRepr_for_pattern()); + } else { retval = new ustring(); } + } + Free(pmatch); + if(ret_val!=0) { + if(ret_val==REG_NOMATCH) { + regfree(&posix_regexp); + retval=new ustring(); + } + else { + /* regexp error */ + char msg[ERRMSG_BUFSIZE]; + regerror(ret_val, &posix_regexp, msg, sizeof(msg)); + FATAL_ERROR("regexp(): regexec() failed: %s", msg); + } + } + else regfree(&posix_regexp); + + return retval; + } + +string* remove_bom(const string& encoded_value) +{ + size_t length = encoded_value.size(); + if (0 == length) return new string(); + if (length % 2 || 0 > length) { + ERROR("remove_bom(): Wrong string. The number of nibbles (%d) in string " + "shall be divisible by 2", static_cast(length)); + return new string(encoded_value); + } + + int length_of_BOM = 0; + string str_uppercase(encoded_value); + size_t enough = length > sizeof(utf32be)-1 ? sizeof(utf32be)-1 : length; + for (size_t i = 0; i < enough; ++i) { + str_uppercase[i] = toupper(encoded_value[i]); + } + + if (str_uppercase.find(utf32be, 0) < length) length_of_BOM = sizeof(utf32be)-1; + else if (str_uppercase.find(utf32le, 0) < length) length_of_BOM = sizeof(utf32le)-1; + else if (str_uppercase.find(utf16be, 0) < length) length_of_BOM = sizeof(utf16be)-1; + else if (str_uppercase.find(utf16le, 0) < length) length_of_BOM = sizeof(utf16le)-1; + else if (str_uppercase.find(utf8, 0) < length) length_of_BOM = sizeof(utf8)-1; + else return new string(encoded_value); // no BOM found + + return new string(encoded_value.substr(length_of_BOM, length)); +} + +static CharCoding::CharCodingType is_ascii (size_t length, const unsigned char* strptr) +{ + const unsigned char nonASCII = 1 << 7;// MSB is 1 in case of non ASCII character + CharCoding::CharCodingType ret = CharCoding::ASCII; + for (size_t i = 0; i < length; ++i) { + if ( strptr[i] & nonASCII) { + ret = CharCoding::UNKNOWN; + break; + } + } + return ret; +} + +static CharCoding::CharCodingType is_utf8(size_t length, const unsigned char* strptr) +{ + const char MSB = 1 << 7; // MSB is 1 in case of non ASCII character + const char MSBmin1 = 1 << 6; // 0100 0000 + size_t i = 0; + while (length > i) { + if ( strptr[i] & MSB) { // non ASCII char + char maskUTF8 = 1 << 6; // 111x xxxx shows how many additional bytes are there + if (!(strptr[i] & maskUTF8)) return CharCoding::UNKNOWN; // accepted 11xxx xxxx but received 10xx xxxx + unsigned int noofUTF8 = 0; // 11xx xxxxx -> 2 bytes, 111x xxxxx -> 3 bytes , 1111 xxxxx -> 4 bytes in UTF-8 + while (strptr[i] & maskUTF8) { + ++noofUTF8; + maskUTF8 >>= 1; // shift right the mask + } + // the second and third (and so on) UTF-8 byte looks like 10xx xxxx + while (0 < noofUTF8 ) { + ++i; + if (!(strptr[i] & MSB) || (strptr[i] & MSBmin1) || i >= length) { // if not like this: 10xx xxxx + return CharCoding::UNKNOWN; + } + --noofUTF8; + } + } + ++i; + } + return CharCoding::UTF_8; +} + +string* get_stringencoding(const string& encoded_value) +{ + size_t length = encoded_value.size(); + if (0 == length) return new string(""); + if (length % 2 || 0 > length) { + ERROR("get_stringencoding(): Wrong string. The number of nibbles (%d) in string " + "shall be divisible by 2", static_cast(length)); + return new string(""); + } + + string str_uppercase(encoded_value); + size_t enough = length > sizeof(utf32be)-1 ? sizeof(utf32be)-1 : length; + for (size_t i = 0; i < enough; ++i) { + str_uppercase[i] = toupper(encoded_value[i]); + } + + if (str_uppercase.find(utf32be, 0) < length) return new string("UTF-32BE"); + else if (str_uppercase.find(utf32le, 0) < length) return new string("UTF-32LE"); + else if (str_uppercase.find(utf16be, 0) < length) return new string("UTF-16BE"); + else if (str_uppercase.find(utf16le, 0) < length) return new string("UTF-16LE"); + else if (str_uppercase.find(utf8, 0) < length) return new string("UTF-8"); + + unsigned char *uc_str = new unsigned char[length/2]; + string ret; + for (size_t i = 0; i < length / 2; ++i) { + uc_str[i] = str2uchar(encoded_value[2 * i], encoded_value[2 * i + 1]); + } + if (is_ascii (length / 2, uc_str) == CharCoding::ASCII) ret = "ASCII"; + else if (CharCoding::UTF_8 == is_utf8 (length / 2, uc_str)) ret = "UTF-8"; + else ret = ""; + + delete [] uc_str; + return new string(ret); +} + +static size_t check_BOM(CharCoding::CharCodingType expected_coding, size_t n_uc, unsigned char* uc_str) +{ + if (0 == n_uc) return 0; + + switch (expected_coding) { + case CharCoding::UTF32: + case CharCoding::UTF32BE: + case CharCoding::UTF32LE: + if (4 > n_uc) { + ERROR("decode_utf32(): The string is shorter than the expected BOM"); + return 0; + } + break; + case CharCoding::UTF16: + case CharCoding::UTF16BE: + case CharCoding::UTF16LE: + if (2 > n_uc) { + ERROR("decode_utf16(): The string is shorter than the expected BOM"); + return 0; + } + break; + default: break; + } + + //BOM indicates that the byte order is determined by a byte order mark, + //if present at the beginning the length of BOM is returned. + bool badBOM = false; + string errmsg; + string caller; + switch (expected_coding) { + case CharCoding::UTF32BE: + case CharCoding::UTF32: + if (0x00 == uc_str[0] && 0x00 == uc_str[1] && 0xFE == uc_str[2] && 0xFF == uc_str[3]) + return 4; + badBOM = true; + caller = "decode_utf32()"; + errmsg = "UTF-32BE"; + break; + case CharCoding::UTF32LE: + if (0xFF == uc_str[0] && 0xFE == uc_str[1] && 0x00 == uc_str[2] && 0x00 == uc_str[3]) + return 4; + badBOM = true; + caller = "decode_utf32()"; + errmsg = "UTF-32LE"; + break; + case CharCoding::UTF16BE: + case CharCoding::UTF16: + if (0xFE == uc_str[0] && 0xFF == uc_str[1]) + return 2; + badBOM = true; + caller = "decode_utf16()"; + errmsg = "UTF-16BE"; + break; + case CharCoding::UTF16LE: + if (0xFF == uc_str[0] && 0xFE == uc_str[1]) + return 2; + badBOM = true; + caller = "decode_utf16()"; + errmsg = "UTF-16LE"; + break; + case CharCoding::UTF_8: + if (0xEF == uc_str[0] && 0xBB == uc_str[1] && 0xBF == uc_str[2]) + return 3; + return 0; + default: + if (CharCoding::UTF32 == expected_coding || CharCoding::UTF16 == expected_coding) { + const char* str = CharCoding::UTF32 == expected_coding ? "UTF-32" : "UTF-16"; + ERROR("Wrong %s string. No BOM detected, however the given coding type (%s) " + "expects it to define the endianness", str, str); + } + else { + ERROR("Wrong string. No BOM detected"); + } + } + if (badBOM) ERROR("%s: Wrong %s string. The expected coding could not be verified", + caller.c_str(), errmsg.c_str()); + return 0; +} + +static void fill_continuing_octets(int n_continuing, unsigned char *continuing_ptr, + size_t n_uc, const unsigned char* uc_str, int start_pos, + int uchar_pos) +{ + for (int i = 0; i < n_continuing; i++) { + if (start_pos + i < static_cast(n_uc)) { + unsigned char octet = uc_str[start_pos + i]; + if ((octet & 0xC0) != 0x80) { + ERROR("decode_utf8(): Malformed: At character position %u, octet position %u: %02X is " + "not a valid continuing octet.", uchar_pos, start_pos + i, octet); + return; + } + continuing_ptr[i] = octet & 0x3F; + } + else { + if (start_pos + i == static_cast(n_uc)) { + if (i > 0) { + // only a part of octets is missing + ERROR("decode_utf8(): Incomplete: At character position %d, octet position %d: %d out " + "of %d continuing octets %s missing from the end of the stream.", + uchar_pos, start_pos + i, n_continuing - i, n_continuing, + n_continuing - i > 1 ? "are" : "is"); + return; + } + else { + // all octets are missing + ERROR("decode_utf8(): Incomplete: At character position %d, octet position %d: %d " + "continuing octet%s missing from the end of the stream.", uchar_pos, + start_pos, n_continuing, n_continuing > 1 ? "s are" : " is"); + return; + } + } + continuing_ptr[i] = 0; + } + } +} + +ustring decode_utf8(const string & ostr, CharCoding::CharCodingType expected_coding) +{ + size_t length = ostr.size(); + if (0 == length) return ustring(); + if (length % 2) { + ERROR("decode_utf8(): Wrong UTF-8 string. The number of nibbles (%d) in octetstring " + "shall be divisible by 2", static_cast(length)); + return ustring(); + } + + unsigned char *uc_str = new unsigned char[length/2]; + for (size_t i = 0; i < length / 2; ++i) { + uc_str[i] = str2uchar(ostr[2 * i], ostr[2 * i + 1]); + } + ustring ucstr; + size_t start = check_BOM(CharCoding::UTF_8, length /2, uc_str); + + for (size_t i = start; i < length / 2;) { + // perform the decoding character by character + if (uc_str[i] <= 0x7F) { + // character encoded on a single octet: 0xxxxxxx (7 useful bits) + unsigned char g = 0; + unsigned char p = 0; + unsigned char r = 0; + unsigned char c = uc_str[i]; + ucstr += ustring(g, p, r, c); + ++i; + } + else if (uc_str[i] <= 0xBF) { + // continuing octet (10xxxxxx) without leading octet ==> malformed + ERROR("decode_utf8(): Malformed: At character position %d, octet position %d: continuing " + "octet %02X without leading octet.", static_cast(ucstr.size()), + static_cast(i), uc_str[i]); + goto dec_error; + } + else if (uc_str[i] <= 0xDF) { + // character encoded on 2 octets: 110xxxxx 10xxxxxx (11 useful bits) + unsigned char octets[2]; + octets[0] = uc_str[i] & 0x1F; + fill_continuing_octets(1, octets + 1, length / 2, uc_str, i + 1, ucstr.size()); + unsigned char g = 0; + unsigned char p = 0; + unsigned char r = octets[0] >> 2; + unsigned char c = octets[0] << 6 | octets[1]; + if (r == 0x00 && c < 0x80) { + ERROR("decode_utf8(): Overlong: At character position %d, octet position %d: 2-octet " + "encoding for quadruple (0, 0, 0, %u).", static_cast(ucstr.size()), + static_cast(i), c); + goto dec_error; + } + ucstr += ustring(g, p, r, c); + i += 2; + } + else if (uc_str[i] <= 0xEF) { + // character encoded on 3 octets: 1110xxxx 10xxxxxx 10xxxxxx + // (16 useful bits) + unsigned char octets[3]; + octets[0] = uc_str[i] & 0x0F; + fill_continuing_octets(2, octets + 1, length / 2, uc_str, i + 1,ucstr.size()); + unsigned char g = 0; + unsigned char p = 0; + unsigned char r = octets[0] << 4 | octets[1] >> 2; + unsigned char c = octets[1] << 6 | octets[2]; + if (r < 0x08) { + ERROR("decode_utf8(): Overlong: At character position %d, octet position %d: 3-octet " + "encoding for quadruple (0, 0, %u, %u).", static_cast(ucstr.size()), + static_cast(i), r, c); + goto dec_error; + } + ucstr += ustring(g, p, r, c); + i += 3; + } + else if (uc_str[i] <= 0xF7) { + // character encoded on 4 octets: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + // (21 useful bits) + unsigned char octets[4]; + octets[0] = uc_str[i] & 0x07; + fill_continuing_octets(3, octets + 1, length / 2, uc_str, i + 1, ucstr.size()); + unsigned char g = 0; + unsigned char p = octets[0] << 2 | octets[1] >> 4; + unsigned char r = octets[1] << 4 | octets[2] >> 2; + unsigned char c = octets[2] << 6 | octets[3]; + if (p == 0x00) { + ERROR("decode_utf8(): Overlong: At character position %d, octet position %d: 4-octet " + "encoding for quadruple (0, 0, %u, %u).", static_cast(ucstr.size()), + static_cast(i), r, c); + goto dec_error; + } + ucstr += ustring(g, p, r, c); + i += 4; + } + else if (uc_str[i] <= 0xFB) { + // character encoded on 5 octets: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx + // 10xxxxxx (26 useful bits) + unsigned char octets[5]; + octets[0] = uc_str[i] & 0x03; + fill_continuing_octets(4, octets + 1, length / 2, uc_str, i + 1, ucstr.size()); + unsigned char g = octets[0]; + unsigned char p = octets[1] << 2 | octets[2] >> 4; + unsigned char r = octets[2] << 4 | octets[3] >> 2; + unsigned char c = octets[3] << 6 | octets[4]; + if (g == 0x00 && p < 0x20) { + ERROR("decode_utf8(): Overlong: At character position %d, octet position %d: 5-octet " + "encoding for quadruple (0, %u, %u, %u).", static_cast(ucstr.size()), + static_cast(i), p, r, c); + goto dec_error; + } + ucstr += ustring(g, p, r, c); + i += 5; + } + else if (uc_str[i] <= 0xFD) { + // character encoded on 6 octets: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx + // 10xxxxxx 10xxxxxx (31 useful bits) + unsigned char octets[6]; + octets[0] = uc_str[i] & 0x01; + fill_continuing_octets(5, octets + 1, length / 2, uc_str, i + 1,ucstr.size()); + unsigned char g = octets[0] << 6 | octets[1]; + unsigned char p = octets[2] << 2 | octets[3] >> 4; + unsigned char r = octets[3] << 4 | octets[4] >> 2; + unsigned char c = octets[4] << 6 | octets[5]; + if (g < 0x04) { + ERROR("decode_utf8(): Overlong: At character position %d, octet position %d: 6-octet " + "encoding for quadruple (%u, %u, %u, %u).", static_cast(ucstr.size()), + static_cast(i), g, p, r, c); + goto dec_error; + } + ucstr += ustring(g, p, r, c); + i += 6; + } + else { + // not used code points: FE and FF => malformed + ERROR("decode_utf8(): Malformed: At character position %d, octet position %d: " + "unused/reserved octet %02X.", static_cast(ucstr.size()), + static_cast(i), uc_str[i]); + goto dec_error; + } + } + + dec_error: + delete[] uc_str; + return ucstr; +} + +} diff --git a/compiler2/PredefFunc.hh b/compiler2/PredefFunc.hh new file mode 100644 index 0000000..0131b42 --- /dev/null +++ b/compiler2/PredefFunc.hh @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Common_PredefFunc_HH +#define _Common_PredefFunc_HH + +#include "Int.hh" +#include "Real.hh" +#include "../common/CharCoding.hh" + +class string; +class ustring; + +namespace Common { + + extern char hexdigit_to_char(unsigned char hexdigit); + extern unsigned char char_to_hexdigit(char c); + + extern int_val_t rem(const int_val_t& left, const int_val_t& right); + extern int_val_t mod(const int_val_t& left, const int_val_t& right); + extern string* to_uppercase(const string& value); + extern string* not4b_bit(const string& bstr); + extern string* not4b_hex(const string& hstr); + extern string* and4b(const string& left, const string& right); + extern string* or4b(const string& left, const string& right); + extern string* xor4b(const string& left, const string& right); + extern string* shift_left(const string& value, const Int& count); + extern string* shift_right(const string& value, const Int& count); + extern string* rotate_left(const string& value, const Int& count); + extern string* rotate_right(const string& value, const Int& count); + extern ustring* rotate_left(const ustring& value, const Int& count); + extern ustring* rotate_right(const ustring& value, const Int& count); + + extern int_val_t* bit2int(const string& bstr); + extern int_val_t* hex2int(const string& hstr); + extern Int unichar2int(const ustring& ustr); + extern string* int2bit(const int_val_t& value, const Int& length); + extern string* int2hex(const int_val_t& value, const Int& length); + extern ustring* int2unichar(const Int& value); + extern string* oct2char(const string& ostr); + extern string* char2oct(const string& cstr); + extern string* bit2hex(const string& bstr); + extern string* hex2oct(const string& hstr); + extern string* asn_hex2oct(const string& hstr); + extern string* bit2oct(const string& bstr); + extern string* asn_bit2oct(const string& bstr); + extern string* hex2bit(const string& hstr); + extern Real int2float(const int_val_t& value); + extern int_val_t* float2int(const Real& value, const Location& loc); + extern string* float2str(const Real& value); + extern string* regexp(const string& instr, const string& expression, + const Int& groupno); + extern ustring* regexp(const ustring& instr, const ustring& expression, + const Int& groupno); + extern string* remove_bom(const string& encoded_value); + extern string* get_stringencoding(const string& encoded_value); + extern ustring decode_utf8(const string & ostr, CharCoding::CharCodingType expected_coding); +} + +#endif // _Common_PredefFunc_HH diff --git a/compiler2/Real.cc b/compiler2/Real.cc new file mode 100644 index 0000000..0a15eda --- /dev/null +++ b/compiler2/Real.cc @@ -0,0 +1,90 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "Real.hh" +#include "string.hh" +#include "error.h" +#include "Setting.hh" + +#include +#include +#include +#include + +namespace Common { + + bool isSpecialFloatValue(const Real& r) + { + return ((r!=r) || (r==REAL_INFINITY) || (r==-REAL_INFINITY)); + } + + string Real2string(const Real& r) + { + if (r == 0.0) return ((1.0/r)==-REAL_INFINITY) ? string("-0.0e0") : string("0.0e0"); + else if (r == REAL_INFINITY) return string("INF"); + else if (r == -REAL_INFINITY) return string("-INF"); + else if (r != r) return string("NaN"); + + Real rabs = fabs(r); + int sign = (r / rabs < 0) ? -1 : 1; + double exponent = floor(log10(rabs)); + double fraction = rabs * pow(10.0, -exponent); + double integral = floor(fraction); + char tmp[64]; + + sprintf(tmp, "%s%.15g%se%d", + (sign == -1) ? "-" : "", + fraction, + (fraction == integral) ? ".0" : "", + (int)exponent); + + return string(tmp); + } + + string Real2code(const Real& r) + { + if (r == 0.0) return ((1.0/r)==-REAL_INFINITY) ? string("-0.0") : string("0.0"); + else if (r == REAL_INFINITY) return string("PLUS_INFINITY"); + else if (r == -REAL_INFINITY) return string("MINUS_INFINITY"); + else if (r != r) return string("NOT_A_NUMBER"); + else { + Real rabs = fabs(r); + Real exponent = floor(log10(rabs)); + Real mantissa = rabs * pow(10.0, -exponent); + + char *tmp = mprintf("%s%.15g", r < 0.0 ? "-" : "", mantissa); + if (floor(mantissa) == mantissa) tmp = mputstr(tmp, ".0"); + if (exponent != 0.0) tmp = mputprintf(tmp, "e%d", (int)exponent); + string ret_val(tmp); + Free(tmp); + return ret_val; + } + } + + Real string2Real(const char *s, const Location& loc) + { + if (s[0] == '\0' || !strcmp(s, "0.0e0")) return 0.0; + else if (!strcmp(s, "-INF")) return -REAL_INFINITY; + else if (!strcmp(s, "INF")) return REAL_INFINITY; + else if (!strcmp(s, "NaN")) return REAL_NAN; + errno = 0; + Real r = strtod(s, NULL); + switch (errno) { + case ERANGE: + loc.error("Overflow when converting `%s' to a floating point value: %s", + s, strerror(errno)); + break; + case 0: + break; + default: + FATAL_ERROR("string2Real(): Unexpected error when converting `%s' to real: %s", + s, strerror(errno)); + } + return r; + } + +} // namespace Common diff --git a/compiler2/Real.hh b/compiler2/Real.hh new file mode 100644 index 0000000..1e5380b --- /dev/null +++ b/compiler2/Real.hh @@ -0,0 +1,88 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Common_Real_HH +#define _Common_Real_HH + +#include "string.hh" +#include + +// older versions of gcc do not have numeric_limits or it is wrong +// and they do not have constants defined by C99 standard +#ifdef INFINITY +static const double REAL_INFINITY = INFINITY; +#else +#include +static const double REAL_INFINITY = (DBL_MAX*DBL_MAX); +#endif + +#ifdef NAN +static const double REAL_NAN = NAN; +#else +static const double REAL_NAN = (REAL_INFINITY-REAL_INFINITY); +#endif + +namespace Common { + + class Location; + + /** + * \defgroup Real Real type and related functions + * + * Real type is used to represent those real/float values which will + * be used in TITAN run-time environment, in the compiler. + * + * @{ + */ + + /** Real typedef */ + + typedef double Real; + + /** +/- infinity and not_a_number are non-numeric float values in ttcn-3, + these special values cannot be used in some places */ + bool isSpecialFloatValue(const Real& r); + + /** + * Converts the Common::Real value to string. + * + * The returned string looks like this: + * + *
+     (
+      (
+        ([\-][1-9]\.(([0-9]+[1-9])|0))
+       |
+        ([\-]0\.([0-9]+[1-9]))
+      )
+      "e"
+      (([\-][1-9][0-9]*)|0)
+     )
+    |
+     (0\.0e0)
+    |
+     "INF"
+    |
+     "-INF"
+   * 
+ */ + string Real2string(const Real& r); + + /** Returns the C++ equivalent of value r */ + string Real2code(const Real& r); + + /** + * Converts the string value to Common::Real. + */ + Real string2Real(const char *s, const Location& loc); + inline Real string2Real(const string& s, const Location& loc) + { return string2Real(s.c_str(), loc); } + /** @} end of Real group */ + +} // namespace Common + +#endif // _Common_Real_HH diff --git a/compiler2/Setting.cc b/compiler2/Setting.cc new file mode 100644 index 0000000..64c02b6 --- /dev/null +++ b/compiler2/Setting.cc @@ -0,0 +1,861 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "../common/dbgnew.hh" +#include "Setting.hh" +#include +#include +#include "map.hh" +#include "Identifier.hh" +#include "CompilerError.hh" +#include "AST.hh" +#include "asn1/AST_asn1.hh" +#include "ttcn3/AST_ttcn3.hh" +#include "Value.hh" +#include "Int.hh" +#include "main.hh" + +namespace Common { + + // ================================= + // ===== Location + // ================================= + + map *Location::source_file_names = NULL; + bool Location::transparency = false; + + const char* Location::add_source_file_name(const string& file_name) + { + if (source_file_names==NULL) + source_file_names = new map(); + if (!source_file_names->has_key(file_name)) + source_file_names->add(file_name, NULL); + return source_file_names->get_key(file_name).c_str(); + } + + void Location::delete_source_file_names() + { + if (source_file_names!=NULL) + { + source_file_names->clear(); + delete source_file_names; + source_file_names = NULL; + } + } + + Location::Location() + { + filename = NULL; + yyloc.first_line = 0; + yyloc.last_line = 0; + yyloc.first_column = 0; + yyloc.last_column = 0; + } + + void Location::set_location(const char *p_filename, int p_lineno) + { + filename = p_filename; + yyloc.first_line = p_lineno; + yyloc.first_column = 0; + yyloc.last_line = p_lineno; + yyloc.last_column = 0; + } + + void Location::set_location(const char *p_filename, const YYLTYPE& p_yyloc) + { + filename = p_filename; + yyloc = p_yyloc; + } + + void Location::set_location(const char *p_filename, const YYLTYPE& p_firstloc, + const YYLTYPE& p_lastloc) + { + filename = p_filename; + yyloc.first_line = p_firstloc.first_line; + yyloc.first_column = p_firstloc.first_column; + yyloc.last_line = p_lastloc.last_line; + yyloc.last_column = p_lastloc.last_column; + } + + void Location::set_location(const char *p_filename, int p_first_line, + int p_first_column, int p_last_line, int p_last_column) + { + filename = p_filename; + yyloc.first_line = p_first_line; + yyloc.first_column = p_first_column; + yyloc.last_line = p_last_line; + yyloc.last_column = p_last_column; + } + + void Location::join_location(const Location& p) + { + // do nothing if this and p refer to different files + if (filename) { + if (!p.filename) return; + else if (strcmp(filename, p.filename)) return; + } else if (p.filename) return; + if (yyloc.last_line < p.yyloc.first_line || + (yyloc.last_line == p.yyloc.first_line && + yyloc.last_column <= p.yyloc.first_column)) { + // p is after this + yyloc.last_line = p.yyloc.last_line; + yyloc.last_column = p.yyloc.last_column; + } else if (yyloc.first_line > p.yyloc.last_line || + (yyloc.first_line == p.yyloc.last_line && + yyloc.first_column >= p.yyloc.last_column)) { + // p is before this + yyloc.first_line = p.yyloc.first_line; + yyloc.first_column = p.yyloc.first_column; + } + } + + void Location::print_line_info(FILE *fp) const + { + if (yyloc.first_line > 0) { + // at least partial line/column information is available + if (output_only_linenum || (yyloc.first_line == yyloc.last_line && + yyloc.first_column <= 0 && yyloc.last_column <= 0)) { + // print only the first line + fprintf(fp, "%d", yyloc.first_line); + } else if (yyloc.last_line > yyloc.first_line) { + // multi-line area + if (yyloc.first_column >= 0 && yyloc.last_column >= 0) { + // all line/column fields are valid + if (gcc_compat) { + fprintf(fp, "%d:%d", yyloc.first_line, yyloc.first_column + 1); + } + else { + fprintf(fp, "%d.%d-%d.%d", yyloc.first_line, + yyloc.first_column + 1, yyloc.last_line, yyloc.last_column); + } + } else { + // only the line numbers are valid + if (gcc_compat) { + fprintf(fp, "%d", yyloc.first_line); + } + else { + fprintf(fp, "%d-%d", yyloc.first_line, yyloc.last_line); + } + } + } else if (yyloc.first_line == yyloc.last_line) { + // single line area + if (yyloc.first_column >= 0 && yyloc.last_column > yyloc.first_column) { + if (gcc_compat) { + fprintf(fp, "%d:%d", yyloc.first_line, yyloc.first_column + 1); + } + else { + if (yyloc.last_column > yyloc.first_column + 1) { + // more characters are covered + fprintf(fp, "%d.%d-%d", yyloc.first_line, yyloc.first_column + 1, + yyloc.last_column); + } else { + // only a single character is covered + fprintf(fp, "%d.%d", yyloc.first_line, yyloc.first_column + 1); + } + } + } else { + // the column information is invalid, print the line number only + fprintf(fp, "%d", yyloc.first_line); + } + } else { + // the last line is smaller than the first line + // print only the first line + fprintf(fp, "%d", yyloc.first_line); + } + } else { + // line information is not available + fputs("", fp); + } + } + + void Location::print_location(FILE *fp) const + { + if (filename) { + fputs(filename, fp); + if (yyloc.first_line > 0) { + // print the line information only if it is available + putc(':', fp); + print_line_info(fp); + } + fputs(": ", fp); + } + // do not print anything if the file name is unknown + } + + void Location::error(const char *fmt, ...) const + { + va_list args; + va_start(args, fmt); + Error_Context::report_error(this, fmt, args); + va_end(args); + } + + void Location::warning(const char *fmt, ...) const + { + va_list args; + va_start(args, fmt); + Error_Context::report_warning(this, fmt, args); + va_end(args); + } + + void Location::note(const char *fmt, ...) const + { + va_list args; + va_start(args, fmt); + Error_Context::report_note(this, fmt, args); + va_end(args); + } + + char *Location::create_location_object(char *str, const char *entitytype, + const char *entityname) const + { + if (!filename || yyloc.first_line <= 0) + FATAL_ERROR("Location::create_location_object()"); + if (include_location_info && !transparency) { + bool tcov_enabled = tcov_file_name && in_tcov_files(get_filename()); + str = mputstr(str, + !tcov_enabled ? "TTCN_Location current_location(\"" + : "TTCN_Location_Statistics current_location(\""); + str = Code::translate_string(str, filename); + str = mputprintf(str, + !tcov_enabled ? "\", %d, TTCN_Location::LOCATION_%s, \"%s\");\n" + : "\", %d, TTCN_Location_Statistics::LOCATION_%s, \"%s\");\n", yyloc.first_line, entitytype, entityname); + if (tcov_enabled) { + effective_module_lines = + mputprintf(effective_module_lines, "%s%d", + (effective_module_lines ? ", " : ""), yyloc.first_line); + effective_module_functions = + mputprintf(effective_module_functions, "%s\"%s\"", + (effective_module_functions ? ", " : ""), entityname); + } + } + return str; + } + + char *Location::update_location_object(char *str) const + { + if (filename && yyloc.first_line > 0) { + if (include_location_info && !transparency) { + str = mputprintf(str, "current_location.update_lineno(%d);\n", + yyloc.first_line); + if (tcov_file_name && in_tcov_files(get_filename())) { + effective_module_lines = + mputprintf(effective_module_lines, "%s%d", + (effective_module_lines ? ", " : ""), yyloc.first_line); + } + } + + if (include_line_info) + str = mputprintf(str, "#line %d \"%s\"\n", yyloc.first_line, filename); + else str = mputprintf(str, "/* %s, line %d */\n", filename, + yyloc.first_line); + } + return str; + } + + // ================================= + // ===== Node + // ================================= + + int Node::counter=0; +#ifdef MEMORY_DEBUG + static Node *list_head = 0, *list_tail = 0; +#endif + + Node::Node() + { +#ifdef MEMORY_DEBUG + prev_node = list_tail; + next_node = 0; + if (list_tail) list_tail->next_node = this; + else list_head = this; + list_tail = this; +#endif + counter++; + } + + Node::Node(const Node&) + : fullname() + { +#ifdef MEMORY_DEBUG + prev_node = list_tail; + next_node = 0; + if (list_tail) list_tail->next_node = this; + else list_head = this; + list_tail = this; +#endif + counter++; + } + + Node::~Node() + { + counter--; +#ifdef MEMORY_DEBUG + if (prev_node) prev_node->next_node = next_node; + else list_head = next_node; + if (next_node) next_node->prev_node = prev_node; + else list_tail = prev_node; +#endif + } + + + void Node::chk_counter() + { + DEBUG(1, "Node::counter is %d", counter); + if(counter) + WARNING("%d nodes were not deleted." + " Please send a bug report including" + " the current input file(s).", counter); +#ifdef MEMORY_DEBUG + for (Node *iter = list_head; iter; iter = iter->next_node) { + fprintf(stderr, "Undeleted node: `%s' (address %p).\n", + iter->get_fullname().c_str(), static_cast(iter)); + } + list_head = 0; + list_tail = 0; +#endif + } + + void Node::set_fullname(const string& p_fullname) + { + fullname = p_fullname; + } + + void Node::set_my_scope(Scope *) + { + } + + void Node::dump(unsigned level) const + { + DEBUG(level, "Node: %s", fullname.c_str()); + } + + // ================================= + // ===== Setting + // ================================= + + Setting::Setting(settingtype_t p_st) + : Node(), Location(), + st(p_st), my_scope(0), checked(false), recurs_checked(false) + { + } + + void Setting::set_my_scope(Scope *p_scope) + { + my_scope = p_scope; + } + + bool Setting::is_asn1() const + { + if (!my_scope) FATAL_ERROR("Setting::is_asn1()"); + return my_scope->get_scope_mod()->get_moduletype() == Module::MOD_ASN; + } + + string Setting::get_temporary_id() const + { + if (!my_scope) FATAL_ERROR("Setting::get_temporary_id()"); + return my_scope->get_scope_mod_gen()->get_temporary_id(); + } + + void Setting::set_genname(const string& p_genname) + { + if (p_genname.empty()) FATAL_ERROR("Setting::set_genname()"); + genname = p_genname; + } + + void Setting::set_genname(const string& p_prefix, const string& p_suffix) + { + if (p_prefix.empty() || p_suffix.empty()) + FATAL_ERROR("Setting::set_genname()"); + genname = p_prefix; + // a single underscore character is needed as separator if neither p_prefix + // ends nor p_suffix begins with a single underscore character + size_t p_prefix_len = p_prefix.size(); + if ((p_prefix[p_prefix_len - 1] != '_' || + (p_prefix_len >= 2 && p_prefix[p_prefix_len - 2] == '_')) && + (p_suffix[0] != '_' || + (p_suffix.size() >= 2 && p_suffix[1] == '_'))) genname += '_'; + genname += p_suffix; + } + + const string& Setting::get_genname_own() const + { + if (genname.empty()) + FATAL_ERROR("Setting::get_genname_own(): genname is not set in %s", \ + get_fullname().c_str()); + return genname; + } + + string Setting::get_genname_own(Scope *p_scope) const + { + if (!p_scope || !my_scope) FATAL_ERROR("Setting::get_genname_own"); + string ret_val; + Module *my_mod = my_scope->get_scope_mod_gen(); + if (my_mod != p_scope->get_scope_mod_gen() && + !Asn::Assignments::is_spec_asss(my_mod)) { + // when the definition is referred from another module + // the reference shall be qualified with the namespace of my module + ret_val = my_mod->get_modid().get_name(); + ret_val += "::"; + } + ret_val += get_genname_own(); + return ret_val; + } + + string Setting::create_stringRepr() + { + return string(""); + } + + // ================================= + // ===== Setting_Error + // ================================= + + Setting_Error* Setting_Error::clone() const + { + FATAL_ERROR("Setting_Error::clone"); + } + + // ================================= + // ===== Governor + // ================================= + + // ================================= + // ===== Governed + // ================================= + + // ================================= + // ===== GovernedSimple + // ================================= + + string GovernedSimple::get_lhs_name() const + { + string ret_val; + if (genname_prefix) ret_val += genname_prefix; + ret_val += get_genname_own(); + return ret_val; + } + + bool GovernedSimple::needs_init_precede(const GovernedSimple *refd) const + { + if (refd->code_generated) return false; + if (code_section == CS_UNKNOWN || refd->code_section == CS_UNKNOWN) + FATAL_ERROR("GovernedSimple::needs_init_precede()"); + if (code_section != refd->code_section) return false; + if (get_my_scope()->get_scope_mod_gen() != + refd->get_my_scope()->get_scope_mod_gen()) return false; + else return true; + } + + bool GovernedSimple::is_toplevel() const + { + const string& name = get_genname_own(); + const char *name_str = name.c_str(); + size_t name_len = name.size(); + for (size_t i = 0; i < name_len; i++) { + char c = name_str[i]; + if ((c < 'A' || c > 'Z') && (c < 'a' ||c > 'z') && + (c < '0' || c > '9') && c != '_') return false; + } + return true; + } + + // ================================= + // ===== GovdSet + // ================================= + + // ================================= + // ===== Scope + // ================================= + + string Scope::get_scope_name() const + { + string s; + if (parent_scope) s = parent_scope->get_scope_name(); + if (!scope_name.empty()) { + if (s.empty()) s = scope_name; + else { + s += '.'; + s += scope_name; + } + } + return s; + } + + string Scope::get_scopeMacro_name() const + { + if (!scopeMacro_name.empty()) return scopeMacro_name; + if (parent_scope) return parent_scope->get_scopeMacro_name(); + return scopeMacro_name; + } + + Ttcn::StatementBlock *Scope::get_statementblock_scope() + { + if (parent_scope) return parent_scope->get_statementblock_scope(); + else return 0; + } + + Ttcn::RunsOnScope *Scope::get_scope_runs_on() + { + if (parent_scope) return parent_scope->get_scope_runs_on(); + else return 0; + } + + Assignments *Scope::get_scope_asss() + { + if (parent_scope) return parent_scope->get_scope_asss(); + else + FATAL_ERROR("The assignments scope is not visible from this scope: " \ + "`%s'", get_scope_name().c_str()); + return 0; + } + + Module* Scope::get_scope_mod() + { + if(parent_scope) return parent_scope->get_scope_mod(); + else FATAL_ERROR("The module scope is not visible from this scope: `%s'", \ + get_scope_name().c_str()); + return 0; + } + + Module* Scope::get_scope_mod_gen() + { + if(parent_scope_gen) return parent_scope_gen->get_scope_mod_gen(); + else if(parent_scope) return parent_scope->get_scope_mod_gen(); + else FATAL_ERROR("The module scope is not visible from this scope: `%s'", \ + get_scope_name().c_str()); + return 0; + } + + bool Scope::has_ass_withId(const Identifier& p_id) + { + if (parent_scope) return parent_scope->has_ass_withId(p_id); + else return false; + } + + bool Scope::is_valid_moduleid(const Identifier& p_id) + { + if (parent_scope) return parent_scope->is_valid_moduleid(p_id); + else return false; + } + + Type *Scope::get_mtc_system_comptype(bool is_system, bool is_connecting) + { + if (parent_scope) return parent_scope->get_mtc_system_comptype(is_system, is_connecting); + else return 0; + } + + void Scope::chk_runs_on_clause(Assignment *p_ass, const Location& p_loc, + const char *p_what) + { + // component type of the referred definition + Type *refd_comptype = p_ass->get_RunsOnType(); + // definitions without 'runs on' can be called from anywhere + if (!refd_comptype) return; + Ttcn::RunsOnScope *t_ros = get_scope_runs_on(); + if (t_ros) { + Type *local_comptype = t_ros->get_component_type(); + if (!refd_comptype->is_compatible(local_comptype, NULL)) { + // the 'runs on' clause of the referred definition is not compatible + // with that of the current scope (i.e. the referring definition) + p_loc.error("Runs on clause mismatch: A definition that runs on " + "component type `%s' cannot %s %s, which runs on `%s'", + local_comptype->get_typename().c_str(), p_what, + p_ass->get_description().c_str(), + refd_comptype->get_typename().c_str()); + } + } else { + // the current scope unit (i.e. the referring definition) does not have + // 'runs on' clause + p_loc.error("A definition without `runs on' clause cannot %s %s, which " + "runs on component type `%s'", p_what, p_ass->get_description().c_str(), + refd_comptype->get_typename().c_str()); + } + } + + void Scope::chk_runs_on_clause(Type *p_fat, const Location& p_loc, + const char *p_what) + { + if (!p_fat) FATAL_ERROR("Scope::chk_runs_on_clause()"); + Type *refd_comptype = p_fat->get_fat_runs_on_type(); + // values of function/altstep types without 'runs on' clause + // or using 'runs on self' clause can be called from anywhere + if (!refd_comptype) return; + const char *typetype_name; + switch (p_fat->get_typetype()) { + case Type::T_FUNCTION: + typetype_name = "function"; + break; + case Type::T_ALTSTEP: + typetype_name = "altstep"; + break; + default: + FATAL_ERROR("Scope::chk_runs_on_clause()"); + typetype_name = 0; + } + Ttcn::RunsOnScope *t_ros = get_scope_runs_on(); + if (t_ros) { + Type *local_comptype = t_ros->get_component_type(); + if (!refd_comptype->is_compatible(local_comptype, NULL)) { + // the 'runs on' clause of the function/altstep type is not compatible + // with that of the current scope (i.e. the referring definition) + p_loc.error("Runs on clause mismatch: A definition that runs on " + "component type `%s' cannot %s a value of %s type `%s', which runs " + "on `%s'", local_comptype->get_typename().c_str(), p_what, + typetype_name, p_fat->get_typename().c_str(), + refd_comptype->get_typename().c_str()); + } + } else { + // the current scope unit (i.e. the referring definition) does not have + // 'runs on' clause + p_loc.error("A definition without `runs on' clause cannot %s a value of " + "%s type `%s', which runs on component type `%s'", p_what, + typetype_name, p_fat->get_typename().c_str(), + refd_comptype->get_typename().c_str()); + } + } + + // ================================= + // ===== Reference + // ================================= + + size_t Reference::_Reference_counter=0; + Setting_Error *Reference::setting_error = 0; + + Reference::~Reference() + { + if (_Reference_counter <= 0) FATAL_ERROR("Reference::~Reference()"); + else if (--_Reference_counter == 0) { + delete setting_error; + setting_error = 0; + } + } + + void Reference::set_my_scope(Scope *p_scope) + { + my_scope = p_scope; + } + + bool Reference::get_is_erroneous() + { + return is_erroneous; + } + + Setting* Reference::get_refd_setting_error() + { + is_erroneous=true; + if(!setting_error) + setting_error=new Setting_Error(); + return setting_error; + } + + bool Reference::refers_to_st(Setting::settingtype_t p_st, + ReferenceChain*) + { + Setting *t_setting=get_refd_setting(); + if(t_setting) return t_setting->get_st()==p_st; + else return p_st==Setting::S_ERROR; + } + + void Reference::set_code_section(GovernedSimple::code_section_t) + { + } + + Ttcn::FieldOrArrayRefs *Reference::get_subrefs() + { + return 0; + } + + Ttcn::ActualParList *Reference::get_parlist() + { + return 0; + } + + void Reference::dump(unsigned level) const + { + DEBUG(level, "Reference: %s", const_cast(this)->get_dispname().c_str()); + } + + // ================================= + // ===== Ref_simple + // ================================= + + string Ref_simple::get_dispname() + { + string ret_val; + const Identifier *t_modid = get_modid(); + if (t_modid) { + ret_val += t_modid->get_dispname(); + ret_val += '.'; + } + ret_val += get_id()->get_dispname(); + return ret_val; + } + + Setting* Ref_simple::get_refd_setting() + { + if(get_is_erroneous()) return get_refd_setting_error(); + Assignment *ass = get_refd_assignment(); + if (ass) return ass->get_Setting(); + else return get_refd_setting_error(); + } + + Assignment* Ref_simple::get_refd_assignment(bool) + { + if (!refd_ass) { + if (!my_scope) FATAL_ERROR("Common::Ref_simple::get_refd_assignment()"); + refd_ass = my_scope->get_ass_bySRef(this); + } + return refd_ass; + } + + bool Ref_simple::has_single_expr() + { + return true; + } + + // ================================= + // ===== ReferenceChain + // ================================= + + ReferenceChain::ReferenceChain(const Location *p_loc, const char *p_str) + : my_loc(p_loc), err_str(p_str), report_error(true) + { + if(!p_loc) + FATAL_ERROR("ReferenceChain::ReferenceChain()"); + } + + ReferenceChain::~ReferenceChain() + { + reset(); + } + + ReferenceChain *ReferenceChain::clone() const + { + FATAL_ERROR("ReferenceChain::clone()"); + return 0; + } + + bool ReferenceChain::exists(const string& s) const + { + for (size_t i = 0; i < refs.size(); i++) + if (*refs[i]==s) return true; + return false; + } + + bool ReferenceChain::add(const string& s) + { + if (!exists(s)) { + refs.add(new string(s)); + return true; + } + + if (report_error) { + if (err_str) { + my_loc->error("%s: Circular reference: %s", err_str, + get_dispstr(s).c_str()); + } else { + my_loc->error("Circular reference: %s", get_dispstr(s).c_str()); + } + } else { + errors.add(get_dispstr(s)); + } + return false; + } + + void ReferenceChain::set_error_reporting(bool enable) { + report_error = enable; + } + + size_t ReferenceChain::nof_errors() const { + return errors.size() - (err_stack.empty() ? 0 : *err_stack.top()); + } + + void ReferenceChain::report_errors() + { + if (!err_stack.empty() && *err_stack.top() > errors.size()) + FATAL_ERROR("Common::ReferenceChain::report_errors()"); + + string err_msg; + if (err_str) { + err_msg += err_str; + err_msg += ": "; + } + + for (size_t i = (err_stack.empty() ? 0 : *err_stack.top()); + i < errors.size(); ++i) { + my_loc->error("%sCircular reference: %s", + err_msg.c_str(), errors[i].c_str()); + } + } + + void ReferenceChain::mark_error_state() + { + err_stack.push(new size_t(errors.size())); + } + + void ReferenceChain::prev_error_state() + { + if (err_stack.empty()) + FATAL_ERROR("Common::ReferenceChain::prev_error_state()"); + if (errors.size() < *err_stack.top()) + FATAL_ERROR("Common::ReferenceChain::prev_error_state()"); + + int state = static_cast(*err_stack.top()); + for (int i = static_cast(errors.size()) - 1; i >= state; --i) { + errors.remove(i); + } + delete err_stack.pop(); + } + + void ReferenceChain::mark_state() + { + refstack.push(new size_t(refs.size())); + } + + void ReferenceChain::prev_state() + { + if(refstack.empty()) + FATAL_ERROR("Common::ReferenceChain::prev_state()"); + size_t state=*refstack.top(); + if(refs.size() + +#include "error.h" +#include "string.hh" +#include "stack.hh" +#include "vector.hh" +#include "map.hh" + +/** YYLTYPE definition from compiler.tab.hh , used by Location class */ +#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED) +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + +struct expression_struct_t; + +namespace Ttcn { + // not defined here + class FieldOrArrayRef; + class FieldOrArrayRefs; + class ActualParList; + class RunsOnScope; + class StatementBlock; + struct ErroneousDescriptor; + class transparency_holder; +} // namespace Ttcn + +namespace Common { + + /** + * \addtogroup AST + * + * @{ + */ + + class Node; + class StringRepr; + class Setting; + class Governor; + class Governed; + class GovdSet; + + class Scope; + + class Reference; + class Ref_simple; + class ReferenceChain; + + // not defined here + class Identifier; + class Module; + class Assignment; + class Assignments; + class Type; + class Value; + + /** + * Base class for the AST-classes that have associated location + * (file name and line number) information. + * + * This class correctly uses the compiler-generated copy constructor + * and assignment operator, despite having a pointer member. + */ + class Location { + private: + /** map used as set containing one instance of all file names + * encountered during preprocessing. + * It is used as long term storage for the filename extracted from + * C preprocessor line markers (#line directives) */ + static map *source_file_names; + /** Source file name. + * Not owned by the Location object. Do not delete. + */ + const char *filename; + /** Source file location. + * Line and column for start and end (some of which may be zero) + */ + YYLTYPE yyloc; /* yyloc.first_line == lineno for backward compatibility */ + /** The location is inside a function with extension "transparent" */ + static bool transparency; + friend class Ttcn::transparency_holder; + public: + + /** adds new file name, returns pointer to stored file name, + * names are stored only once */ + static const char* add_source_file_name(const string& file_name); + static void delete_source_file_names(); + + /** Default constructor. + * Sets everything to 0/NULL. + */ + Location(); + + /** Constructor with filename and just a line number. + * Sets \c yyloc.first_line and \c yyloc.last_line to \p p_lineno, + * and the columns to zero. */ + Location(const char *p_filename, int p_lineno=0) + { set_location(p_filename, p_lineno); } + + /** Constructor with filename and full location information. + * Copies \p p_yyloc into \p yyloc. + */ + Location(const char *p_filename, const YYLTYPE& p_yyloc) + { set_location(p_filename, p_yyloc); } + + /** Constructor with filename and two location info. + * + * @param p_filename + * @param p_firstloc holds the location of the beginning. + * Its \p first_line and \p first_column are copied into + * \c yyloc.first_line and \c yyloc.first_column. + * @param p_lastloc contains the location of the end. + * Its \p last_line and \p last_column are copied into + * \c yyloc.last_line and \c yyloc.last_column. + */ + Location(const char *p_filename, const YYLTYPE& p_firstloc, + const YYLTYPE& p_lastloc) + { set_location(p_filename, p_firstloc, p_lastloc); } + + /** Constructor with filename and full location available separately. + * Stores the filename, and the line/column info in the appropriate + * members of \c yyloc. + */ + Location(const char *p_filename, int p_first_line, int p_first_column, + int p_last_line, int p_last_column) + { set_location(p_filename, p_first_line, p_first_column, + p_last_line, p_last_column); } + + /** Setter with filename and full location information. + * Copies \p p_yyloc into \p yyloc. + */ + void set_location(const char *p_filename, int p_lineno=0); + /** Setter with filename and full location information. + * Copies \p p_yyloc into \p yyloc. + */ + void set_location(const char *p_filename, const YYLTYPE& p_yyloc); + /** Setter with filename and two location info. + * + * @param p_filename + * @param p_firstloc holds the location of the beginning. + * Its \p first_line and \p first_column are copied into + * \c yyloc.first_line and \c yyloc.first_column. + * @param p_lastloc contains the location of the end. + * Its \p last_line and \p last_column are copied into + * \c yyloc.last_line and \c yyloc.last_column. + */ + void set_location(const char *p_filename, const YYLTYPE& p_firstloc, + const YYLTYPE& p_lastloc); + /** Setter with filename and full location available separately. + * Stores the filename, and the line/column info in the appropriate + * members of \c yyloc. + */ + void set_location(const char *p_filename, int p_first_line, + int p_first_column, int p_last_line, int p_last_column); + + /** Copies the stored location information from \a p. */ + void set_location(const Location& p) { *this = p; } + + /** Joins the coordinates of adjacent location \a p into this. */ + void join_location(const Location& p); + + /** Returns the attribute filename. */ + const char *get_filename() const { return filename; } + /** Returns the line number, for backward compatibility */ + int get_lineno() const { return yyloc.first_line; } + /** Returns the first line attribute */ + int get_first_line() const { return yyloc.first_line; } + /** Returns the last line attribute */ + int get_last_line() const { return yyloc.last_line; } + /** Returns the first column attribute */ + int get_first_column() const { return yyloc.first_column; } + /** Returns the last column attribute */ + int get_last_column() const { return yyloc.last_column; } + +private: + /** Prints the line/column information stored in \a this into file \a fp. + * Used by functions print_location() */ + void print_line_info(FILE *fp) const; +public: + /** Prints the contents of \a this into file \a fp. Used in error + * messages */ + void print_location(FILE *fp) const; + + /** Generic error reporting function with printf-like arguments. */ + void error(const char *fmt, ...) const + __attribute__ ((__format__ (__printf__, 2, 3))); + /** Generic warning function with printf-like arguments. */ + void warning(const char *fmt, ...) const + __attribute__ ((__format__ (__printf__, 2, 3))); + /** Generic note function with printf-like arguments. */ + void note(const char *fmt, ...) const + __attribute__ ((__format__ (__printf__, 2, 3))); + + /** Generates a C++ code fragment that instantiates a runtime location + * object containing the file name and source line information carried by + * \a this. The C++ code is appended to argument \a str and the resulting + * string is returned. Arguments \a entitytype and \a entityname determine + * the attributes of the location object based on the kind (FUNCTION, + * TESTCASE, etc.) and name of the corresponding TTCN-3 definition. + * The generation of location objects is optional, it is controlled by a + * command line switch. */ + char *create_location_object(char *str, const char *entitytype, + const char *entityname) const; + /** Generates a C++ code fragment that updates the line number information + * of the innermost runtime location object. The C++ code is appended to + * argument \a str and the resulting string is returned. The function is + * used by subsequent statements of statement blocks. */ + char *update_location_object(char *str) const; + }; + + /** + * Base class for AST-classes. + * + * The AST is an example of the Composite pattern ("Design Patterns", by + * Gamma et al.): it represents a part-whole hierarchy and allows clients + * to treat individual objects and compositions of objects uniformly. + * + * A container node "distributes" method calls to its subordinates: + * + * Common::Modules contains a collection of Asn/Ttcn::Module objects. + * Common::Modules::generate_code() calls Common::Module::generate_code() + * for each module that was parsed. Common::Module::generate_code() calls + * the virtual generate_code_internal(); for a TTCN-3 module this is + * Ttcn::Module::generate_code_internal(). + * + * A Ttcn::Module contains (among others) imports, definitions and (maybe) + * a control part. Consequently Ttcn::Module::generate_code_internal() calls + * Ttcn::Imports::generate_code(), then Ttcn::Definitions::generate_code(), + * then (maybe) Ttcn::ControlPart::generate_code(). + */ + class Node { + private: + /** To detect missing/duplicated invoking of destructor. */ + static int counter; +#ifdef MEMORY_DEBUG + /** Linked list for tracking undeleted nodes. */ + Node *prev_node, *next_node; +#endif + /** Name that contains information about the node's position in + * the AST. It is used when reporting things to the user. + * Guidelines for names can be found in X.680 clause 14. Main + * rules: components are separated by dot ("."). Absolute names + * begin with "@" followed by the module name. + */ + string fullname; + protected: // Setting needs access to the constructors + /** Default constructor. */ + Node(); + /** The copy constructor. */ + Node(const Node& p); + private: + /** Assignment disabled */ + Node& operator=(const Node& p); + public: + /** + * "Virtual constructor". + * + * In AST-classes, you should invoke the clone() member + * explicitly, instead of using the copy constructor. + * + * \note The clone is not an exact copy of the original object. + * Some information (like cached things, links to parent etc., if + * any) are not copied; they are updated when adding to parent + * node, checking the value etc. + */ + virtual Node* clone() const = 0; + /** The destructor. */ + virtual ~Node(); + /** Gives an error message if counter is not zero. It can be + * invoked before the program exits (like check_mem_leak()) to + * verify that all AST-objects are destroyed. */ + static void chk_counter(); + /** Sets the fullname. In the descendant classes, it sets also the + * fullname of the node's children, if any. */ + virtual void set_fullname(const string& p_fullname); + /** Gets the fullname. */ + const string& get_fullname() const { return fullname; } + virtual void set_my_scope(Scope *p_scope); + virtual void dump(unsigned level) const; + }; + + /** + * Class Setting. ObjectClass, Object, ObjectSet, Type, Value or + * ValueSet. + */ + class Setting : public Node, public Location { + public: + enum settingtype_t { + S_UNDEF, /**< Reference to non-existent stuff */ + S_ERROR, /**< Reference to non-existent stuff */ + S_OC, /**< ObjectClass */ + S_T, /**< Type */ + S_TEMPLATE, /**< Template */ + S_O, /**< Object */ + S_V, /**< Value */ + S_OS, /**< ObjectSet */ + S_VS /**< ValueSet */ + }; + protected: // Governed and Governor need access to members and copy c-tor + settingtype_t st; + Scope *my_scope; + string genname; + bool checked; + /** Indicates whether the circular references within embedded entities + * has been checked. For instance: a record/SEQUENCE type cannot contain + * itself as a mandatory field; a field in a value cannot refer to the + * value itself. */ + bool recurs_checked; + + Setting(const Setting& p) + : Node(p), Location(p), st(p.st), my_scope(0), + genname(), checked(false), recurs_checked(false) {} + private: + /** Assignment disabled */ + Setting& operator=(const Setting& p); + public: + Setting(settingtype_t p_st); + virtual Setting* clone() const = 0; + settingtype_t get_st() const { return st; } + virtual void set_my_scope(Scope *p_scope); + Scope *get_my_scope() const { return my_scope; } + /** Returns whether the setting was defined in ASN.1 module. */ + bool is_asn1() const; + /** Returns a unique temporary C++ identifier, which is obtained from + * the module scope. */ + string get_temporary_id() const; + /** Set \a genname from \p p_genname. + * + * @pre p_genname must not be empty. */ + void set_genname(const string& p_genname); + /** Set \a genname from two parts. + * + * Basically concatenates \p p_prefix, an underscore and \p p_suffix, + * unless p_prefix already ends with, or p_suffix already begins with + * \b precisely one underscore. + * + * @pre p_prefix must not be empty. + * @pre p_suffix must not be empty. */ + void set_genname(const string& p_prefix, const string& p_suffix); + public: + /** Returns a C++ reference that points to the C++ equivalent of this + * setting from the local module (when such entity exists) */ + const string& get_genname_own() const; + /** Returns a C++ reference that points to this setting from the module of + * scope \a p_scope */ + string get_genname_own(Scope *p_scope) const; + + private: + /** Creates and returns the string representation of the setting. */ + virtual string create_stringRepr(); + public: + /** Returns the string representation of the setting. Currently it calls + * \a create_stringRepr(), but it may use some caching in the future. */ + string get_stringRepr() { return create_stringRepr(); } + }; + + /** + * Ass_Error::get_Setting() returns this. + */ + class Setting_Error : public Setting { + private: + Setting_Error(const Setting_Error& p) : Setting(p) {} + public: + Setting_Error() : Setting(S_ERROR) {} + virtual Setting_Error* clone() const; + }; + + /** + * Things that can be the governor of something. + */ + class Governor : public Setting { + protected: // Derived classes need access to the copy c-tor + Governor(const Governor& p) : Setting(p) {} + public: + Governor(settingtype_t p_st) : Setting(p_st) {} + virtual Governor* clone() const =0; + virtual void chk() =0; + }; + + /** + * Things that have a governor. Object, Value... + */ + class Governed : public Setting { + protected: // Derived classes need access to the copy c-tor + Governed(const Governed& p) : Setting(p) {} + public: + Governed(settingtype_t p_st) : Setting(p_st) {} + virtual Governed* clone() const =0; + virtual Governor* get_my_governor() const =0; + }; + + /** + * A governed thing that will be mapped to a C++ entity. + * (e.g. Value, Template) + */ + class GovernedSimple : public Governed { + public: + enum code_section_t { + CS_UNKNOWN, /**< Unknown (i.e. not specified). */ + CS_PRE_INIT, /**< Initialized before processing the configuration file + * (i.e. module parameters are not known). Example: + * constants, default value for module parameters. */ + CS_POST_INIT, /**< Initialized after processing the configuration file + * (i.e. module parameters are known). Example: + * non-parameterized templates. */ + CS_INIT_COMP, /**< Initialized with the component entities (i.e. when + * the component type is known). Example: initial value + * for component variables, default duration for timers. */ + CS_INLINE /**< Initialized immediately at the place of definition. + * Applicable to local definitions only. Example: initial + * value for a local variable. */ + }; + private: + /** A prefix that shall be inserted before the genname when initializing + * the C++ object. Without this prefix the genname points to a read-only + * C++ object reference. For example, `const_c1' is a writable object with + * limited access (file static), but `c1' is a global const reference + * pointing to it. + * Possible values: "const_", "modulepar_", "template_". + */ + const char *genname_prefix; + /** Indicates the section of the output code where the initializer C++ + * sequence has to be put. If entity A refers to entity B and both has to + * be initialized in the same section, the initializer of B must precede + * the initializer of A. If the initializer of A and B has to be put into + * different sections the right order is provided automatically by the + * run-time environment. */ + code_section_t code_section; + /** A flag that indicates whether the initializer C++ code has been + * generated for the object (or object field). + */ + bool code_generated; + protected: // Derived classes need access to the copy c-tor + Ttcn::ErroneousDescriptor* err_descr; // not owned, used by negative testing + GovernedSimple(const GovernedSimple& p) : Governed(p), + genname_prefix(p.genname_prefix), code_section(p.code_section), + code_generated(false), err_descr(NULL), needs_conversion(false) { } + bool needs_conversion; /**< Type conversion needed. */ + private: + /** Assignment disabled */ + GovernedSimple& operator=(const GovernedSimple& p); + public: + GovernedSimple(settingtype_t p_st) : Governed(p_st), genname_prefix(0), + code_section(CS_UNKNOWN), code_generated(false), err_descr(NULL), + needs_conversion(false) { } + + /** Sets attribute \a genname_prefix to \a p_genname_prefix. For efficiency + * reasons the string itself is not copied, thus it must point to a + * permanent memory area. */ + void set_genname_prefix(const char *p_genname_prefix) + { genname_prefix = p_genname_prefix; } + /** Returns attribute \a genname_prefix. */ + const char *get_genname_prefix() const { return genname_prefix; } + + /** Returns the attribute \a code_section. */ + code_section_t get_code_section() const { return code_section; } + /** Sets the attribute \a code_section to \a p_code_section. */ + void set_code_section(code_section_t p_code_section) + { code_section = p_code_section; } + + /** Returns the flag \a code_generated. */ + bool get_code_generated() const { return code_generated; } + /** Sets the flag \a code_generated to true. */ + void set_code_generated() { code_generated = true; } + + /** Sets the err_descr if the template or value has negative testing */ + void set_err_descr(Ttcn::ErroneousDescriptor* p_err_descr) + { err_descr = p_err_descr; } + Ttcn::ErroneousDescriptor* get_err_descr() const + { return err_descr; } + + /** has_single_expr() to return false. */ + inline void set_needs_conversion() { needs_conversion = true; } + inline bool get_needs_conversion() const { return needs_conversion; } + + /** Returns the C++ expression that refers to the object, which has to be + * initialized. */ + string get_lhs_name() const; + + /** Returns whether the C++ initialization sequence of \a refd must be + * inserted before the initialization sequence of \a this. The function is + * used when \a this refers to \a refd. + * It returns true if all the following conditions apply: + * 1) Code has not been generated for \a refd. + * 2) Both \a this and \a refd are defined in the same module. + * 3) The initialization sequence for both shall be placed into the same + * code section. */ + bool needs_init_precede(const GovernedSimple *refd) const; + /** Returns whether the entity is a top-level one (i.e. it is not embedded + * into another entity). The function examines whether the genname is a + * single identifier or not. */ + bool is_toplevel() const; + }; + + /** + * A set of governed stuff. ObjectSet or ValueSet. + */ + class GovdSet : public Governed { + protected: // Asn::ObjectSet needs access + GovdSet(const GovdSet& p) : Governed(p) {} + public: + GovdSet(settingtype_t p_st) : Governed(p_st) {} + virtual GovdSet* clone() const =0; + }; + + /** + * An interface-class to represent scopes of references. A scope + * is an entity from which assignments can be seen; each of these + * assignments can be referred by a Reference. + */ + class Scope : public Node { + protected: // Several derived classes need access + /** Link to the parent in the scope hierarchy. Can be 0 + * (root-node, in case of the Module scope). */ + Scope *parent_scope; + /** Some special kind of parent. Used only in conjunction with + * ASN.1 parameterized references. */ + Scope *parent_scope_gen; + + /** The name of the scope. */ + string scope_name; + + /** The name of the scope + * as it should be reported by the __SCOPE__ macro. */ + string scopeMacro_name; + + Scope(const Scope& p) + : Node(p), parent_scope(0), parent_scope_gen(0), scope_name(), + scopeMacro_name() {} + private: + /** Assignment disabled */ + Scope& operator=(const Scope& p); + public: + Scope() : Node(), parent_scope(0), parent_scope_gen(0), scope_name(), + scopeMacro_name() {} + + /** Sets the parent_scope to the given value. */ + void set_parent_scope(Scope *p_parent_scope) + { parent_scope = p_parent_scope; } + /** Sets some othe parent scope. + * Only called from Ref_pard::get_ref_defd_simple */ + void set_parent_scope_gen(Scope *p_parent_scope_gen) + { parent_scope_gen = p_parent_scope_gen; } + /** Returns the parent_scope or NULL. */ + Scope *get_parent_scope() const { return parent_scope; } + /** Sets the name of the scope. */ + void set_scope_name(const string& p_scope_name) + { scope_name = p_scope_name; } + /** Gets the full-qualified name of the scope. */ + string get_scope_name() const; + /** Sets the name of the scope. */ + void set_scopeMacro_name(const string& p_scopeMacro_name) + { scopeMacro_name = p_scopeMacro_name; } + /** Gets the full-qualified name of the scope. */ + virtual string get_scopeMacro_name() const; + /** Returns the closest statementblock unit of the hierarchy, or null if the actual scope is not within a + * statementblock scope. */ + virtual Ttcn::StatementBlock *get_statementblock_scope(); + /** Returns the scope unit of the hierarchy that belongs to a + * 'runs on' clause. */ + virtual Ttcn::RunsOnScope *get_scope_runs_on(); + /** Returns the assignments/module definitions scope. */ + virtual Assignments *get_scope_asss(); + /** Gets the module scope. This function returns this scope or a + * scope above this or executes FATAL_ERROR if neither is a + * Module. */ + virtual Module* get_scope_mod(); + virtual Module* get_scope_mod_gen(); + /** Returns the assignment referenced by \a p_ref. If no such + * node, 0 is returned. */ + virtual Assignment* get_ass_bySRef(Ref_simple *p_ref) =0; + /** Returns whether the current scope (or its parent) has an + * assignment with the given \a p_id. Imported symbols are not + * searched. */ + 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); + /** 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 + * "activate". */ + void chk_runs_on_clause(Assignment *p_ass, const Location& p_loc, + const char *p_what); + /** Checks the 'runs on' clause of type \a p_fat that the values of it can + * be called from this scope unit. Type \a p_fat shall be of type function + * or altstep. Parameters \a p_loc and \a p_what are used in error messages. + * \a p_what contains "call" or "activate". */ + void chk_runs_on_clause(Type *p_fat, const Location& p_loc, + const char *p_what); + }; + + /** + * A Reference refers to a Setting. + */ + class Reference : public Node, public Location { + protected: // Derived classes need access + Scope *my_scope; + bool is_erroneous; + static size_t _Reference_counter; + static Setting_Error *setting_error; + + Reference() : Node(), Location(), my_scope(0), is_erroneous(false) + { _Reference_counter++; } + Reference(const Reference& p) : Node(p), Location(p), my_scope(0), + is_erroneous(p.is_erroneous) { _Reference_counter++; } + private: + /** Assignment disabled */ + Reference& operator=(const Reference& p); + public: + virtual ~Reference(); + virtual Reference* clone() const =0; + /** Creates a display-name for the reference. */ + virtual string get_dispname() =0; + virtual void set_my_scope(Scope *p_scope); + Scope *get_my_scope() const { return my_scope; } + virtual bool get_is_erroneous(); + /** Returns the referenced stuff. Returns NULL if the referenced + * stuff does not exists. */ + virtual Setting* get_refd_setting() =0; + virtual Setting* get_refd_setting_error(); + /** Returns the referred TTCN-3 definition or ASN.1 assignment. + * If the referenced definition is not found NULL is returned after + * reporting the error. The function ignores the TTCN-3 field or array + * sub-references. Flag \a check_parlist indicates whether to verify the + * actual parameter list of the TTCN-3 reference against the formal + * parameter list of the referred definition. The parameter checking is + * done by default, but it can be disabled in certain cases. */ + virtual Assignment* get_refd_assignment(bool check_parlist = true) = 0; + /** Returns the field or array subreferences of TTCN-3 references or NULL + * otherwise. */ + virtual Ttcn::FieldOrArrayRefs *get_subrefs(); + /** Returns the actual parameter list for parameterized TTCN-3 references + * or NULL otherwise. */ + virtual Ttcn::ActualParList *get_parlist(); + /** True if this reference refers to a settingtype \a p_st. */ + virtual bool refers_to_st(Setting::settingtype_t p_st, + ReferenceChain* refch=0); + virtual bool getUsedInIsbound() {return false;} + virtual void setUsedInIsbound() {} + /** Returns whether the reference can be represented by an in-line C++ + * expression. */ + virtual bool has_single_expr() = 0; + /** Sets the code section of embedded values (parameters, array indices). */ + virtual void set_code_section( + GovernedSimple::code_section_t p_code_section); + /** Generates the C++ equivalent of the reference (including the parameter + * list and sub-references). */ + virtual void generate_code(expression_struct_t *expr) = 0; + virtual void generate_code_const_ref(expression_struct_t *expr) = 0; + virtual void dump(unsigned level) const; + }; + + /** + * Interface-class to refer to entities. %Common entities which can + * be referred are: modules, types and values. Each simple + * reference is formed by one or two identifiers. An optional + * identifier identifies the module (modid), and another + * the entity within that module (id). The \a modid is + * optional; if present, then the reference is \a global. If not + * present, then the identifier must be seen from the Reference's + * Scope or one of its parent-scopes not higher (in the + * scope-hierarchy) than a Module. + */ + class Ref_simple : public Reference { + protected: // Derived classes need access + /** Points to the referred assignment. Used for caching. */ + Assignment *refd_ass; + Ref_simple() : Reference(), refd_ass(0) {} + Ref_simple(const Ref_simple& p) : Reference(p), refd_ass(0) {} + private: + /** Assignment disabled */ + Ref_simple& operator=(const Ref_simple& p); + public: + virtual Reference* clone() const =0; + /** Returns the \a modid, or 0 if not present. */ + virtual const Identifier* get_modid() =0; + /** Returns the \a id. */ + virtual const Identifier* get_id() =0; + /** Creates a display-name for the reference. */ + virtual string get_dispname(); + virtual Setting* get_refd_setting(); + /** \param check_parlist is ignored */ + virtual Assignment* get_refd_assignment(bool check_parlist = true); + /** Always returns true */ + virtual bool has_single_expr(); + }; + + /** + * Auxiliary class to detect circular references. Stores strings + * (e.g., the display-name of the references). When adding a string, + * checks whether it already exists. If exists, throws an + * Error_AST_uniq with the full chain in the description. + * + * @note ReferenceChains should not be reused without calling reset(). + * It's even better not to reuse them at all. + */ + class ReferenceChain : public Node { + private: + /** Stores the strings representing references. */ + vector refs; + /** Stores a history of the length of the reference chain. + * Used by mark_state() and prev_state(). */ + stack refstack; + const Location *my_loc; + /** Operation being performed (for error reporting) */ + const char* err_str; + dynamic_array errors; + /** Used to mark states of the errors array. */ + stack err_stack; + /** If report_error is true, the errors will be reported + * automatically. Otherwise the string representation + * of the errors will be stored in the errors array.*/ + bool report_error; + private: + /** Copy constructor disabled */ + ReferenceChain(const ReferenceChain& p); + /** Assignment disabled */ + ReferenceChain& operator=(const ReferenceChain& p); + public: + /** Constructor. + * + * @param p_loc + * @param p_str string describing the operation being performed + */ + ReferenceChain(const Location *p_loc, const char *p_str=0); + /** Destructor. Calls reset(). */ + virtual ~ReferenceChain(); + /** "Virtual constructor"; calls FATAL_ERROR() */ + virtual ReferenceChain* clone() const; + /** Returns whether the chain contains string \a s. */ + bool exists(const string& s) const; + /** Adds a new string. Returns true on success or false if \a s already + * exists on chain. */ + bool add(const string& s); + /** Turns on or off the automatic error reporting. */ + void set_error_reporting(bool enable); + /** Returns the number of errors found after the last + * marked state (mark_error_state())*/ + size_t nof_errors() const; + /** Marks the current state in the errors array. prev_error_state() + * can be used to restore this state.*/ + void mark_error_state(); + void prev_error_state(); + /** Reports all the errors found after the last mark_error_state() call. */ + void report_errors(); + /** Marks the current state, so later prev_state() can restore + * this state. Useful in recursive checks. + * It stores the length of the reference chain in \p refstack. */ + void mark_state(); + /** Restores the reference chain to the last saved state. + * Pops a stored size from \p refstack and truncates the chain + * to that size (the chain can never be shorter than the saved size). */ + void prev_state(); + /** Cleans the references and the stored sizes. */ + void reset(); + /** Gives a string like this: "`ref1' -> `ref2' -> `ref3' -> `ref1'". + * It uses the contents of \a refs starting with the first occurrence + * of string \a s. Finally it appends \a s to close the loop. */ + string get_dispstr(const string& s) const; + }; + + /** @} end of AST group */ + +} // namespace Common + +#endif // _Common_Setting_HH diff --git a/compiler2/SigParam.cc b/compiler2/SigParam.cc new file mode 100644 index 0000000..739edff --- /dev/null +++ b/compiler2/SigParam.cc @@ -0,0 +1,267 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "SigParam.hh" + +#include "Type.hh" +#include "CompilerError.hh" + +namespace Common { + +// ================================= +// ===== SignatureParam +// ================================= + +SignatureParam::SignatureParam(param_direction_t p_d, Type *p_t, + Identifier *p_i) + : param_direction(p_d), param_type(p_t), param_id(p_i) +{ + if (!p_t || !p_i) FATAL_ERROR("SignatureParam::SignatureParam()"); + param_type->set_ownertype(Type::OT_SIG_PAR, this); +} + +SignatureParam::~SignatureParam() +{ + delete param_type; + delete param_id; +} + +SignatureParam *SignatureParam::clone() const +{ + FATAL_ERROR("SignatureParam::clone"); +} + +void SignatureParam::set_fullname(const string& p_fullname) +{ + Node::set_fullname(p_fullname); + param_type->set_fullname(p_fullname); +} + +void SignatureParam::set_my_scope(Scope *p_scope) +{ + param_type->set_my_scope(p_scope); +} + +void SignatureParam::dump(unsigned level) const +{ + switch(param_direction) { + case PARAM_IN: DEBUG(level,"in"); break; + case PARAM_OUT: DEBUG(level,"out"); break; + case PARAM_INOUT: DEBUG(level,"inout");break; + default: FATAL_ERROR("SignatureParam::dump()"); break; + } + param_type->dump(level+1); + param_id->dump(level+2); +} + +// ================================= +// ===== SignatureParamList +// ================================= + +SignatureParamList::~SignatureParamList() +{ + for (size_t i = 0; i < params_v.size(); i++) delete params_v[i]; + params_v.clear(); + params_m.clear(); + in_params_v.clear(); + out_params_v.clear(); +} + +SignatureParamList *SignatureParamList::clone() const +{ + FATAL_ERROR("SignatureParam::clone"); +} + +void SignatureParamList::set_fullname(const string& p_fullname) +{ + Node::set_fullname(p_fullname); + for (size_t i = 0; i < params_v.size(); i++) { + SignatureParam *param = params_v[i]; + param->set_fullname(p_fullname + "." + param->get_id().get_dispname()); + } +} + +void SignatureParamList::set_my_scope(Scope *p_scope) +{ + for (size_t i = 0; i < params_v.size(); i++) + params_v[i]->set_my_scope(p_scope); +} + +void SignatureParamList::add_param(SignatureParam *p_param) +{ + if (!p_param || checked) FATAL_ERROR("SignatureParamList::add_param()"); + params_v.add(p_param); +} + +size_t SignatureParamList::get_nof_in_params() const +{ + if (!checked) FATAL_ERROR("SignatureParamList::get_nof_in_params()"); + return in_params_v.size(); +} + +SignatureParam *SignatureParamList::get_in_param_byIndex(size_t n) const +{ + if (!checked) FATAL_ERROR("SignatureParamList::get_in_param_byIndex()"); + return in_params_v[n]; +} + +size_t SignatureParamList::get_nof_out_params() const +{ + if (!checked) FATAL_ERROR("SignatureParamList::get_nof_out_params()"); + return out_params_v.size(); +} + +SignatureParam *SignatureParamList::get_out_param_byIndex(size_t n) const +{ + if (!checked) FATAL_ERROR("SignatureParamList::get_out_param_byIndex()"); + return out_params_v[n]; +} + +bool SignatureParamList::has_param_withName(const Identifier& p_name) const +{ + if (!checked) FATAL_ERROR("SignatureParamList::has_param_withName()"); + return params_m.has_key(p_name.get_name()); +} + +const SignatureParam *SignatureParamList::get_param_byName + (const Identifier& p_name) const +{ + if (!checked) FATAL_ERROR("SignatureParamList::get_param_byName()"); + return params_m[p_name.get_name()]; +} + +void SignatureParamList::chk(Type *p_signature) +{ + if (checked) return; + checked = true; + for (size_t i = 0; i < params_v.size(); i++) { + SignatureParam *param = params_v[i]; + const Identifier& id = param->get_id(); + const string& name = id.get_name(); + const char *dispname_str = id.get_dispname().c_str(); + if (params_m.has_key(name)) { + param->error("Duplicate parameter identifier: `%s'", dispname_str); + params_m[name]->note("Parameter `%s' is already defined here", + dispname_str); + } else params_m.add(name, param); + Error_Context cntxt(param, "In parameter `%s'", dispname_str); + bool is_nonblock = p_signature->is_nonblocking_signature(); + switch (param->get_direction()) { + case SignatureParam::PARAM_IN: + in_params_v.add(param); + break; + case SignatureParam::PARAM_OUT: + if (is_nonblock) param->error("A non-blocking signature cannot have " + "`out' parameter"); + out_params_v.add(param); + break; + case SignatureParam::PARAM_INOUT: + if (is_nonblock) param->error("A non-blocking signature cannot have " + "`inout' parameter"); + in_params_v.add(param); + out_params_v.add(param); + break; + default: + FATAL_ERROR("SignatureParamList::chk()"); + } + Type *param_type = param->get_type(); + param_type->set_genname(p_signature->get_genname_own(), name); + param_type->set_parent_type(p_signature); + param_type->chk(); + param_type->chk_embedded(false, "the type of a signature parameter"); + } +} + +void SignatureParamList::dump(unsigned level) const +{ + for (size_t i = 0; i < params_v.size(); i++) params_v[i]->dump(level); +} + +// ================================= +// ===== SignatureExceptions +// ================================= + +SignatureExceptions::~SignatureExceptions() +{ + for (size_t i = 0; i < exc_v.size(); i++) delete exc_v[i]; + exc_v.clear(); + exc_m.clear(); +} + +SignatureExceptions *SignatureExceptions::clone() const +{ + FATAL_ERROR("SignatureExceptions::clone"); +} + +void SignatureExceptions::add_type(Type *p_type) +{ + if (!p_type) FATAL_ERROR("SignatureExceptions::add_type()"); + exc_v.add(p_type); +} + +bool SignatureExceptions::has_type(Type *p_type) +{ + if (!p_type) FATAL_ERROR("SignatureExceptions::has_type()"); + if (p_type->get_type_refd_last()->get_typetype() == Type::T_ERROR) + return true; + else return exc_m.has_key(p_type->get_typename()); +} + +size_t SignatureExceptions::get_nof_compatible_types(Type *p_type) +{ + if (!p_type) FATAL_ERROR("SignatureExceptions::get_nof_compatible_types()"); + if (p_type->get_type_refd_last()->get_typetype() == Type::T_ERROR) { + // Return a positive answer for erroneous types. + return 1; + } else { + size_t ret_val = 0; + for (size_t i = 0; i < exc_v.size(); i++) + // Don't allow type compatibility. The types must match exactly. + if (exc_v[i]->is_compatible(p_type, NULL)) + ret_val++; + return ret_val; + } +} + +void SignatureExceptions::chk(Type *p_signature) +{ + Error_Context cntxt(this, "In exception list"); + for (size_t i = 0; i < exc_v.size(); i++) { + Type *type = exc_v[i]; + type->set_genname(p_signature->get_genname_own(), Int2string(i + 1)); + type->set_parent_type(p_signature); + type->chk(); + if (type->get_typetype() == Type::T_ERROR) continue; + type->chk_embedded(false, "on the exception list of a signature"); + const string& type_name = type->get_typename(); + if (exc_m.has_key(type_name)) { + type->error("Duplicate type in exception list"); + exc_m[type_name]->note("Type `%s' is already given here", + type_name.c_str()); + } else exc_m.add(type_name, type); + } +} + +void SignatureExceptions::set_fullname(const string& p_fullname) +{ + Node::set_fullname(p_fullname); + for (size_t i = 0; i < exc_v.size(); i++) + exc_v[i]->set_fullname(p_fullname + "."); +} + +void SignatureExceptions::set_my_scope(Scope *p_scope) +{ + for (size_t i = 0; i < exc_v.size(); i++) + exc_v[i]->set_my_scope(p_scope); +} + +void SignatureExceptions::dump(unsigned level) const +{ + for (size_t i=0; i < exc_v.size(); i++) exc_v[i]->dump(level); +} + +} /* namespace Common */ diff --git a/compiler2/SigParam.hh b/compiler2/SigParam.hh new file mode 100644 index 0000000..c32592c --- /dev/null +++ b/compiler2/SigParam.hh @@ -0,0 +1,111 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef SIGPARAM_HH_ +#define SIGPARAM_HH_ + +#include "Setting.hh" + +namespace Common { + +/** + * Signature parameter + */ +class SignatureParam : public Node, public Location { +public: + enum param_direction_t { PARAM_IN, PARAM_OUT, PARAM_INOUT }; +private: + param_direction_t param_direction; + Type *param_type; + Identifier *param_id; + /** Copy constructor not implemented */ + SignatureParam(const SignatureParam& p); + /** Assignment disabled */ + SignatureParam& operator=(const SignatureParam& p); +public: + SignatureParam(param_direction_t p_d, Type *p_t, Identifier *p_i); + ~SignatureParam(); + virtual SignatureParam *clone() const; + const Identifier& get_id() const { return *param_id; } + Type *get_type() const { return param_type; } + param_direction_t get_direction() const { return param_direction; } + virtual void set_fullname(const string& p_fullname); + virtual void set_my_scope(Scope *p_scope); + virtual void dump(unsigned level) const; +}; + +/** + * Signature parameter-list + */ +class SignatureParamList : public Node { + vector params_v; + map params_m; + vector in_params_v, out_params_v; + bool checked; +private: + /** Copy constructor not implemented */ + SignatureParamList(const SignatureParamList& p); + /** Assignment disabled */ + SignatureParamList& operator=(const SignatureParamList& p); +public: + SignatureParamList() + : Node(), params_v(), params_m(), in_params_v(), out_params_v(), + checked(false) { } + ~SignatureParamList(); + virtual SignatureParamList *clone() const; + virtual void set_fullname(const string& p_fullname); + virtual void set_my_scope(Scope *p_scope); + void add_param(SignatureParam *p_param); + size_t get_nof_params() const { return params_v.size(); } + SignatureParam *get_param_byIndex(size_t n) const { return params_v[n]; } + /** Returns the number of in/inout parameters. */ + size_t get_nof_in_params() const; + /** Returns the n-th in/inout parameter. */ + SignatureParam *get_in_param_byIndex(size_t n) const; + /** Returns the number of out/inout parameters. */ + size_t get_nof_out_params() const; + /** Returns the n-th out/inout parameter. */ + SignatureParam *get_out_param_byIndex(size_t n) const; + bool has_param_withName(const Identifier& p_name) const; + const SignatureParam *get_param_byName(const Identifier& p_name) const; + + void chk(Type *p_signature); + virtual void dump(unsigned level) const; +}; + +/** + * Signature exception-list + */ +class SignatureExceptions : public Node, public Location { + vector exc_v; + map exc_m; +private: + /** Copy constructor not implemented */ + SignatureExceptions(const SignatureExceptions& p); + /** Assignment disabled */ + SignatureExceptions& operator=(const SignatureExceptions& p); +public: + SignatureExceptions() : Node(), Location(), exc_v(), exc_m() { } + ~SignatureExceptions(); + SignatureExceptions *clone() const; + void add_type(Type *p_type); + size_t get_nof_types() const { return exc_v.size(); } + Type *get_type_byIndex(size_t n) const { return exc_v[n]; } + bool has_type(Type *p_type); + /** Returns the number of types that are compatible with * \a p_type. */ + size_t get_nof_compatible_types(Type *p_type); + Type *get_type_byName(const string& p_typename) const + { return exc_m[p_typename]; } + + void chk(Type *p_signature); + virtual void set_fullname(const string& p_fullname); + virtual void set_my_scope(Scope *p_scope); + virtual void dump(unsigned level) const; +}; + +} /* namespace Common */ +#endif /* SIGPARAM_HH_ */ diff --git a/compiler2/Stopwatch.cc b/compiler2/Stopwatch.cc new file mode 100644 index 0000000..7495079 --- /dev/null +++ b/compiler2/Stopwatch.cc @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "Stopwatch.hh" +#include "error.h" +#include + +Stopwatch::Stopwatch(const char *name) +: tv_start() +, my_name(name) +{ + gettimeofday(&tv_start, 0); +} + +Stopwatch::~Stopwatch() +{ + struct timeval tv_end; + gettimeofday(&tv_end, 0); + + struct timeval tv_diff = { + tv_end.tv_sec - tv_start.tv_sec, + tv_end.tv_usec - tv_start.tv_usec + }; + if (tv_diff.tv_usec < 0) { + --tv_diff.tv_sec; + tv_diff.tv_usec += 1000000; + } + + NOTIFY("%s took %ld.%06ld sec", my_name, + (long)tv_diff.tv_sec, (long)tv_diff.tv_usec); +} diff --git a/compiler2/Stopwatch.hh b/compiler2/Stopwatch.hh new file mode 100644 index 0000000..8fcbdfb --- /dev/null +++ b/compiler2/Stopwatch.hh @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef STOPWATCH_HH_ +#define STOPWATCH_HH_ + +#include + +class Stopwatch { +public: + Stopwatch(const char *name); + ~Stopwatch(); +private: + struct timeval tv_start; + const char *my_name; // not owned +private: + Stopwatch(const Stopwatch&); // no copy + Stopwatch& operator=(const Stopwatch&); // no assignment +}; + +#ifdef NDEBUG +#define STOPWATCH(s) ((void)(s)) +#else +#define STOPWATCH(s) Stopwatch chrono_meter(s) +#endif + +#endif /* STOPWATCH_HH_ */ diff --git a/compiler2/Type.cc b/compiler2/Type.cc new file mode 100644 index 0000000..2f59ba7 --- /dev/null +++ b/compiler2/Type.cc @@ -0,0 +1,6836 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "../common/dbgnew.hh" +#include "Type.hh" +#include +#include "Typestuff.hh" // FIXME CTs +#include "CompType.hh" +#include "TypeCompat.hh" +#include "CompField.hh" +#include "SigParam.hh" +#include "EnumItem.hh" + +#include "Valuestuff.hh" +#include "ttcn3/ArrayDimensions.hh" +#include "asn1/Tag.hh" +#include "asn1/Block.hh" +#include "asn1/Ref.hh" +#include "Constraint.hh" +#include "main.hh" +#include "../common/pattern.hh" +#include "ttcn3/Attributes.hh" +#include "XerAttributes.hh" +#include "ttcn3/Ttcnstuff.hh" +#include "ttcn3/TtcnTemplate.hh" +#include "ttcn3/Templatestuff.hh" + +#include "../common/static_check.h" +#include "PredefFunc.hh" + +// implemented in coding_attrib_p.y +extern Ttcn::ExtensionAttributes * parse_extattributes( + Ttcn::WithAttribPath *w_attrib_path); + +namespace Common { + + using Ttcn::MultiWithAttrib; + using Ttcn::SingleWithAttrib; + using Ttcn::WithAttribPath; + + const char* Type::type_as_string[] = { + "undefined", // T_UNDEF + "erroneous", // T_ERROR + "null(ASN)", // T_NULL + "boolean", // T_BOOL + "integer", // T_INT + "integer(ASN.1)", // T_INT_A + "real/float", // T_REAL + "enumerated(ASN.1)", // T_ENUM_A + "enumerated(TTCN-3)", // T_ENUM_T + "bitstring", // T_BSTR + "bitstring(ASN)", // T_BSTR_A + "hexstring(TTCN-3)", // T_HSTR + "octetstring", // T_OSTR + "charstring (TTCN-3)", // T_CSTR + "universal charstring(TTCN-3)", // T_USTR + "UTF8String(ASN.1)", // T_UTF8STRING + "NumericString(ASN.1)", // T_NUMERICSTRING + "PrintableString(ASN.1)", // T_PRINTABLESTRING + "TeletexString(ASN.1)", //T_TELETEXSTRING + "VideotexString(ASN.1)", // T_VIDEOTEXSTRING + "IA5String(ASN.1)", // T_IA5STRING + "GraphicString(ASN.1)", // T_GRAPHICSTRING, + "VisibleString(ASN.1)", // T_VISIBLESTRING + "GeneralString (ASN.1)", // T_GENERALSTRING + "UniversalString (ASN.1)", // T_UNIVERSALSTRING + "BMPString (ASN.1)", // T_BMPSTRING + "UnrestrictedCharacterString(ASN.1)", // T_UNRESTRICTEDSTRING + "UTCTime(ASN.1)", // T_UTCTIME + "GeneralizedTime(ASN.1)", // T_GENERALIZEDTIME + "Object descriptor, a kind of string (ASN.1)", // T_OBJECTDESCRIPTOR + "object identifier", // T_OID + "relative OID(ASN.1)", // T_ROID + "choice(ASN-1)", // T_CHOICE_A + "union(TTCN-3)", // T_CHOICE_T + "sequence (record) of", // T_SEQOF + "set of", // T_SETOF + "sequence(ASN-1)", // T_SEQ_A + "record(TTCN-3)", // T_SEQ_T + "set(ASN.1)", // T_SET_A + "set(TTCN-3)", // T_SET_T + "ObjectClassFieldType(ASN.1)", // T_OCFT + "open type(ASN.1)", // T_OPENTYPE + "ANY(deprecated ASN.1)", // T_ANY + "external(ASN.1)", // T_EXTERNAL + "embedded PDV(ASN.1)", // T_EMBEDDED_PDV + "referenced", // T_REFD + "special referenced(by pointer, not by name)", // T_REFDSPEC + "selection type(ASN.1)", // T_SELTYPE + "verdict type(TTCN-3)", // T_VERDICT + "port type(TTCN-3)", // T_PORT + "component type(TTCN-3)", // T_COMPONENT + "address type(TTCN-3)", // T_ADDRESS + "default type (TTCN-3)", // T_DEFAULT + "array(TTCN-3)", // T_ARRAY + "signature(TTCN-3)", // T_SIGNATURE + "function reference(TTCN-3)", // T_FUNCTION + "altstep reference(TTCN-3)", // T_ALTSTEP + "testcase reference(TTCN-3)", // T_TESTCASE + "anytype(TTCN-3)", // T_ANYTYPE + }; + + // ================================= + // ===== Type + // ================================= + const char* Type::asString() const { + if (this->get_typetype() < Type::T_LAST && Type::T_UNDEF < this->get_typetype()) { + return type_as_string[this->get_typetype()]; + } + else { + return type_as_string[Type::T_UNDEF]; + } + } + + const char* Type::asString(Type::typetype_t type) { + if (type < Type::T_LAST && Type::T_UNDEF < type) { + return type_as_string[type]; + } + else { + return type_as_string[Type::T_UNDEF]; + } + } + + // Used by dump() for user-readable messages, by Def_ExtFunction::generate_* + // The text returned must match the case label without the "CT_" ! + const char *Type::get_encoding_name(MessageEncodingType_t encoding_type) + { + ENSURE_EQUAL(Type::T_UNDEF, 0); + ENSURE_EQUAL(Type::OT_UNKNOWN, 0); + switch (encoding_type) { + case CT_BER: + return "BER"; + case CT_PER: + return "PER"; + case CT_XER: + return "XER"; + case CT_RAW: + return "RAW"; + case CT_TEXT: + return "TEXT"; + case CT_JSON: + return "JSON"; + default: + return ""; + } + } + + Type *Type::get_stream_type(MessageEncodingType_t encoding_type) + { + switch (encoding_type) { + case CT_BER: + case CT_PER: + case CT_RAW: + case CT_XER: // UTF-8 doesn't fit into charstring and universal is wasteful + case CT_JSON: + return get_pooltype(T_OSTR); + case CT_TEXT: + return get_pooltype(T_CSTR); + default: + FATAL_ERROR("Type::get_stream_type()"); + return 0; + } + } + + map *Type::pooltypes = 0; + + Type* Type::get_pooltype(typetype_t p_typetype) + { + p_typetype=get_typetype_ttcn3(p_typetype); + switch(p_typetype) { + case T_NULL: + case T_BOOL: + case T_INT: + case T_REAL: + case T_BSTR: + case T_HSTR: + case T_OSTR: + case T_CSTR: + case T_USTR: + case T_OID: + case T_ERROR: + case T_VERDICT: + case T_COMPONENT: + case T_DEFAULT: + break; // we have a pool type + default: + return 0; // no pool type for you! + } // switch + if (!pooltypes) pooltypes = new map; // lazy init + else if (pooltypes->has_key(p_typetype)) return (*pooltypes)[p_typetype]; + Type *t; + if (p_typetype == T_COMPONENT) + t = new Type(T_COMPONENT, new ComponentTypeBody()); + else t = new Type(p_typetype); + t->ownertype = OT_POOL; + pooltypes->add(p_typetype, t); + return t; + } + + void Type::destroy_pooltypes() + { + if(pooltypes) { + for(size_t i=0; isize(); i++) + delete pooltypes->get_nth_elem(i); + pooltypes->clear(); + delete pooltypes; + pooltypes=0; + } + } + + Tag *Type::get_default_tag() + { + typetype_t t_typetype; + switch (typetype) { + case T_INT: + t_typetype = T_INT_A; + break; + case T_BSTR: + t_typetype = T_BSTR_A; + break; + case T_ENUM_T: + t_typetype = T_ENUM_A; + break; + case T_SEQ_T: + case T_SEQOF: + t_typetype = T_SEQ_A; + break; + case T_SET_T: + case T_SETOF: + t_typetype = T_SET_A; + break; + case T_OPENTYPE: + t_typetype = T_ANY; + break; + case T_REFD: + case T_REFDSPEC: + case T_SELTYPE: + case T_OCFT: + return get_type_refd()->get_tag(); + default: + t_typetype = typetype; + break; + } + if (!default_tags) default_tags = new map; + else if (default_tags->has_key(t_typetype)) + return (*default_tags)[t_typetype]; + Tag *tag; + switch (t_typetype) { + case T_ANY: + tag = new Tag(Tag::TAG_EXPLICIT, Tag::TAG_ALL, (Int)0); + break; + case T_ERROR: + tag = new Tag(Tag::TAG_EXPLICIT, Tag::TAG_ERROR, (Int)0); + break; + default: { + int tagnumber = get_default_tagnumber(t_typetype); + if (tagnumber < 0) FATAL_ERROR ("Type::get_default_tag():type `%s' " + "does not have default tag", get_typename().c_str()); + tag = new Tag(Tag::TAG_EXPLICIT, Tag::TAG_UNIVERSAL, Int(tagnumber)); + break; } + } + default_tags->add(t_typetype, tag); + return tag; + } + + int Type::get_default_tagnumber(typetype_t p_tt) + { + switch (p_tt) { + // note: tag number 0 is reserved for internal use + case T_BOOL: + return 1; + case T_INT_A: + return 2; + case T_BSTR_A: + return 3; + case T_OSTR: + return 4; + case T_NULL: + return 5; + case T_OID: + return 6; + case T_OBJECTDESCRIPTOR: + return 7; + case T_EXTERNAL: + return 8; + case T_REAL: + return 9; + case T_ENUM_A: + return 10; + case T_EMBEDDED_PDV: + return 11; + case T_UTF8STRING: + return 12; + case T_ROID: + return 13; + // note: tag numbers 14 and 15 are reserved for future use + case T_SEQ_A: + return 16; + case T_SET_A: + return 17; + case T_NUMERICSTRING: + return 18; + case T_PRINTABLESTRING: + return 19; + case T_TELETEXSTRING: + return 20; + case T_VIDEOTEXSTRING: + return 21; + case T_IA5STRING: + return 22; + case T_UTCTIME: + return 23; + case T_GENERALIZEDTIME: + return 24; + case T_GRAPHICSTRING: + return 25; + case T_VISIBLESTRING: + return 26; + case T_GENERALSTRING: + return 27; + case T_UNIVERSALSTRING: + return 28; + case T_UNRESTRICTEDSTRING: + return 29; + case T_BMPSTRING: + return 30; + default: + return -1; + } + } + + map *Type::default_tags = 0; + + void Type::destroy_default_tags() + { + if (default_tags) { + size_t nof_tags = default_tags->size(); + for (size_t i = 0; i < nof_tags; i++) + delete default_tags->get_nth_elem(i); + default_tags->clear(); + delete default_tags; + default_tags = 0; + } + } + + Type::Type(const Type& p) + : Governor(p), typetype(p.typetype) + { + init(); + if (p.w_attrib_path != NULL) FATAL_ERROR("Type::Type()"); + tags=p.tags?p.tags->clone():0; + if(p.constraints) { + constraints=p.constraints->clone(); + constraints->set_my_type(this); + } + else constraints=0; + if(p.parsed_restr!=NULL) { + parsed_restr=new vector; + for(size_t i=0;isize();i++) { + SubTypeParse *stp = 0; + switch((*p.parsed_restr)[i]->get_selection()) { + case SubTypeParse::STP_SINGLE: + stp=new SubTypeParse((*p.parsed_restr)[i]->Single()); + break; + case SubTypeParse::STP_RANGE: + stp=new SubTypeParse((*p.parsed_restr)[i]->Min(), + (*p.parsed_restr)[i]->MinExclusive(), + (*p.parsed_restr)[i]->Max(), + (*p.parsed_restr)[i]->MaxExclusive()); + break; + case SubTypeParse::STP_LENGTH: + FATAL_ERROR("Type::Type(Type&): STP_LENGTH"); + break; + default: FATAL_ERROR("Type::Type()"); + } + parsed_restr->add(stp); + } + } + else parsed_restr=0; + switch(typetype) { + case T_ERROR: + case T_NULL: + case T_BOOL: + case T_INT: + case T_REAL: + case T_BSTR: + case T_HSTR: + case T_OSTR: + case T_CSTR: + case T_USTR: + case T_UTF8STRING: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_IA5STRING: + case T_GRAPHICSTRING: + case T_VISIBLESTRING: + case T_GENERALSTRING: + case T_UNIVERSALSTRING: + case T_BMPSTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + case T_OBJECTDESCRIPTOR: + case T_OID: + case T_ROID: + case T_ANY: + case T_EXTERNAL: + case T_EMBEDDED_PDV: + case T_UNRESTRICTEDSTRING: + case T_VERDICT: + case T_DEFAULT: + break; + case T_INT_A: + case T_BSTR_A: + u.namednums.block=p.u.namednums.block?p.u.namednums.block->clone():0; + u.namednums.nvs=p.u.namednums.nvs?p.u.namednums.nvs->clone():0; + break; + case T_ENUM_A: + u.enums.block=p.u.enums.block?p.u.enums.block->clone():0; + u.enums.eis1=p.u.enums.eis1?p.u.enums.eis1->clone():0; + u.enums.ellipsis=p.u.enums.ellipsis; + u.enums.excSpec=p.u.enums.excSpec?p.u.enums.excSpec->clone():0; + u.enums.eis2=p.u.enums.eis2?p.u.enums.eis2->clone():0; + // no break + case T_ENUM_T: + u.enums.eis=p.u.enums.eis->clone(); + u.enums.eis_by_name=0; + break; + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + case T_ANYTYPE: + u.secho.cfm=p.u.secho.cfm->clone(); + u.secho.field_by_name = 0; + u.secho.component_internal = false; + u.secho.has_single_charenc = false; + break; + case T_SEQ_A: + case T_SET_A: + u.secho.tr_compsof_ready=p.u.secho.tr_compsof_ready; + // no break + case T_CHOICE_A: + u.secho.cfm = 0; + u.secho.block=p.u.secho.block?p.u.secho.block->clone():0; + u.secho.ctss=p.u.secho.ctss?p.u.secho.ctss->clone():0; + u.secho.field_by_name = 0; + u.secho.component_internal = false; + u.secho.has_single_charenc = false; + break; + case T_SEQOF: + case T_SETOF: + u.seof.ofType=p.u.seof.ofType->clone(); + u.seof.component_internal = false; + break; + case T_REFD: + u.ref.ref=p.u.ref.ref->clone(); + u.ref.type_refd=0; + u.ref.component_internal = false; + break; + case T_OCFT: + u.ref.oc_defn=p.u.ref.oc_defn; + u.ref.oc_fieldname=p.u.ref.oc_fieldname; + // no break + case T_REFDSPEC: + u.ref.type_refd=p.u.ref.type_refd; + u.ref.component_internal = false; + break; + case T_SELTYPE: + u.seltype.id=p.u.seltype.id->clone(); + u.seltype.type=p.u.seltype.type->clone(); + u.seltype.type_refd=0; + break; + case T_OPENTYPE: + u.secho.cfm=new CompFieldMap(); + u.secho.cfm->set_my_type(this); + u.secho.oc_defn=p.u.secho.oc_defn; + u.secho.oc_fieldname=p.u.secho.oc_fieldname; + u.secho.my_tableconstraint=0; + u.secho.field_by_name = 0; + u.secho.component_internal = false; + u.secho.has_single_charenc = false; + break; + case T_ARRAY: + u.array.element_type=p.u.array.element_type->clone(); + u.array.dimension = p.u.array.dimension->clone(); + u.array.in_typedef = p.u.array.in_typedef; + u.array.component_internal = false; + break; + case T_PORT: + u.port = p.u.port->clone(); + break; + case T_COMPONENT: + u.component = p.u.component->clone(); + break; + case T_ADDRESS: + u.address = 0; + break; + case T_SIGNATURE: + u.signature.parameters = p.u.signature.parameters ? + p.u.signature.parameters->clone() : 0; + u.signature.return_type = p.u.signature.return_type ? + p.u.signature.return_type->clone() : 0; + u.signature.no_block = p.u.signature.no_block; + u.signature.exceptions = p.u.signature.exceptions ? + p.u.signature.exceptions->clone() : 0; + u.signature.component_internal = false; + break; + case T_FUNCTION: + case T_ALTSTEP: + u.fatref.fp_list = p.u.fatref.fp_list->clone(); + u.fatref.runs_on.ref = p.u.fatref.runs_on.ref ? + p.u.fatref.runs_on.ref->clone() : 0; + u.fatref.runs_on.self = p.u.fatref.runs_on.self; + u.fatref.runs_on.type = 0; + u.fatref.return_type = p.u.fatref.return_type ? + p.u.fatref.return_type->clone() : 0; + u.fatref.is_startable = false; + u.fatref.returns_template = p.u.fatref.returns_template; + u.fatref.template_restriction = p.u.fatref.template_restriction; + break; + case T_TESTCASE: + u.fatref.fp_list = p.u.fatref.fp_list->clone(); + u.fatref.runs_on.ref = p.u.fatref.runs_on.ref ? + p.u.fatref.runs_on.ref->clone() : 0; + u.fatref.runs_on.self = false; + u.fatref.runs_on.type = 0; + u.fatref.system.ref = p.u.fatref.system.ref ? + p.u.fatref.system.ref->clone() : 0; + u.fatref.system.type = 0; + u.fatref.is_startable = false; + u.fatref.returns_template = false; + u.fatref.template_restriction = TR_NONE; + break; + default: + FATAL_ERROR("Type::Type()"); + } // switch + } + + void Type::init() + { + tags_checked = false; + tbl_cons_checked = false; + text_checked = false; + json_checked = false; + raw_parsed = false; + raw_checked = false; + xer_checked = false; + raw_length_calculated = false; + has_opentypes = false; + opentype_outermost = false; + code_generated = false; + embed_values_possible = false; + use_nil_possible = false; + use_order_possible = false; + raw_length = -1; + parent_type = 0; + tags = 0; + constraints = 0; + w_attrib_path = 0; + encode_attrib_path = 0; + rawattrib = 0; + textattrib = 0; + xerattrib = 0; + berattrib = 0; + jsonattrib = 0; + sub_type = 0; + parsed_restr = 0; + ownertype = OT_UNKNOWN; + owner = 0; + chk_finished = false; + } + + void Type::clean_up() + { + switch (typetype) { + case T_ERROR: + case T_NULL: + case T_BOOL: + case T_INT: + case T_REAL: + case T_BSTR: + case T_HSTR: + case T_OSTR: + case T_CSTR: + case T_USTR: + case T_UTF8STRING: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_IA5STRING: + case T_GRAPHICSTRING: + case T_VISIBLESTRING: + case T_GENERALSTRING: + case T_UNIVERSALSTRING: + case T_BMPSTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + case T_OBJECTDESCRIPTOR: + case T_OID: + case T_ROID: + case T_ANY: + case T_EXTERNAL: + case T_EMBEDDED_PDV: + case T_UNRESTRICTEDSTRING: + case T_REFDSPEC: + case T_OCFT: + case T_VERDICT: + case T_ADDRESS: + case T_DEFAULT: + break; + case T_INT_A: + case T_BSTR_A: + delete u.namednums.block; + delete u.namednums.nvs; + break; + case T_ENUM_A: + delete u.enums.block; + if(u.enums.eis1) { + u.enums.eis1->release_eis(); + delete u.enums.eis1; + } + if(u.enums.eis2) { + u.enums.eis2->release_eis(); + delete u.enums.eis2; + } + /* no break */ + case T_ENUM_T: + delete u.enums.eis; + if (u.enums.eis_by_name) { + for (size_t a = 0; a < u.enums.eis_by_name->size(); a++) { + delete u.enums.eis_by_name->get_nth_elem(a); + } + u.enums.eis_by_name->clear(); + delete u.enums.eis_by_name; + } + break; + case T_CHOICE_A: + case T_SEQ_A: + case T_SET_A: + delete u.secho.block; + delete u.secho.ctss; + /* no break */ + case T_ANYTYPE: + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + case T_OPENTYPE: + delete u.secho.cfm; + if (u.secho.field_by_name) { + for(size_t a = 0; a < u.secho.field_by_name->size(); a++) { + delete u.secho.field_by_name->get_nth_elem(a); + } + u.secho.field_by_name->clear(); + delete u.secho.field_by_name; + } + break; + case T_SEQOF: + case T_SETOF: + delete u.seof.ofType; + break; + case T_REFD: + delete u.ref.ref; + break; + case T_SELTYPE: + delete u.seltype.id; + delete u.seltype.type; + break; + case T_ARRAY: + delete u.array.element_type; + delete u.array.dimension; + break; + case T_PORT: + delete u.port; + break; + case T_COMPONENT: + delete u.component; + break; + case T_SIGNATURE: + delete u.signature.parameters; + delete u.signature.return_type; + delete u.signature.exceptions; + break; + case T_FUNCTION: + case T_ALTSTEP: + delete u.fatref.fp_list; + delete u.fatref.runs_on.ref; + delete u.fatref.return_type; + break; + case T_TESTCASE: + delete u.fatref.fp_list; + delete u.fatref.runs_on.ref; + delete u.fatref.system.ref; + break; + default: + FATAL_ERROR("Type::clean_up()"); + } // switch + typetype = T_ERROR; + delete tags; + tags = 0; + delete constraints; + constraints = 0; + delete rawattrib; + rawattrib = 0; + delete textattrib; + textattrib = 0; + delete xerattrib; + xerattrib = 0; + delete sub_type; + sub_type = 0; + delete berattrib; + berattrib = 0; + delete jsonattrib; + jsonattrib = 0; + if (parsed_restr) { + for (size_t i = 0; i < parsed_restr->size(); i++) + delete (*parsed_restr)[i]; + parsed_restr->clear(); + delete parsed_restr; + parsed_restr = 0; + } + delete w_attrib_path; + w_attrib_path = 0; + delete encode_attrib_path; + encode_attrib_path = 0; + } + + Type::Type(typetype_t p_tt) + : Governor(S_T), typetype(p_tt) + { + init(); + switch(p_tt) { + case T_ERROR: + case T_NULL: + case T_BOOL: + case T_INT: + case T_REAL: + case T_BSTR: + case T_HSTR: + case T_OSTR: + case T_CSTR: + case T_USTR: + case T_UTF8STRING: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_IA5STRING: + case T_GRAPHICSTRING: + case T_VISIBLESTRING: + case T_GENERALSTRING: + case T_UNIVERSALSTRING: + case T_BMPSTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + case T_OBJECTDESCRIPTOR: + case T_OID: + case T_ROID: + case T_ANY: + case T_EXTERNAL: + case T_EMBEDDED_PDV: + case T_UNRESTRICTEDSTRING: + case T_VERDICT: + case T_DEFAULT: + break; + case T_ANYTYPE: { + u.secho.cfm = new CompFieldMap; + u.secho.cfm->set_my_type(this); + u.secho.block=0; + u.secho.ctss=0; + u.secho.field_by_name = 0; + u.secho.component_internal = false; + u.secho.has_single_charenc = false; + break; } + case T_INT_A: + case T_BSTR_A: + u.namednums.block=0; + u.namednums.nvs=0; + break; + case T_ADDRESS: + u.address = 0; + break; + default: + FATAL_ERROR("Type::Type()"); + } // switch + } + + Type::Type(typetype_t p_tt, EnumItems *p_eis) + : Governor(S_T), typetype(p_tt) + { + if (p_tt != T_ENUM_T || !p_eis) FATAL_ERROR("Type::Type()"); + init(); + u.enums.eis=p_eis; + u.enums.eis_by_name=0; + } + + Type::Type(typetype_t p_tt, Block *p_block) + : Governor(S_T), typetype(p_tt) + { + if (!p_block) FATAL_ERROR("NULL parameter"); + init(); + switch(p_tt) { + case T_INT_A: + case T_BSTR_A: + u.namednums.block=p_block; + u.namednums.nvs=0; + break; + case T_ENUM_A: + u.enums.eis=new EnumItems(); + u.enums.block=p_block; + u.enums.eis1=0; + u.enums.ellipsis=false; + u.enums.excSpec=0; + u.enums.eis2=0; + u.enums.eis_by_name=0; + break; + case T_SEQ_A: + case T_SET_A: + u.secho.tr_compsof_ready=false; + // no break + case T_CHOICE_A: + u.secho.cfm = 0; + u.secho.block=p_block; + u.secho.ctss=0; + u.secho.field_by_name = 0; + u.secho.component_internal = false; + u.secho.has_single_charenc = false; + break; + default: + FATAL_ERROR("Type::Type()"); + } // switch + } + + Type::Type(typetype_t p_tt, + EnumItems *p_eis1, bool p_ellipsis, EnumItems *p_eis2) + : Governor(S_T), typetype(p_tt) + { + if (p_tt != T_ENUM_A || !p_eis1) FATAL_ERROR("Type::Type()"); + init(); + u.enums.eis=new EnumItems(); + u.enums.block=0; + u.enums.eis1=p_eis1; + u.enums.ellipsis=p_ellipsis; + u.enums.eis2=p_eis2; + u.enums.eis_by_name=0; + } + + Type::Type(typetype_t p_tt, CompFieldMap *p_cfm) + : Governor(S_T), typetype(p_tt) + { + if (!p_cfm) FATAL_ERROR("NULL parameter"); + init(); + switch (p_tt) { + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + u.secho.cfm=p_cfm; + u.secho.field_by_name = 0; + u.secho.component_internal = false; + u.secho.has_single_charenc = false; + break; + default: + FATAL_ERROR("Type::Type()"); + } // switch + } + + Type::Type(typetype_t p_tt, Type *p_type) + : Governor(S_T), typetype(p_tt) + { + if (!p_type) FATAL_ERROR("NULL parameter"); + init(); + switch (p_tt) { + case T_SEQOF: + case T_SETOF: + u.seof.ofType=p_type; + u.seof.ofType->set_ownertype(OT_RECORD_OF, this); + u.seof.component_internal = false; + break; + case T_REFDSPEC: + u.ref.type_refd=p_type; + u.ref.type_refd->set_ownertype(OT_REF_SPEC, this); + u.ref.component_internal = false; + break; + default: + FATAL_ERROR("Type::Type()"); + } // switch + } + + Type::Type(typetype_t p_tt, Identifier *p_id, Type *p_type) + : Governor(S_T), typetype(p_tt) + { + if (p_tt != T_SELTYPE || !p_id || !p_type) FATAL_ERROR("Type::Type()"); + init(); + u.seltype.id=p_id; + u.seltype.type=p_type; + u.seltype.type->set_ownertype(OT_SELTYPE, this); + u.seltype.type_refd=0; + } + + Type::Type(typetype_t p_tt, Type *p_type, Ttcn::ArrayDimension *p_dim, + bool p_in_typedef) + : Governor(S_T), typetype(p_tt) + { + if (p_tt != T_ARRAY || !p_type || !p_dim) FATAL_ERROR("Type::Type()"); + init(); + u.array.element_type = p_type; + u.array.element_type->set_ownertype(OT_ARRAY, this); + u.array.dimension = p_dim; + u.array.in_typedef = p_in_typedef; + u.array.component_internal = false; + } + + Type::Type(typetype_t p_tt, Type *p_type, OC_defn *p_oc_defn, + const Identifier *p_id) + : Governor(S_T), typetype(p_tt) + { + if (p_tt != T_OCFT || !p_type ||!p_oc_defn || !p_id) + FATAL_ERROR("Type::Type()"); + init(); + u.ref.type_refd=p_type; + u.ref.type_refd->set_ownertype(OT_OCFT, this); + u.ref.oc_defn=p_oc_defn; + u.ref.oc_fieldname=p_id; + u.ref.component_internal = false; + } + + Type::Type(typetype_t p_tt, OC_defn *p_oc_defn, + const Identifier *p_id) + : Governor(S_T), typetype(p_tt) + { + if (p_tt != T_OPENTYPE || !p_oc_defn || !p_id) FATAL_ERROR("Type::Type()"); + init(); + has_opentypes=true; + u.secho.cfm=new CompFieldMap(); + u.secho.cfm->set_my_type(this); + u.secho.oc_defn=p_oc_defn; + u.secho.oc_fieldname=p_id; + u.secho.my_tableconstraint=0; + u.secho.field_by_name = 0; + u.secho.component_internal = false; + u.secho.has_single_charenc = false; + } + + Type::Type(typetype_t p_tt, Reference *p_ref) + : Governor(S_T), typetype(p_tt) + { + if (p_tt != T_REFD || !p_ref) FATAL_ERROR("Type::Type()"); + init(); + u.ref.ref=p_ref; + u.ref.type_refd=0; + u.ref.component_internal = false; + } + + Type::Type(typetype_t p_tt, Ttcn::PortTypeBody *p_pb) + : Governor(S_T), typetype(p_tt) + { + if (p_tt != T_PORT || !p_pb) FATAL_ERROR("Type::Type()"); + init(); + u.port = p_pb; + p_pb->set_my_type(this); + } + + Type::Type(typetype_t p_tt, ComponentTypeBody *p_cb) + : Governor(S_T), typetype(p_tt) + { + if (p_tt != T_COMPONENT || !p_cb) FATAL_ERROR("Type::Type()"); + init(); + u.component = p_cb; + p_cb->set_my_type(this); + } + + Type::Type(typetype_t p_tt, SignatureParamList *p_params, Type *p_returntype, + bool p_noblock, SignatureExceptions *p_exceptions) + : Governor(S_T), typetype(p_tt) + { + if (p_tt != T_SIGNATURE || (p_returntype && p_noblock)) + FATAL_ERROR("Type::Type()"); + init(); + u.signature.parameters = p_params; + if ((u.signature.return_type = p_returntype)) { // check assignment for 0 + u.signature.return_type->set_ownertype(OT_SIGNATURE, this); + } + u.signature.no_block = p_noblock; + u.signature.exceptions = p_exceptions; + u.signature.component_internal = false; + } + + Type::Type(typetype_t p_tt,Ttcn::FormalParList *p_params, + Ttcn::Reference* p_runs_on_ref, bool p_runs_on_self, + Type *p_returntype, bool p_returns_template, + template_restriction_t p_template_restriction) + : Governor(S_T), typetype(p_tt) + { + if (p_tt != T_FUNCTION || !p_params || (!p_returntype && p_returns_template) + || (p_runs_on_ref && p_runs_on_self)) FATAL_ERROR("Type::Type()"); + init(); + u.fatref.fp_list = p_params; + u.fatref.runs_on.ref = p_runs_on_ref; + u.fatref.runs_on.self = p_runs_on_self; + u.fatref.runs_on.type = 0; + if ((u.fatref.return_type = p_returntype)) { // check assignment for 0 + u.fatref.return_type->set_ownertype(OT_FUNCTION, this); + } + u.fatref.is_startable = false; + u.fatref.returns_template = p_returns_template; + u.fatref.template_restriction = p_template_restriction; + } + + Type::Type(typetype_t p_tt,Ttcn::FormalParList *p_params, + Ttcn::Reference* p_runs_on_ref, bool p_runs_on_self) + : Governor(S_T), typetype(p_tt) + { + if(p_tt != T_ALTSTEP || !p_params || (p_runs_on_ref && p_runs_on_self)) + FATAL_ERROR("Type::Type()"); + init(); + u.fatref.fp_list = p_params; + u.fatref.runs_on.ref = p_runs_on_ref; + u.fatref.runs_on.self = p_runs_on_self; + u.fatref.runs_on.type = 0; + u.fatref.return_type = 0; + u.fatref.is_startable = false; + u.fatref.returns_template = false; + u.fatref.template_restriction = TR_NONE; + } + + Type::Type(typetype_t p_tt,Ttcn::FormalParList *p_params, + Ttcn::Reference* p_runs_on_ref, Ttcn::Reference *p_system_ref) + : Governor(S_T), typetype(p_tt) + { + if(p_tt != T_TESTCASE || !p_params || !p_runs_on_ref) + FATAL_ERROR("Type::Type()"); + init(); + u.fatref.fp_list = p_params; + u.fatref.runs_on.ref = p_runs_on_ref; + u.fatref.runs_on.self = false; + u.fatref.runs_on.type = 0; + u.fatref.system.ref = p_system_ref; + u.fatref.system.type = 0; + u.fatref.is_startable = false; + u.fatref.returns_template = false; + u.fatref.template_restriction = TR_NONE; + } + + Type::~Type() + { + clean_up(); + } + + void Type::free_pools() + { + destroy_default_tags();// Additionally: R&S license warning + destroy_pooltypes();// Additionally: R&S license checkin/disconnect/shutdown + } + + Type *Type::clone() const + { + return new Type(*this); + } + + Type::typetype_t Type::get_typetype_ttcn3(typetype_t p_tt) + { + switch (p_tt) { + case T_INT_A: + return T_INT; + case T_ENUM_A: + return T_ENUM_T; + case T_BSTR_A: + return T_BSTR; + case T_UTF8STRING: + case T_BMPSTRING: + case T_UNIVERSALSTRING: + return T_USTR; + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_GRAPHICSTRING: + case T_OBJECTDESCRIPTOR: + case T_GENERALSTRING: + // iso2022str + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + return T_CSTR; + case T_ROID: + return T_OID; + case T_ANY: + return T_OSTR; + case T_CHOICE_A: + case T_OPENTYPE: + return T_CHOICE_T; + case T_SEQ_A: + case T_EXTERNAL: + case T_EMBEDDED_PDV: + case T_UNRESTRICTEDSTRING: + return T_SEQ_T; + case T_SET_A: + return T_SET_T; + default: + return p_tt; + } // switch typetype + } + + bool Type::is_asn1() const + { + if (my_scope) return Setting::is_asn1(); + // the type might be a pool type, which is considered to be a TTCN-3 type + typetype_t t_typetype = get_typetype_ttcn3(typetype); + if (pooltypes && pooltypes->has_key(t_typetype) && + (*pooltypes)[t_typetype] == this) return false; + else FATAL_ERROR("Type::is_asn1()"); + } + + bool Type::is_ref() const + { + switch(typetype) { + case T_UNRESTRICTEDSTRING: + case T_OCFT: + case T_EXTERNAL: + case T_EMBEDDED_PDV: + case T_REFD: + case T_REFDSPEC: + case T_SELTYPE: + case T_ADDRESS: + return true; + default: + return false; + } // switch + } + + bool Type::is_secho() const + { + switch(typetype) { + case T_ANYTYPE: + case T_CHOICE_A: + case T_CHOICE_T: + case T_OPENTYPE: + case T_SEQ_A: + case T_SEQ_T: + case T_SET_A: + case T_SET_T: + return true; + default: + return false; + } // switch + } + + Type::truth Type::is_charenc() + { + switch(typetype) { + case T_CHOICE_A: + case T_CHOICE_T: + { + bool possible = true; + size_t ncomp = u.secho.cfm->get_nof_comps(); + for (size_t i=0; iget_comp_byIndex(i); + if (cf->get_type()->is_charenc() == No) { + possible = false; break; + } + } // next i + if (possible) { + return (xerattrib && (xerattrib->useUnion_ || xerattrib->useType_)) ? Yes : No; + } + } + // no break + case T_SEQ_A: + case T_SEQ_T: + case T_SET_A: + case T_SET_T: + case T_OPENTYPE: + // UNTAGGED cannot be used to make a type character-encodable! + // But USE-QNAME can! + return (xerattrib && xerattrib->useQName_) ? Yes : No; + + case T_SEQOF: // A record-of is character-encodable if it has the "list" + case T_SETOF: // attribute and its element is character-encodable. + return (xerattrib && xerattrib->list_ && (u.seof.ofType->is_charenc()==Yes)) + ? Yes : No; + + case T_ENUM_A: + case T_ENUM_T: + case T_VERDICT: + return Yes; + + default: + if (is_ref()) { + truth retval = get_type_refd_last()->is_charenc(); + if (retval == Yes) return Yes; + else if (retval == Maybe) { + if (xerattrib && xerattrib->useUnion_) return Yes; + } + // else fall through to No + } + return No; + + case T_BSTR: + case T_OSTR: + case T_HSTR: + case T_CSTR: + case T_USTR: + case T_UTF8STRING: + // TODO ASN.1 restricted character string types when (if) ASN.1 gets XER + // TODO check subtype; strings must be restricted to not contain + // control characters (0..0x1F except 9,0x0A,0x0D) + case T_INT_A: + case T_INT: + case T_BOOL: + case T_REAL: + // TODO more types + /* FIXME : this kind of check should be applied to elements of secho, + * not to the type of the element ! */ + return Yes; + } + } + + bool Type::has_empty_xml() { + bool answer = false; + switch (typetype) { + case T_SEQ_A: case T_SEQ_T: + case T_SET_A: case T_SET_T: { + answer = true; // If all components are optional. + size_t n_comps = get_nof_comps(); + for (size_t i = 0; i < n_comps; ++i) { + CompField* cf = get_comp_byIndex(i); + if (!cf->get_is_optional()) { + answer = false; + break; // the loop + } + } + break; } + case T_SEQOF: case T_SETOF: + // _If_ there is a length restriction, 0 length must be allowed. + // By this time parsed_restr has been absorbed into sub_type. + answer = (sub_type==0) || sub_type->zero_length_allowed(); + break; + default: + break; + } // switch + return answer; + } + + void Type::set_fullname(const string& p_fullname) + { + Governor::set_fullname(p_fullname); + switch(typetype) { + case T_INT_A: + case T_BSTR_A: + if(u.namednums.block) u.namednums.block->set_fullname(p_fullname); + if(u.namednums.nvs) + u.namednums.nvs->set_fullname(p_fullname+"."); + break; + case T_ENUM_A: + if(u.enums.eis1) u.enums.eis1->set_fullname(p_fullname); + if(u.enums.eis2) u.enums.eis2->set_fullname(p_fullname); + // no break + case T_ENUM_T: + u.enums.eis->set_fullname(p_fullname); + break; + case T_ANYTYPE: + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + case T_OPENTYPE: + u.secho.cfm->set_fullname(p_fullname); + break; + case T_SEQ_A: + case T_SET_A: + case T_CHOICE_A: + if (u.secho.ctss) u.secho.ctss->set_fullname(p_fullname); + break; + case T_SEQOF: + case T_SETOF: { + string subtypename("."); + Type * t = u.seof.ofType; + /* Do NOT call get_type_refd_last() or else fatal_error ! + * The AST is not fully set up. */ + + /* XER will use these strings */ + switch (t->typetype) + { + case T_EMBEDDED_PDV: case T_EXTERNAL: + case T_SEQ_A: case T_SEQ_T: + subtypename = ".SEQUENCE"; + break; + + case T_SET_A: case T_SET_T: + subtypename = ".SET"; + break; + + case T_SEQOF: + subtypename = ".SEQUENCE_OF"; + break; + + case T_SETOF: + subtypename = ".SET_OF"; + break; + + case T_BSTR_A: + subtypename = ".BITSTRING"; + break; + + case T_BOOL: + subtypename = ".BOOLEAN"; + break; + + case T_CHOICE_A: case T_CHOICE_T: + subtypename = ".CHOICE"; + break; + + case T_ENUM_A: case T_ENUM_T: + subtypename = ".ENUMERATED"; + break; + + case T_INT_A: case T_INT: + subtypename = ".INTEGER"; + break; + + default: + break; + } + u.seof.ofType->set_fullname(p_fullname+subtypename); + break; } + case T_REFD: + u.ref.ref->set_fullname(p_fullname); + break; + case T_SELTYPE: + u.seltype.type->set_fullname(p_fullname+"."); + break; + case T_PORT: + u.port->set_fullname(p_fullname); + break; + case T_COMPONENT: + u.component->set_fullname(p_fullname); + break; + case T_ARRAY: + u.array.element_type->set_fullname(p_fullname + "."); + u.array.dimension->set_fullname(p_fullname + "."); + break; + case T_SIGNATURE: + if (u.signature.parameters) + u.signature.parameters->set_fullname(p_fullname); + if (u.signature.return_type) + u.signature.return_type->set_fullname(p_fullname + "."); + if (u.signature.exceptions) + u.signature.exceptions->set_fullname(p_fullname + "."); + break; + case T_FUNCTION: + case T_ALTSTEP: + u.fatref.fp_list->set_fullname(p_fullname + ""); + if (u.fatref.runs_on.ref) + u.fatref.runs_on.ref->set_fullname(p_fullname + ""); + if (u.fatref.return_type) + u.fatref.return_type->set_fullname(p_fullname + ""); + break; + case T_TESTCASE: + u.fatref.fp_list->set_fullname(p_fullname + "."); + if (u.fatref.runs_on.ref) + u.fatref.runs_on.ref->set_fullname(p_fullname+"."); + if (u.fatref.system.ref) + u.fatref.system.ref->set_fullname(p_fullname + "."); + break; + default: + break; + } // switch + } + + void Type::set_my_scope(Scope *p_scope) + { + Governor::set_my_scope(p_scope); + if(tags) tags->set_my_scope(p_scope); + switch(typetype) { + case T_INT_A: + case T_BSTR_A: + if(u.namednums.nvs) u.namednums.nvs->set_my_scope(p_scope); + break; + case T_ENUM_A: + if(u.enums.eis1) u.enums.eis1->set_my_scope(p_scope); + if(u.enums.eis2) u.enums.eis2->set_my_scope(p_scope); + // no break + case T_ENUM_T: + u.enums.eis->set_my_scope(p_scope); + break; + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + case T_OPENTYPE: + case T_ANYTYPE: + u.secho.cfm->set_my_scope(p_scope); + break; + case T_SEQ_A: + case T_SET_A: + case T_CHOICE_A: + if(u.secho.ctss) u.secho.ctss->set_my_scope(p_scope); + break; + case T_SEQOF: + case T_SETOF: + u.seof.ofType->set_my_scope(p_scope); + break; + case T_REFD: + u.ref.ref->set_my_scope(p_scope); + break; + case T_SELTYPE: + u.seltype.type->set_my_scope(p_scope); + break; + case T_ARRAY: + u.array.element_type->set_my_scope(p_scope); + u.array.dimension->set_my_scope(p_scope); + break; + case T_PORT: + u.port->set_my_scope(p_scope); + break; + case T_SIGNATURE: + if (u.signature.parameters) + u.signature.parameters->set_my_scope(p_scope); + if (u.signature.return_type) + u.signature.return_type->set_my_scope(p_scope); + if (u.signature.exceptions) + u.signature.exceptions->set_my_scope(p_scope); + break; + case T_COMPONENT: + u.component->set_my_scope(p_scope); + break; + case T_FUNCTION: + case T_ALTSTEP: + // the scope of parameter list is set later in chk_Fat() + if (u.fatref.runs_on.ref) + u.fatref.runs_on.ref->set_my_scope(p_scope); + if (u.fatref.return_type) + u.fatref.return_type->set_my_scope(p_scope); + break; + case T_TESTCASE: + // the scope of parameter list is set later in chk_Fat() + if (u.fatref.runs_on.ref) + u.fatref.runs_on.ref->set_my_scope(p_scope); + if (u.fatref.system.ref) + u.fatref.system.ref->set_my_scope(p_scope); + break; + default: + break; + } // switch + } + + Type* Type::get_type_refd(ReferenceChain *refch) + { + switch(typetype) { + case T_REFD: { + if(refch && !refch->add(get_fullname())) goto error; + if(!u.ref.type_refd) { + Assignment *ass = u.ref.ref->get_refd_assignment(); + if (!ass) goto error; // The referenced assignment is not found + switch (ass->get_asstype()) { + case Assignment::A_ERROR: + goto error; + case Assignment::A_TYPE: + case Assignment::A_VS: + u.ref.type_refd = ass->get_Type()->get_field_type( + u.ref.ref->get_subrefs(), EXPECTED_DYNAMIC_VALUE, refch); + if (!u.ref.type_refd) goto error; + break; + //case Assignment::A_VS: + //u.ref.type_refd = ass->get_Type(); + // if(!u.ref.type_refd) goto error; + //break; + case Assignment::A_OC: + case Assignment::A_OBJECT: + case Assignment::A_OS: { + Setting *setting = u.ref.ref->get_refd_setting(); + if (!setting || setting->get_st() == Setting::S_ERROR) goto error; + /* valueset? */ + u.ref.type_refd = dynamic_cast(setting); + if(!u.ref.type_refd) { + error("`%s' is not a reference to a type", + u.ref.ref->get_dispname().c_str()); + goto error; + } + + if (u.ref.type_refd->ownertype == OT_UNKNOWN) { + u.ref.type_refd->set_ownertype(OT_REF, this); + } + + break;} + default: + error("`%s' is not a reference to a type", + u.ref.ref->get_dispname().c_str()); + goto error; + } // switch + if(!u.ref.type_refd->get_my_scope()) { + // opentype or OCFT + u.ref.type_refd->set_my_scope(get_my_scope()); + u.ref.type_refd->set_parent_type(get_parent_type()); + u.ref.type_refd->set_genname(get_genname_own(), string("type")); + u.ref.type_refd->set_fullname(get_fullname()+".type"); + } + if (u.ref.type_refd->typetype == T_OPENTYPE && !constraints) + warning("An open type without table constraint is useless in TTCN-3"); + } + return u.ref.type_refd; + break;} + case T_SELTYPE: { + if(refch && !refch->add(get_fullname())) goto error; + if(!u.seltype.type_refd) { + Type *t=u.seltype.type->get_type_refd_last(refch); + if(t->typetype==T_ERROR) goto error; + if(t->typetype!=T_CHOICE_A) { + error("(Reference to) a CHOICE type was expected" + " in selection type."); + goto error; + } + if(!t->has_comp_withName(*u.seltype.id)) { + error("No alternative with name `%s' in the given type `%s'.", + u.seltype.id->get_dispname().c_str(), + t->get_fullname().c_str()); + goto error; + } + u.seltype.type_refd=t->get_comp_byName(*u.seltype.id)->get_type(); + } + return u.seltype.type_refd; + break;} + case T_REFDSPEC: + case T_OCFT: + if(refch && !refch->add(get_fullname())) goto error; + return u.ref.type_refd; + break; + case T_EXTERNAL: { + if (!my_scope) FATAL_ERROR("Type::get_type_refd()"); + Identifier t_id(Identifier::ID_ASN, string("EXTERNAL")); + return my_scope->get_scope_asss()->get_local_ass_byId(t_id)->get_Type(); } + case T_EMBEDDED_PDV: { + if (!my_scope) FATAL_ERROR("Type::get_type_refd()"); + Identifier t_id(Identifier::ID_ASN, string("EMBEDDED PDV")); + return my_scope->get_scope_asss()->get_local_ass_byId(t_id)->get_Type(); } + case T_UNRESTRICTEDSTRING: { + if (!my_scope) FATAL_ERROR("Type::get_type_refd()"); + Identifier t_id(Identifier::ID_ASN, string("CHARACTER STRING")); + return my_scope->get_scope_asss()->get_local_ass_byId(t_id)->get_Type(); } + case T_ADDRESS: + if (refch && !refch->add(get_fullname())) goto error; + if (u.address) return u.address; + if (!my_scope) FATAL_ERROR("Type::get_type_refd()"); + u.address = my_scope->get_scope_mod()->get_address_type(); + if (!u.address) { + error("Type `address' is not defined in this module"); + goto error; + } + return u.address; + default: + FATAL_ERROR("Type::get_type_refd()"); + return 0; + } // switch + error: + clean_up(); + return this; + } + + Type* Type::get_type_refd_last(ReferenceChain *refch) + { + Type *t=this; + while(t->is_ref()) t=t->get_type_refd(refch); + return t; + } + + Type *Type::get_field_type(Ttcn::FieldOrArrayRefs *subrefs, + expected_value_t expected_index, ReferenceChain *refch, + bool interrupt_if_optional) + { + if (!subrefs) return this; + Type *t = this; + if (expected_index == EXPECTED_TEMPLATE) + expected_index = EXPECTED_DYNAMIC_VALUE; + size_t nof_refs = subrefs->get_nof_refs(); + subrefs->clear_string_element_ref(); + for (size_t i = 0; i < nof_refs; i++) { + if (refch) refch->mark_state(); + t = t->get_type_refd_last(refch); + if (refch) refch->prev_state(); + // stop immediately if current type t is erroneous + // (e.g. because of circular reference) + if (t->typetype == T_ERROR) return 0; + Ttcn::FieldOrArrayRef *ref = subrefs->get_ref(i); + switch (ref->get_type()) { + case Ttcn::FieldOrArrayRef::FIELD_REF: { + const Identifier& id = *ref->get_id(); + switch (t->typetype) { + case T_CHOICE_A: + case T_CHOICE_T: + case T_OPENTYPE: + case T_SEQ_A: + case T_SEQ_T: + case T_SET_A: + case T_SET_T: + case T_ANYTYPE: + break; + default: + ref->error("Invalid field reference `%s': type `%s' " + "does not have fields", id.get_dispname().c_str(), + t->get_typename().c_str()); + return 0; + } + if (!t->has_comp_withName(id)) { + ref->error("Reference to non-existent field `%s' in type `%s'", + id.get_dispname().c_str(), + t->get_typename().c_str()); + return 0; + } + CompField* cf = t->get_comp_byName(id); + if (interrupt_if_optional && cf->get_is_optional()) return 0; + t = cf->get_type(); + break; } + case Ttcn::FieldOrArrayRef::ARRAY_REF: { + Type *embedded_type = 0; + switch (t->typetype) { + case T_SEQOF: + case T_SETOF: + embedded_type = t->u.seof.ofType; + break; + case T_ARRAY: + embedded_type = t->u.array.element_type; + break; + case T_BSTR: + case T_BSTR_A: + case T_HSTR: + case T_OSTR: + case T_CSTR: + case T_USTR: + case T_UTF8STRING: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_IA5STRING: + case T_GRAPHICSTRING: + case T_VISIBLESTRING: + case T_GENERALSTRING: + case T_UNIVERSALSTRING: + case T_BMPSTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + case T_OBJECTDESCRIPTOR: + if (subrefs->refers_to_string_element()) { + ref->error("A string element of type `%s' cannot be indexed", + t->get_typename().c_str()); + return 0; + } else { + subrefs->set_string_element_ref(); + // string elements have the same type as the string itself + embedded_type = t; + break; + } + default: + ref->error("Type `%s' cannot be indexed", + t->get_typename().c_str()); + return 0; + } + // check the index value + Value *index_value = ref->get_val(); + if (t->typetype == T_ARRAY) { + // checking of array index is performed by the array dimension + t->u.array.dimension->chk_index(index_value, expected_index); + } else { + // perform a generic index check for other types + if (refch == 0 // variable assignment + || index_value->get_valuetype() != Value::V_NOTUSED) { + Error_Context cntxt(index_value, "In index value"); + index_value->chk_expr_int(expected_index); + } + Value *v_last = index_value->get_value_refd_last(); + if (v_last->get_valuetype() == Value::V_INT) { + const int_val_t *index_int = v_last->get_val_Int(); + if (*index_int > INT_MAX) { + index_value->error("Integer value `%s' is too big for indexing " + "type `%s'", (index_int->t_str()).c_str(), + (t->get_typename()).c_str()); + index_value->set_valuetype(Value::V_ERROR); + } else { + if (*index_int < 0) { + index_value->error("A non-negative integer value was " + "expected for indexing type `%s' instead of `%s'", + t->get_typename().c_str(), (index_int->t_str()).c_str()); + index_value->set_valuetype(Value::V_ERROR); + } + } + } + } + // change t to the embedded type + t = embedded_type; + break; } + default: + FATAL_ERROR("Type::get_field_type(): invalid reference type"); + } + } + return t; + } + + bool Type::get_subrefs_as_array(const Ttcn::FieldOrArrayRefs *subrefs, dynamic_array& subrefs_array, dynamic_array& type_array) + { + if (!subrefs) FATAL_ERROR("Type::get_subrefs_as_array()"); + Type *t = this; + size_t nof_refs = subrefs->get_nof_refs(); + for (size_t i = 0; i < nof_refs; i++) { + t = t->get_type_refd_last(); + type_array.add(t); + if (t->typetype == T_ERROR) FATAL_ERROR("Type::get_subrefs_as_array()"); + Ttcn::FieldOrArrayRef *ref = subrefs->get_ref(i); + size_t field_index=0; + switch (ref->get_type()) { + case Ttcn::FieldOrArrayRef::FIELD_REF: { + const Identifier& id = *ref->get_id(); + if (!t->has_comp_withName(id)) FATAL_ERROR("Type::get_subrefs_as_array()"); + CompField* cf = t->get_comp_byName(id); + field_index = t->get_comp_index_byName(id); + field_index = t->get_codegen_index(field_index); + t = cf->get_type(); + break; } + case Ttcn::FieldOrArrayRef::ARRAY_REF: { + Value *index_value = ref->get_val(); + Value *v_last = index_value->get_value_refd_last(); + if (v_last->get_valuetype()!=Value::V_INT) { + // workaround: get_field_type() does not return NULL if the index + // value is invalid, this function returns false in this case + return false; + } + const int_val_t *index_int = v_last->get_val_Int(); + if (!index_int->is_native() || index_int->is_negative()) { + return false; + } + field_index = (size_t)index_int->get_val(); + Type *embedded_type = 0; + switch (t->typetype) { + case T_SEQOF: + case T_SETOF: + embedded_type = t->u.seof.ofType; + break; + case T_ARRAY: + embedded_type = t->u.array.element_type; + break; + default: + embedded_type = t; + break; + } + // change t to the embedded type + t = embedded_type; + break; } + default: + FATAL_ERROR("Type::get_subrefs_as_array()"); + } + subrefs_array.add(field_index); + } + return true; + } + + bool Type::is_optional_field() const { + if (ownertype == OT_COMP_FIELD) { + const CompField* const myOwner = (CompField*) owner; + return myOwner && myOwner->get_is_optional(); + } + return false; + } + + bool Type::field_is_optional(Ttcn::FieldOrArrayRefs *subrefs) + { + // handling trivial cases + if (!subrefs) return false; + size_t nof_subrefs = subrefs->get_nof_refs(); + if (nof_subrefs < 1) return false; + Ttcn::FieldOrArrayRef *last_ref = subrefs->get_ref(nof_subrefs - 1); + if (last_ref->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF) return false; + // following the embedded types + Type *t=get_type_refd_last(); + for (size_t i = 0; i < nof_subrefs - 1; i++) { + Ttcn::FieldOrArrayRef *ref = subrefs->get_ref(i); + if (ref->get_type() == Ttcn::FieldOrArrayRef::FIELD_REF) + t = t->get_comp_byName(*ref->get_id())->get_type(); + else t = t->get_ofType(); + t=t->get_type_refd_last(); + } + // now last_ref refers to a field of t + return t->get_comp_byName(*last_ref->get_id())->get_is_optional(); + } + + bool Type::is_root_basic(){ + Type *t=get_type_refd_last(); + switch(t->typetype){ + case T_INT: + case T_BOOL: + case T_BSTR: + case T_HSTR: + case T_OSTR: + case T_CSTR: + return true; + break; + default: + break; + } + return false; + } + + int Type::get_raw_length(){ + if(!raw_checked) FATAL_ERROR("Type::get_raw_length()"); + if(raw_length_calculated) return raw_length; + raw_length_calculated=true; + switch(typetype) { + case T_REFD: + raw_length=get_type_refd()->get_raw_length(); + break; + case T_INT: + if(rawattrib) raw_length=rawattrib->fieldlength; + else raw_length=8; + break; + case T_BOOL: + if(rawattrib) raw_length=rawattrib->fieldlength; + else raw_length=1; + break; + case T_BSTR: + case T_HSTR: + case T_OSTR: + case T_CSTR: + if(rawattrib && rawattrib->fieldlength) raw_length=rawattrib->fieldlength; + else raw_length=-1; + break; + case T_ENUM_T: + if(rawattrib && rawattrib->fieldlength) raw_length=rawattrib->fieldlength; + else{ + int min_bits=0; + int max_val=u.enums.first_unused; + for(size_t a=0;aget_nof_eis();a++){ + int val=u.enums.eis->get_ei_byIndex(a)->get_value()->get_val_Int() + ->get_val(); + if((max_val<0?-max_val:max_val)<(val<0?-val:val)) max_val=val; + } + if(max_val<0){ min_bits=1;max_val=-max_val;} + while(max_val){ min_bits++; max_val/=2;} + raw_length=min_bits; + } + break; + case T_SEQ_T: + case T_SET_T: + raw_length=0; + for(size_t i = 0; i < get_nof_comps(); i++){ + int l=0; + CompField* cf=get_comp_byIndex(i); + if(cf->get_is_optional()){ + raw_length=-1; + return raw_length; + } + l=cf->get_type()->get_raw_length(); + if(l==-1){ + raw_length=-1; + return raw_length; + } + if(cf->get_type()->rawattrib + && (cf->get_type()->rawattrib->pointerto + || cf->get_type()->rawattrib->lengthto_num)){ + raw_length=-1; + return raw_length; + } + raw_length+=l; + } + break; + // TODO: case T_ANYTYPE: for get_raw_length needed ? + case T_CHOICE_T: + for(size_t i = 0; i < get_nof_comps(); i++){ + CompField *cf=get_comp_byIndex(i); + int l=0; + l=cf->get_type()->get_raw_length(); + if(l==-1){ + raw_length=-1; + return raw_length; + } + if(i){ + if(raw_length!=l){ + raw_length=-1; + return raw_length; + } + } + else raw_length=l; + } + break; + default: + raw_length=-1; + break; + } + return raw_length; + } + + /** \todo: add extra checks and warnings for unsupported attributes + * e.g. when TAG refers to a record/set field which has union type */ + void Type::chk_raw() + { + bool self_ref = false; + if (raw_checked) return; + raw_checked = true; + if (!enable_raw()) return; + int restrlength=-1; + if(sub_type) + restrlength=(int)sub_type->get_length_restriction(); + if(restrlength!=-1){ + if(!rawattrib){ + Type *t=get_type_refd_last(); + typetype_t basic_type=t->typetype; + rawattrib=new RawAST(basic_type==T_INT); + if(basic_type==T_REAL) rawattrib->fieldlength=64; + } + rawattrib->length_restrition=restrlength; + } + if(!rawattrib) return; + switch(typetype) { + case T_REFD: + get_type_refd()->force_raw(); + if(rawattrib->fieldlength==0 && rawattrib->length_restrition!=-1){ + typetype_t basic_type=get_type_refd_last()->typetype; + switch(basic_type){ + case T_BSTR: + rawattrib->fieldlength=rawattrib->length_restrition; + rawattrib->length_restrition=-1; + break; + case T_HSTR: + rawattrib->fieldlength=rawattrib->length_restrition*4; + rawattrib->length_restrition=-1; + break; + case T_OSTR: + rawattrib->fieldlength=rawattrib->length_restrition*8; + rawattrib->length_restrition=-1; + break; + case T_CSTR: + rawattrib->fieldlength=rawattrib->length_restrition*8; + rawattrib->length_restrition=-1; + break; + case T_SEQOF: + case T_SETOF: + rawattrib->fieldlength=rawattrib->length_restrition; + rawattrib->length_restrition=-1; + break; + default: + break; + } + } + break; + case T_CHOICE_T: + if(rawattrib){ + size_t nof_comps = get_nof_comps(); + for (size_t i = 0; i < nof_comps; i++) + get_comp_byIndex(i)->get_type()->force_raw(); + for(int c=0;ctaglist.nElements;c++){ + Identifier *idf=rawattrib->taglist.tag[c].fieldName; + if(!has_comp_withName(*idf)){ + error("Invalid field name `%s' in RAW parameter TAG for type `%s'", + idf->get_dispname().c_str(), get_typename().c_str()); + continue; + } + size_t fieldnum = get_comp_index_byName(*idf); + for(int a=0;ataglist.tag[c].nElements;a++){ + bool hiba=false; + CompField *cf=get_comp_byIndex(fieldnum); + Type *t=cf->get_type()->get_type_refd_last(); + for(int b=0;btaglist.tag[c].keyList[a]. + keyField->nElements;b++){ + Identifier *idf2= + rawattrib->taglist.tag[c].keyList[a].keyField->names[b]; + if(!t->is_secho()){ + error("Invalid fieldmember type in RAW parameter TAG" + " for field %s." + ,cf->get_name().get_dispname().c_str()); + hiba=true; + break; + } + if(!t->has_comp_withName(*idf2)){ + error("Invalid field member name `%s' in RAW parameter TAG " + "for field `%s'", idf2->get_dispname().c_str(), + cf->get_name().get_dispname().c_str()); + hiba=true; + break; + } + size_t comp_index=t->get_comp_index_byName(*idf2); + CompField *cf2=t->get_comp_byIndex(comp_index); + t=cf2->get_type()->get_type_refd_last(); + } + if(!hiba){ + Error_Context cntx(this, "In Raw parmeter TAG"); + Value *v = rawattrib->taglist.tag[c].keyList[a].v_value; + v->set_my_scope(get_my_scope()); + v->set_my_governor(t); + t->chk_this_value_ref(v); + self_ref = t->chk_this_value(v, 0, EXPECTED_CONSTANT, + INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK); + Value::valuetype_t vt = v->get_valuetype(); + if (vt == Value::V_ENUM || vt == Value::V_REFD) { + Free(rawattrib->taglist.tag[c].keyList[a].value); + rawattrib->taglist.tag[c].keyList[a].value = + mcopystr(v->get_single_expr().c_str()); + } + } + } + } + } + break; + case T_SEQ_T: + case T_SET_T: + if(rawattrib){ + size_t fieldnum; + for(int c=0;ctaglist.nElements;c++) { // check TAG + Identifier *idf=rawattrib->taglist.tag[c].fieldName; + if(!has_comp_withName(*idf)){ + error("Invalid field name `%s' in RAW parameter TAG " + "for type `%s'", idf->get_dispname().c_str(), + get_typename().c_str()); + continue; + } + fieldnum=get_comp_index_byName(*idf); + for(int a=0;ataglist.tag[c].nElements;a++){ + bool hiba=false; + CompField *cf=get_comp_byIndex(fieldnum); + Type *t=cf->get_type()->get_type_refd_last(); + for(int b=0;btaglist.tag[c].keyList[a]. + keyField->nElements;b++){ + Identifier *idf2= + rawattrib->taglist.tag[c].keyList[a].keyField->names[b]; + if(!t->is_secho()){ + error("Invalid fieldmember type in RAW parameter TAG" + " for field %s." + ,cf->get_name().get_dispname().c_str()); + hiba=true; + break; + } + if(!t->has_comp_withName(*idf2)){ + error("Invalid field member name `%s' in RAW parameter TAG " + "for field `%s'", idf2->get_dispname().c_str(), + cf->get_name().get_dispname().c_str()); + hiba=true; + break; + } + size_t comp_index=t->get_comp_index_byName(*idf2); + CompField *cf2=t->get_comp_byIndex(comp_index); + t=cf2->get_type()->get_type_refd_last(); + } + if(!hiba){ + Error_Context cntx(this, "In Raw parmeter TAG"); + Value *v = rawattrib->taglist.tag[c].keyList[a].v_value; + v->set_my_scope(get_my_scope()); + v->set_my_governor(t); + t->chk_this_value_ref(v); + self_ref = t->chk_this_value(v, 0, EXPECTED_CONSTANT, + INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK); + Value::valuetype_t vt = v->get_valuetype(); + if (vt == Value::V_ENUM || vt == Value::V_REFD) { + Free(rawattrib->taglist.tag[c].keyList[a].value); + rawattrib->taglist.tag[c].keyList[a].value = + mcopystr(v->get_single_expr().c_str()); + } + } + } + } + for(int a=0; aext_bit_goup_num;a++){ // EXTENSION_BIT_GROUP + Identifier *idf=rawattrib->ext_bit_groups[a].from; + Identifier *idf2=rawattrib->ext_bit_groups[a].to; + bool hiba=false; + if(!has_comp_withName(*idf)){ + error("Invalid field name `%s' in RAW parameter " + "EXTENSION_BIT_GROUP for type `%s'", + idf->get_dispname().c_str(), get_typename().c_str()); + hiba=true; + } + if(!has_comp_withName(*idf2)){ + error("Invalid field name `%s' in RAW parameter " + "EXTENSION_BIT_GROUP for type `%s'", + idf2->get_dispname().c_str(), get_typename().c_str()); + hiba=true; + } + if(!hiba){ + size_t kezd=get_comp_index_byName(*idf); + size_t veg=get_comp_index_byName(*idf2); + if(kezd>veg){ + error("Invalid field order in RAW parameter " + "EXTENSION_BIT_GROUP for type `%s': `%s', `%s'", + get_typename().c_str(), idf->get_dispname().c_str(), + idf2->get_dispname().c_str()); + hiba=true; + } + } + } + if(rawattrib->paddall!=XDEFDEFAULT){ // PADDALL + for(size_t i = 0; i < get_nof_comps(); i++) { + CompField *cfield=get_comp_byIndex(i); + RawAST *field_rawattr=cfield->get_type()->rawattrib; + if(field_rawattr==NULL){ + Type *t=cfield->get_type()->get_type_refd_last(); + typetype_t basic_type=t->typetype; + t=cfield->get_type(); + if(t->is_ref()) t=t->get_type_refd(); + while(!t->rawattrib && t->is_ref()) t=t->get_type_refd(); + field_rawattr= new RawAST(t->rawattrib,basic_type==T_INT); + if(!t->rawattrib && basic_type==T_REAL) field_rawattr->fieldlength=64; + cfield->get_type()->rawattrib=field_rawattr; + } + if(field_rawattr->padding==0) + field_rawattr->padding=rawattrib->padding; + if(field_rawattr->prepadding==0) + field_rawattr->prepadding=rawattrib->prepadding; + if (field_rawattr->padding_pattern_length == 0 && + rawattrib->padding_pattern_length > 0) { + Free(field_rawattr->padding_pattern); + field_rawattr->padding_pattern = + mcopystr(rawattrib->padding_pattern); + field_rawattr->padding_pattern_length = + rawattrib->padding_pattern_length; + } + } + } + if(rawattrib->fieldorder!=XDEFDEFAULT){ // FIELDORDER + for(size_t i = 0; i < get_nof_comps(); i++) { + CompField *cfield=get_comp_byIndex(i); + RawAST *field_rawattr=cfield->get_type()->rawattrib; + if(field_rawattr==NULL){ + Type *t=cfield->get_type()->get_type_refd_last(); + typetype_t basic_type=t->typetype; + t=cfield->get_type(); + if(t->is_ref()) t=t->get_type_refd(); + while(!t->rawattrib && t->is_ref()) t=t->get_type_refd(); + field_rawattr= new RawAST(t->rawattrib,basic_type==T_INT); + if(!t->rawattrib && basic_type==T_REAL) field_rawattr->fieldlength=64; + cfield->get_type()->rawattrib=field_rawattr; + } + if(field_rawattr->fieldorder==XDEFDEFAULT) + field_rawattr->fieldorder=rawattrib->fieldorder; + } + } + } + for(int a=0;apresence.nElements;a++){ //PRESENCE + Type *t=this; + bool hiba=false; + for(int b=0;bpresence.keyList[a].keyField->nElements;b++){ + Identifier *idf=rawattrib->presence.keyList[a].keyField->names[b]; + if(!t->is_secho()){ + error("Invalid fieldmember type in RAW parameter PRESENCE" + " for the record %s." + ,get_typename().c_str()); + hiba=true; + break; + } + if(!t->has_comp_withName(*idf)){ + error("Invalid fieldname in RAW parameter" + " PRESENCE for the record %s: %s" + ,get_typename().c_str() + ,rawattrib->presence.keyList[a].keyField->names[b] + ->get_dispname().c_str()); + hiba=true; + break; + } + t=t->get_comp_byName(*idf)->get_type()->get_type_refd_last(); + } + if(!hiba){ + Error_Context cntx(this, "In Raw parameter PRESENCE"); + Value *v = rawattrib->presence.keyList[a].v_value; + v->set_my_scope(get_my_scope()); + v->set_my_governor(t); + t->chk_this_value_ref(v); + self_ref = t->chk_this_value(v, 0, EXPECTED_CONSTANT, + INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK); + Value::valuetype_t vt = v->get_valuetype(); + if (vt == Value::V_ENUM || vt == Value::V_REFD) { + Free(rawattrib->presence.keyList[a].value); + rawattrib->presence.keyList[a].value = + mcopystr(v->get_single_expr().c_str()); + } + } + } + for(size_t i = 0; i < get_nof_comps(); i++) { // field attributes + CompField *cf = get_comp_byIndex(i); + const Identifier& field_id = cf->get_name(); + Type *field_type = cf->get_type(); + Type *field_type_last = field_type->get_type_refd_last(); + field_type->force_raw(); + RawAST *rawpar = field_type->rawattrib; + if (rawpar) { + for (int j = 0; j < rawpar->lengthto_num; j++) { // LENGTHTO + Identifier *idf = rawpar->lengthto[j]; + if (!has_comp_withName(*idf)) { + error("Invalid fieldname in RAW parameter " + "LENGTHTO for field %s: %s", + field_id.get_dispname().c_str(), + rawpar->lengthto[j]->get_dispname().c_str()); + } + } + if (rawpar->lengthto_num) { + Type *ft = field_type; + if (ft->get_typetype() == T_REFD) ft = ft->get_type_refd_last(); + typetype_t ftt = ft->get_typetype(); + switch (ftt) { + case T_INT: + case T_INT_A: + break; + case T_CHOICE_T: + case T_CHOICE_A: + for (size_t fi = 0; fi < ft->get_nof_comps(); fi++) { + typetype_t uftt = ft->get_comp_byIndex(fi)->get_type() + ->get_typetype(); + if (uftt != T_INT && uftt != T_INT_A) + error("The union type LENGTHTO field must contain only " + "integer fields"); + } + break; + case T_ANYTYPE: + case T_OPENTYPE: + case T_SEQ_A: + case T_SEQ_T: + case T_SET_A: + case T_SET_T: + if (rawpar->lengthindex) break; // Will be checked in the next step. + // Else continue with default. + default: + error("The LENGTHTO field must be an integer or union type " + "instead of `%s'", ft->get_typename().c_str()); + break; + } + } + if(rawpar->lengthto_num && rawpar->lengthindex){ // LENGTHINDEX + Identifier *idf=rawpar->lengthindex->names[0]; + if(!field_type_last->is_secho()){ + error("Invalid fieldmember type in RAW parameter LENGTHINDEX" + " for field %s." + ,field_id.get_dispname().c_str()); + break; + } + if(!field_type_last->has_comp_withName(*idf)) + error("Invalid fieldname in RAW parameter" + " LENGTHINDEX for field %s: %s" + ,field_id.get_dispname().c_str() + ,rawpar->lengthindex->names[0]->get_dispname().c_str()); + } + if(rawpar->pointerto){ // POINTERTO + Identifier *idf=rawpar->pointerto; + bool hiba=false; + size_t pointed=0; + if(!has_comp_withName(*idf)){ + error("Invalid fieldname in RAW" + " parameter POINTERTO for field %s: %s" + ,field_id.get_dispname().c_str() + ,rawpar->pointerto->get_dispname().c_str()); + hiba=true; + } + if(!hiba && (pointed=get_comp_index_byName(*idf))<=i){ + error("Pointer must precede the pointed field. Incorrect field " + "name `%s' in RAW parameter POINTERTO for field `%s'", + rawpar->pointerto->get_dispname().c_str(), + field_id.get_dispname().c_str()); + hiba=true; + } + if(!hiba && rawpar->ptrbase){ // POINTERTO + Identifier *idf2=rawpar->ptrbase; + if(!has_comp_withName(*idf2)){ + error("Invalid field name `%s' in RAW parameter PTROFFSET for " + "field `%s'", rawpar->ptrbase->get_dispname().c_str(), + field_id.get_dispname().c_str()); + hiba=true; + } + if(!hiba && get_comp_index_byName(*idf2)>pointed){ + error("Pointer base must precede the pointed field. Incorrect " + "field name `%s' in RAW parameter PTROFFSET for field " + "`%s'", rawpar->ptrbase->get_dispname().c_str(), + field_id.get_dispname().c_str()); + } + } + } + for(int a=0;apresence.nElements;a++){ //PRESENCE + Type *t=this; + bool hiba=false; + for(int b=0;bpresence.keyList[a].keyField->nElements;b++){ + Identifier *idf=rawpar->presence.keyList[a].keyField->names[b]; + if(!t->is_secho()){ + error("Invalid fieldmember type in RAW parameter PRESENCE" + " for field %s." + ,field_id.get_dispname().c_str()); + hiba=true; + break; + } + if(!t->has_comp_withName(*idf)){ + error("Invalid fieldname `%s' in RAW parameter PRESENCE for " + "field `%s'", rawpar->presence.keyList[a].keyField + ->names[b]->get_dispname().c_str(), + field_id.get_dispname().c_str()); + hiba=true; + break; + } + if(b==0 && !(get_comp_index_byName(*rawpar->presence.keyList[a] + .keyField->names[0])presence.keyList[a].keyField->names[0] + ->get_dispname().c_str() + ,field_id.get_dispname().c_str()); + hiba=true; + break; + } + t=t->get_comp_byName(*idf)->get_type()->get_type_refd_last(); + } + if(!hiba){ + Error_Context cntx(this, "In Raw parmeter PRESENCE"); + Value *v = rawpar->presence.keyList[a].v_value; + v->set_my_scope(get_my_scope()); + v->set_my_governor(t); + t->chk_this_value_ref(v); + self_ref = t->chk_this_value(v, 0, EXPECTED_CONSTANT, + INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK); + Value::valuetype_t vt = v->get_valuetype(); + if (vt == Value::V_ENUM || vt == Value::V_REFD) { + Free(rawpar->presence.keyList[a].value); + rawpar->presence.keyList[a].value = + mcopystr(v->get_single_expr().c_str()); + } + } + } + for(int c=0;ccrosstaglist.nElements;c++) { // CROSSTAG + Identifier *idf=rawpar->crosstaglist.tag[c].fieldName; + if(!field_type_last->is_secho()){ + error("Invalid fieldmember type in RAW parameter CROSSTAG" + " for field %s." + ,field_id.get_dispname().c_str()); + break; + } + if(!field_type_last->has_comp_withName(*idf)){ + error("Invalid fieldmember name in RAW parameter CROSSTAG" + " for field %s: %s" + ,field_id.get_dispname().c_str() + ,rawpar->crosstaglist.tag[c].fieldName + ->get_dispname().c_str()); + break; + } + for(int a=0;acrosstaglist.tag[c].nElements;a++){ + Type *t2=this; + bool hiba=false; + bool allow_omit = false; + for(int b=0; + bcrosstaglist.tag[c].keyList[a].keyField->nElements;b++){ + Identifier *idf2= + rawpar->crosstaglist.tag[c].keyList[a].keyField->names[b]; + if(!t2->is_secho()){ + error("Invalid fieldmember type in RAW parameter CROSSTAG" + " for field %s." + ,field_id.get_dispname().c_str()); + hiba=true; + break; + } + if(!t2->has_comp_withName(*idf2)){ + error("Invalid fieldname in RAW parameter CROSSTAG" + " for field %s: %s" + ,field_id.get_dispname().c_str() + ,idf2->get_dispname().c_str()); + hiba=true; + break; + } + if (b == 0) { + size_t field_idx = get_comp_index_byName(*idf2); + if (field_idx == i) { + error("RAW parameter CROSSTAG for field `%s' cannot refer " + "to the field itself", idf2->get_dispname().c_str()); + } else if (field_idx > i) { + if (cf->get_is_optional() || + field_type->get_raw_length() < 0) + error("Field `%s' that CROSSTAG refers to must precede " + "field `%s' or field `%s' must be mandatory with " + "fixed length", idf2->get_dispname().c_str(), + field_id.get_dispname().c_str(), + field_id.get_dispname().c_str()); + } + } + CompField *cf2=t2->get_comp_byName(*idf2); + t2=cf2->get_type()->get_type_refd_last(); + if (b == rawpar->crosstaglist.tag[c].keyList[a].keyField + ->nElements - 1 && cf2->get_is_optional()) + allow_omit = true; + } + if(!hiba){ + Error_Context cntx(this, "In Raw parmeter CROSSTAG"); + Value *v = rawpar->crosstaglist.tag[c].keyList[a].v_value; + v->set_my_scope(get_my_scope()); + v->set_my_governor(t2); + t2->chk_this_value_ref(v); + self_ref = t2->chk_this_value(v, 0, EXPECTED_CONSTANT, + INCOMPLETE_NOT_ALLOWED, + (allow_omit ? OMIT_ALLOWED : OMIT_NOT_ALLOWED), SUB_CHK); + Value::valuetype_t vt = v->get_valuetype(); + if (vt == Value::V_ENUM || vt == Value::V_REFD) { + Free(rawpar->crosstaglist.tag[c].keyList[a].value); + rawpar->crosstaglist.tag[c].keyList[a].value = + mcopystr(v->get_single_expr().c_str()); + } + } + } + } + } + } + break; + case T_BSTR: + if(rawattrib->fieldlength==0 && rawattrib->length_restrition!=-1){ + rawattrib->fieldlength=rawattrib->length_restrition; + rawattrib->length_restrition=-1; + } + break; + case T_HSTR: + if(rawattrib->fieldlength==0 && rawattrib->length_restrition!=-1){ + rawattrib->fieldlength=rawattrib->length_restrition*4; + rawattrib->length_restrition=-1; + } + break; + case T_OSTR: + if(rawattrib->fieldlength==0 && rawattrib->length_restrition!=-1){ + rawattrib->fieldlength=rawattrib->length_restrition*8; + rawattrib->length_restrition=-1; + } + break; + case T_CSTR: + if(rawattrib->fieldlength==0 && rawattrib->length_restrition!=-1){ + rawattrib->fieldlength=rawattrib->length_restrition*8; + rawattrib->length_restrition=-1; + } + break; + case T_SEQOF: + case T_SETOF: + get_ofType()->force_raw(); + if(rawattrib->fieldlength==0 && rawattrib->length_restrition!=-1){ + rawattrib->fieldlength=rawattrib->length_restrition; + rawattrib->length_restrition=-1; + } + if(rawattrib->length_restrition!=-1 && + rawattrib->length_restrition!=rawattrib->fieldlength){ + error("Invalid length specified in parameter FIELDLENGTH for %s of " + "type `%s'. The FIELDLENGTH must be equal to specified length " + "restriction", typetype == T_SEQOF ? "record" : "set", + get_fullname().c_str()); + } + break; + case T_REAL: + if(rawattrib->fieldlength!=64 && rawattrib->fieldlength!=32){ + error("Invalid length (%d) specified in parameter FIELDLENGTH for " + "float type `%s'. The FIELDLENGTH must be single (32) or double " + "(64)", rawattrib->fieldlength, get_fullname().c_str()); + } + break; + case T_ENUM_T: + case T_INT: + case T_BOOL: + default: + // nothing to do, ASN1 types or types without defined raw attribute + break; + } // switch + + (void)self_ref; + } + + void Type::force_raw() + { + if (!rawattrib) + { + switch (typetype) { + case T_SEQOF: + case T_SETOF: + case T_CHOICE_T: + // TODO case T_ANYTYPE: for force_raw ? + case T_ENUM_T: + case T_SEQ_T: + case T_SET_T: + rawattrib = new RawAST(false); + break; + default: + if (is_ref()) get_type_refd()->force_raw(); + break; + } + } + + // Don't run chk_raw() on unchecked types + if (chk_finished) + chk_raw(); + } + + void Type::chk_text() + { + if (text_checked) return; + text_checked = true; + if (!textattrib || !enable_text()) return; +//textattrib->print_TextAST(); + + chk_text_matching_values(textattrib->begin_val, "BEGIN"); + chk_text_matching_values(textattrib->end_val, "END"); + chk_text_matching_values(textattrib->separator_val, "SEPARATOR"); + + switch (typetype) { + case T_ANYTYPE: + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: { + size_t nof_comps = get_nof_comps(); + for (size_t i = 0; i < nof_comps; i++) + get_comp_byIndex(i)->get_type()->force_text(); + break; } + case T_SEQOF: + case T_SETOF: + get_ofType()->force_text(); + break; + default: + if (is_ref()) get_type_refd()->force_text(); + break; + } + + switch (get_type_refd_last()->typetype) { + case T_BOOL: + chk_text_matching_values(textattrib->true_params, "true value"); + chk_text_matching_values(textattrib->false_params, "false value"); + break; + case T_ENUM_T: + if(textattrib->nof_field_params){ + Type *t=get_type_refd_last(); + size_t nof_comps = t->u.enums.eis->get_nof_eis(); + textAST_enum_def **params=(textAST_enum_def**) + Malloc(nof_comps*sizeof(textAST_enum_def*)); + memset(params,0,nof_comps*sizeof(textAST_enum_def*)); + for (int a = 0; a < textattrib->nof_field_params; a++) { + const Identifier& id = *textattrib->field_params[a]->name; + if (t->u.enums.eis->has_ei_withName(id)) { + int index = t->get_eis_index_byName(id); + if (params[index]) FATAL_ERROR("Type::chk_text(): duplicate " \ + "attribute for enum `%s'", id.get_dispname().c_str()); + params[index] = textattrib->field_params[a]; + char *attrib_name = mprintf("enumerated value `%s'", + id.get_dispname().c_str()); + chk_text_matching_values(¶ms[index]->value, attrib_name); + Free(attrib_name); + } else { + error("Coding attribute refers to non-existent enumerated value " + "`%s'", id.get_dispname().c_str()); + Free(textattrib->field_params[a]->value.encode_token); + Free(textattrib->field_params[a]->value.decode_token); + delete textattrib->field_params[a]->name; + Free(textattrib->field_params[a]); + } + } + Free(textattrib->field_params); + textattrib->field_params=params; + textattrib->nof_field_params=nof_comps; + } + break; + case T_OSTR: + case T_CSTR: + case T_INT: + if (textattrib->decode_token) { + char *tmp = textattrib->decode_token; + textattrib->decode_token = process_decode_token(tmp, *this); + Free(tmp); + tmp = TTCN_pattern_to_regexp(textattrib->decode_token); + if (tmp) Free(tmp); + else { + error("Incorrect select token expression: `%s'", + textattrib->decode_token); + } + } + break; + default: + break; + } +//textattrib->print_TextAST(); + } + + void Type::chk_text_matching_values(textAST_matching_values *matching_values, + const char *attrib_name) + { + if (!matching_values) return; + if (matching_values->decode_token) { + // check whether decode token is a correct TTCN-3 pattern + char *tmp = matching_values->decode_token; + matching_values->decode_token = process_decode_token(tmp, *this); + Free(tmp); + tmp = TTCN_pattern_to_regexp(matching_values->decode_token); + if (tmp) Free(tmp); + else { + error("Incorrect matching expression for %s: `%s'", attrib_name, + matching_values->decode_token); + } + } else if (matching_values->encode_token) { + // the decode token is not present, but there is an encode token + // derive the decode token from the encode token + matching_values->generated_decode_token = true; + matching_values->decode_token = + convert_charstring_to_pattern(matching_values->encode_token); + } + } + + void Type::force_text() + { + if (!textattrib) + { + switch (typetype) { + case T_SEQOF: + case T_SETOF: + case T_CHOICE_T: + // TODO case T_ANYTYPE: for force_text ? + case T_ENUM_T: + case T_SEQ_T: + case T_SET_T: + textattrib = new TextAST; + break; + default: + if (is_ref()) get_type_refd()->force_text(); + break; + } + } + if (chk_finished) + chk_text(); + } + + void Type::chk_json() + { + if (json_checked) return; + json_checked = true; + if ((NULL == jsonattrib && !hasEncodeAttr(CT_JSON)) || !enable_json()) return; + + switch (typetype) { + case T_ANYTYPE: + case T_CHOICE_T: + case T_CHOICE_A: + case T_SEQ_T: + case T_SEQ_A: + case T_SET_T: + case T_SET_A: { + size_t nof_comps = get_nof_comps(); + for (size_t i = 0; i < nof_comps; i++) + get_comp_byIndex(i)->get_type()->force_json(); + break; } + case T_SEQOF: + case T_SETOF: + get_ofType()->force_json(); + break; + default: + if (is_ref()) get_type_refd()->force_json(); + break; + } + + if (NULL != jsonattrib) { + if (jsonattrib->omit_as_null && !is_optional_field()) { + error("Invalid attribute, 'omit as null' requires optional " + "field of a record or set."); + } + + if (jsonattrib->as_value && T_CHOICE_T != get_type_refd_last()->typetype) { + error("Invalid attribute, 'as value' is only allowed for unions"); + } + + if (NULL != jsonattrib->alias) { + Type* parent = get_parent_type(); + if (NULL == parent || (T_SEQ_T != parent->typetype && + T_SET_T != parent->typetype && T_CHOICE_T != parent->typetype)) { + error("Invalid attribute, 'name as ...' requires field of a " + "record, set or union."); + } + if (NULL != parent && NULL != parent->jsonattrib && + T_CHOICE_T == parent->typetype && parent->jsonattrib->as_value) { + warning("Attribute 'name as ...' will be ignored, because parent union " + "is encoded without field names."); + } + } + + if (NULL != jsonattrib->default_value) { + chk_json_default(); + } + } + } + + void Type::chk_json_default() + { + const char* dval = jsonattrib->default_value; + const size_t dval_len = strlen(dval); + Type *last = get_type_refd_last(); + bool err = false; + switch (last->typetype) { + case T_BOOL: + if (strcmp(dval, "true") != 0 && strcmp(dval, "false") != 0) { + err = true; + } + break; + case T_INT: + for (size_t i = (dval[0] == '-') ? 1 : 0; i < dval_len; ++i) { + if (dval[i] < '0' || dval[i] > '9') { + err = true; + break; // from the loop + } + } + break; + case T_REAL: { + if (strcmp(dval, "infinity") == 0 || strcmp(dval, "-infinity") == 0 || + strcmp(dval, "not_a_number") == 0) { + // special float values => skip the rest of the check + break; + } + + boolean first_digit = false; // first non-zero digit reached + boolean zero = false; // first zero digit reached + boolean decimal_point = false; // decimal point (.) reached + boolean exponent_mark = false; // exponential mark (e or E) reached + boolean exponent_sign = false; // sign of the exponential (- or +) reached + + size_t i = (dval[0] == '-') ? 1 : 0; + while(!err && i < dval_len) { + switch (dval[i]) { + case '.': + if (decimal_point || exponent_mark || (!first_digit && !zero)) { + err = true; + } + decimal_point = true; + first_digit = false; + zero = false; + break; + case 'e': + case 'E': + if (exponent_mark || (!first_digit && !zero)) { + err = true; + } + exponent_mark = true; + first_digit = false; + zero = false; + break; + case '0': + if (!first_digit && (exponent_mark || (!decimal_point && zero))) { + err = true; + } + zero = true; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (!first_digit && zero && (!decimal_point || exponent_mark)) { + err = true; + } + first_digit = true; + break; + case '-': + case '+': + if (exponent_sign || !exponent_mark || zero || first_digit) { + err = true; + } + exponent_sign = true; + break; + default: + err = true; + } + ++i; + } + err = !first_digit && !zero; + break; } + case T_BSTR: + for (size_t i = 0; i < dval_len; ++i) { + if (dval[i] < '0' || dval[i] > '1') { + err = true; + break; // from the loop + } + } + break; + case T_OSTR: + if (dval_len % 2 != 0) { + err = true; + break; + } + // no break + case T_HSTR: + for (size_t i = 0; i < dval_len; ++i) { + if ((dval[i] < '0' || dval[i] > '9') && (dval[i] < 'a' || dval[i] > 'f') && + (dval[i] < 'A' || dval[i] > 'F')) { + err = true; + break; // from the loop + } + } + break; + case T_CSTR: + case T_USTR: { + size_t i = 0; + while(!err && i < dval_len) { + if (dval[i] < 0 && last->typetype == T_CSTR) { + err = true; + } + else if (dval[i] == '\\') { + if (i == dval_len - 1) { + err = true; + } else { + ++i; + switch (dval[i]) { + case '\\': + case '\"': + case 'n': + case 't': + case 'r': + case 'f': + case 'b': + case '/': + break; // these are OK + case 'u': { + if (i + 4 >= dval_len) { + err = true; + } else if (last->typetype == T_CSTR && + (dval[i + 1] != '0' || dval[i + 2] != '0' || + dval[i + 3] < '0' || dval[i + 3] > '7')) { + err = true; + } else { + for (size_t j = (last->typetype == T_CSTR) ? 4 : 1; j <= 4; ++j) { + if ((dval[i + j] < '0' || dval[i + j] > '9') && + (dval[i + j] < 'a' || dval[i + j] > 'f') && + (dval[i + j] < 'A' || dval[i + j] > 'F')) { + err = true; + break; // from the loop + } + } + } + i += 4; + break; } + default: + err = true; + break; + } + } + } + ++i; + } + break; } + case T_ENUM_T: { + Common::Identifier id(Identifier::ID_TTCN, string(dval)); + if (!last->has_ei_withName(id)) { + err = true; + } + break; } + case T_VERDICT: + if (strcmp(dval, "none") != 0 && strcmp(dval, "pass") != 0 && + strcmp(dval, "inconc") != 0 && strcmp(dval, "fail") != 0 && + strcmp(dval, "error") != 0) { + err = true; + } + break; + default: + error("JSON default values are not available for type `%s'", + last->get_stringRepr().c_str()); + return; + } + + if (err) { + if (last->typetype == T_ENUM_T) { + error("Invalid JSON default value for enumerated type `%s'", + last->get_stringRepr().c_str()); + } else { + error("Invalid %s JSON default value", get_typename_builtin(last->typetype)); + } + } + } + + void Type::force_json() + { + if (!jsonattrib) + { + switch (typetype) { + case T_SEQOF: + case T_SETOF: + case T_CHOICE_T: + case T_CHOICE_A: + case T_ENUM_T: + case T_ENUM_A: + case T_SEQ_T: + case T_SEQ_A: + case T_SET_T: + case T_SET_A: + jsonattrib = new JsonAST; + break; + default: + if (is_ref()) get_type_refd()->force_json(); + break; + } + } + if (chk_finished) + chk_json(); + } + + + int Type::get_length_multiplier() + { + switch(typetype) { + case T_REFD: + return get_type_refd()->get_length_multiplier(); + break; + case T_HSTR: + return 4; + break; + case T_OSTR: + case T_CSTR: + return 8; + default: + return 1; + break; + } + return 1; + } + + /** \todo review, especially the string types... */ + bool Type::is_compatible_tt_tt(typetype_t p_tt1, typetype_t p_tt2, + bool p_is_asn11, bool p_is_asn12) + { + if (p_tt2 == T_ERROR) return true; + switch (p_tt1) { + // error type is compatible with everything + case T_ERROR: + return true; + // unambiguous built-in types + case T_NULL: + case T_BOOL: + case T_REAL: + case T_HSTR: + case T_SEQOF: + case T_SETOF: + case T_VERDICT: + case T_DEFAULT: + case T_COMPONENT: + case T_SIGNATURE: + case T_PORT: + case T_ARRAY: + case T_FUNCTION: + case T_ALTSTEP: + case T_TESTCASE: + return p_tt1 == p_tt2; + case T_OSTR: + return p_tt2==T_OSTR || (!p_is_asn11 && p_tt2==T_ANY); + case T_USTR: + switch (p_tt2) { + case T_USTR: + case T_UTF8STRING: + case T_BMPSTRING: + case T_UNIVERSALSTRING: + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_GRAPHICSTRING: + case T_OBJECTDESCRIPTOR: + case T_GENERALSTRING: + case T_CSTR: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + return true; + default: + return false; + } + // character string group 1 + case T_UTF8STRING: + case T_BMPSTRING: + case T_UNIVERSALSTRING: + switch (p_tt2) { + case T_USTR: + case T_UTF8STRING: + case T_BMPSTRING: + case T_UNIVERSALSTRING: + case T_CSTR: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + return true; + default: + return false; + } + // character string group 2 + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_GRAPHICSTRING: + case T_OBJECTDESCRIPTOR: + case T_GENERALSTRING: + switch (p_tt2) { + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_GRAPHICSTRING: + case T_OBJECTDESCRIPTOR: + case T_GENERALSTRING: + case T_CSTR: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + return true; + case T_USTR: + // maybe :) is ustr.is_cstr() + return true; + default: + return false; + } + // character string group 3 + case T_CSTR: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + switch (p_tt2) { + case T_CSTR: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + return true; + default: + return false; + } + // polymorphic built-in types + case T_BSTR: + case T_BSTR_A: + return p_tt2 == T_BSTR || p_tt2 == T_BSTR_A; + case T_INT: + case T_INT_A: + return p_tt2 == T_INT || p_tt2 == T_INT_A; + // ROID is visible as OID from TTCN-3 + case T_OID: + return p_tt2 == T_OID || + (!p_is_asn11 && p_tt2 == T_ROID); + case T_ROID: + return p_tt2 == T_ROID || + (!p_is_asn12 && p_tt2 == T_OID); + case T_ENUM_A: + case T_ENUM_T: + return p_tt2==T_ENUM_A || p_tt2==T_ENUM_T; + case T_CHOICE_T: + case T_CHOICE_A: + case T_OPENTYPE: + return p_tt2==T_CHOICE_T || p_tt2==T_CHOICE_A || p_tt2==T_OPENTYPE; + case T_SEQ_A: + case T_SEQ_T: + return p_tt2==T_SEQ_A || p_tt2==T_SEQ_T; + case T_SET_A: + case T_SET_T: + return p_tt2==T_SET_A || p_tt2==T_SET_T; + case T_ANY: + return p_tt2 == T_ANY || p_tt2 == T_OSTR; + // these should never appear? + case T_REFD: + case T_REFDSPEC: + case T_OCFT: + case T_ADDRESS: + return false; + default: + FATAL_ERROR("Type::is_compatible_tt_tt()"); + return false; + } + } + + bool Type::is_compatible_tt(typetype_t p_tt, bool p_is_asn1) + { + chk(); + Type *t1=get_type_refd_last(); + if (p_tt == T_ERROR) return true; + switch (t1->typetype) { + // these should never appear + case T_REFD: + case T_REFDSPEC: + case T_OCFT: + case T_ADDRESS: + FATAL_ERROR("Type::is_compatible_tt()"); + return false; + default: + return is_compatible_tt_tt(t1->typetype, p_tt, is_asn1(), p_is_asn1); + } + } + + bool Type::is_compatible(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain, TypeChain *p_right_chain) + { + chk(); + p_type->chk(); + Type *t1 = get_type_refd_last(); + Type *t2 = p_type->get_type_refd_last(); + // Error type is compatible with everything. + if (t1->typetype == T_ERROR || t2->typetype == T_ERROR) return true; + bool is_type_comp; + switch (t1->typetype) { + // Unambiguous built-in types. + case T_NULL: + case T_BOOL: + case T_REAL: + case T_HSTR: + case T_VERDICT: + case T_DEFAULT: + is_type_comp = (t1->typetype == t2->typetype); + break; + case T_OSTR: + is_type_comp = ( t2->typetype==T_OSTR || (!is_asn1() && t2->typetype==T_ANY) ); + break; + case T_USTR: + switch (t2->typetype) { + case T_USTR: + case T_UTF8STRING: + case T_BMPSTRING: + case T_UNIVERSALSTRING: + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_GRAPHICSTRING: + case T_OBJECTDESCRIPTOR: + case T_GENERALSTRING: + case T_CSTR: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + is_type_comp = true; + break; + default: + is_type_comp = false; + break; + } + break; + // Character string group 1. + case T_UTF8STRING: + case T_BMPSTRING: + case T_UNIVERSALSTRING: + switch (t2->typetype) { + case T_USTR: + case T_UTF8STRING: + case T_BMPSTRING: + case T_UNIVERSALSTRING: + case T_CSTR: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + is_type_comp = true; + break; + default: + is_type_comp = false; + break; + } + break; + // Character string group 2. + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_GRAPHICSTRING: + case T_OBJECTDESCRIPTOR: + case T_GENERALSTRING: + switch (t2->typetype) { + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_GRAPHICSTRING: + case T_OBJECTDESCRIPTOR: + case T_GENERALSTRING: + case T_CSTR: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + is_type_comp = true; + break; + case T_USTR: + // Maybe :) is ustr.is_cstr(). + is_type_comp = true; + break; + default: + is_type_comp = false; + break; + } + break; + // Character string group 3. + case T_CSTR: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + switch (t2->typetype) { + case T_CSTR: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + is_type_comp = true; + break; + default: + is_type_comp = false; + break; + } + break; + // Polymorphic built-in types. + case T_BSTR: + case T_BSTR_A: + is_type_comp = ( t2->typetype == T_BSTR || t2->typetype == T_BSTR_A ); + break; + case T_INT: + case T_INT_A: + is_type_comp = ( t2->typetype == T_INT || t2->typetype == T_INT_A ); + break; + // ROID is visible as OID from TTCN-3. + case T_OID: + is_type_comp = ( t2->typetype == T_OID || (!is_asn1() && t2->typetype == T_ROID) ); + break; + case T_ROID: + is_type_comp = ( t2->typetype == T_ROID || (!p_type->is_asn1() && t2->typetype == T_OID) ); + break; + case T_COMPONENT: + is_type_comp = ( t2->typetype == T_COMPONENT && t1->u.component->is_compatible(t2->u.component) ); + break; + case T_SEQ_A: + case T_SEQ_T: + is_type_comp = t1->is_compatible_record(t2, p_info, p_left_chain, p_right_chain); + break; + case T_SEQOF: + is_type_comp = t1->is_compatible_record_of(t2, p_info, p_left_chain, p_right_chain); + break; + case T_SET_A: + case T_SET_T: + is_type_comp = t1->is_compatible_set(t2, p_info, p_left_chain, p_right_chain); + break; + case T_SETOF: + is_type_comp = t1->is_compatible_set_of(t2, p_info, p_left_chain, p_right_chain); + break; + case T_ARRAY: + is_type_comp = t1->is_compatible_array(t2, p_info, p_left_chain, p_right_chain); + break; + case T_CHOICE_T: + case T_CHOICE_A: + case T_ANYTYPE: + is_type_comp = t1->is_compatible_choice_anytype(t2, p_info, p_left_chain, p_right_chain); + break; + case T_ENUM_A: + case T_ENUM_T: + case T_SIGNATURE: + case T_PORT: + case T_OPENTYPE: + is_type_comp = ( t1 == t2 ); + break; + case T_FUNCTION: + case T_ALTSTEP: + case T_TESTCASE: + // TODO: Compatibility. + is_type_comp = ( t1 == t2 ); + break; + case T_ANY: + is_type_comp = ( t2->typetype == T_ANY || t2->typetype == T_OSTR ); + break; + default: + FATAL_ERROR("Type::is_compatible()"); + } + // if types are compatible then check subtype compatibility + // skip check if p_info is NULL + if ((p_info!=NULL) && is_type_comp && (sub_type!=NULL) && (p_type->sub_type!=NULL) && + (sub_type->get_subtypetype()==p_type->sub_type->get_subtypetype())) + { + if (p_info->get_str1_elem()) { + if (p_info->get_str2_elem()) { + // both are string elements -> nothing to do + } else { + // char <-> string + if (!p_type->sub_type->is_compatible_with_elem()) { + is_type_comp = false; + p_info->set_subtype_error( + string("Subtype mismatch: string element has no common value with subtype ")+ + p_type->sub_type->to_string()); + } + } + } else { + if (p_info->get_str2_elem()) { + // string <-> char + if (!sub_type->is_compatible_with_elem()) { + is_type_comp = false; + p_info->set_subtype_error(string("Subtype mismatch: subtype ")+ + sub_type->to_string()+string(" has no common value with a string element")); + } + } else { + // string <-> string + if (!sub_type->is_compatible(p_type->sub_type)) { + is_type_comp = false; + p_info->set_subtype_error(string("Subtype mismatch: subtype ")+ + sub_type->to_string()+string(" has no common value with subtype ")+ + p_type->sub_type->to_string()); + } + } + } + } + return is_type_comp; + } + + bool Type::is_structured_type() const + { + switch (typetype) { + case T_SEQ_A: + case T_SEQ_T: + case T_SEQOF: + case T_ARRAY: + case T_CHOICE_A: + case T_CHOICE_T: + case T_ANYTYPE: + case T_SET_A: + case T_SET_T: + case T_SETOF: + return true; + default: + return false; + } + } + + bool Type::is_subtype_length_compatible(Type *p_type) + { + if (typetype != T_SEQOF && typetype != T_SETOF) + FATAL_ERROR("Type::is_subtype_length_compatible()"); + if (!sub_type) return true; + SubtypeConstraint::subtype_t st_t = typetype == T_SEQOF ? + SubtypeConstraint::ST_RECORDOF : SubtypeConstraint::ST_SETOF; + switch (p_type->typetype) { + case T_SEQ_A: + case T_SEQ_T: + case T_SET_A: + case T_SET_T: { + vector p_stp_v; + Value *p_nof_comps = new Value(Value::V_INT, + new int_val_t(p_type->get_nof_comps())); + p_stp_v.add(new SubTypeParse(new Ttcn::LengthRestriction(p_nof_comps))); + SubType p_st(st_t, this, NULL, &p_stp_v, NULL); + p_st.chk(); + delete p_stp_v[0]; + p_stp_v.clear(); + return sub_type->is_length_compatible(&p_st); } + case T_SEQOF: + case T_SETOF: + if (!p_type->sub_type) return true; + else return sub_type->is_length_compatible(p_type->sub_type); + case T_ARRAY: { + if (p_type->u.array.dimension->get_has_error()) return false; + vector p_stp_v; + Value *p_nof_comps + = new Value(Value::V_INT, + new int_val_t(p_type->u.array.dimension->get_size())); + p_stp_v.add(new SubTypeParse(new Ttcn::LengthRestriction(p_nof_comps))); + SubType p_st(st_t, this, NULL, &p_stp_v, NULL); + p_st.chk(); // Convert SubTypeParse to SubType. + delete p_stp_v[0]; + p_stp_v.clear(); + return sub_type->is_length_compatible(&p_st); } + default: + FATAL_ERROR("Type::is_subtype_length_compatible()"); + } + } + + // Errors and warnings are reported in an upper level. We just make a + // simple decision here. + bool Type::is_compatible_record(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain, + TypeChain *p_right_chain) + { + if (typetype != T_SEQ_A && typetype != T_SEQ_T) + FATAL_ERROR("Type::is_compatible_record()"); + // The get_type_refd_last() was called for both Types at this point. All + // this code runs in both run-times. + if (this == p_type) return true; + else if (!use_runtime_2 || !p_info + || (p_info && p_info->is_strict())) return false; + size_t nof_comps = get_nof_comps(); + switch (p_type->typetype) { + case T_SEQ_A: + case T_SEQ_T: { + // According to 6.3.2.2 the # of fields and the optionality must be + // the same for record types. It's good news for compile-time checks. + // Conversion is always from "p_type -> this". + size_t p_nof_comps = p_type->get_nof_comps(); + if (nof_comps != p_nof_comps) { + p_info->set_is_erroneous(this, p_type, string("The number of fields in " + "record/SEQUENCE types must be the same")); + return false; + } + // If p_info is present we have the chains as well. + if (p_left_chain->empty()) p_left_chain->add(this); + if (p_right_chain->empty()) p_right_chain->add(p_type); + for (size_t i = 0; i < nof_comps; i++) { + CompField *cf = get_comp_byIndex(i); + CompField *p_cf = p_type->get_comp_byIndex(i); + Type *cf_type = cf->get_type()->get_type_refd_last(); + Type *p_cf_type = p_cf->get_type()->get_type_refd_last(); + string cf_name = cf->get_name().get_dispname(); + string p_cf_name = p_cf->get_name().get_dispname(); + if (cf->get_is_optional() != p_cf->get_is_optional()) { + p_info->append_ref_str(0, "." + cf_name); + p_info->append_ref_str(1, "." + p_cf_name); + p_info->set_is_erroneous(cf_type, p_cf_type, string("The optionality of " + "fields in record/SEQUENCE types must be " + "the same")); + return false; + } + TypeCompatInfo info_tmp(p_info->get_my_module(), cf_type, p_cf_type, + false, false); + p_left_chain->mark_state(); + p_right_chain->mark_state(); + p_left_chain->add(cf_type); + p_right_chain->add(p_cf_type); + if (cf_type != p_cf_type + && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) + && !cf_type->is_compatible(p_cf_type, &info_tmp, p_left_chain, + p_right_chain)) { + p_info->append_ref_str(0, "." + cf_name + info_tmp.get_ref_str(0)); + p_info->append_ref_str(1, "." + p_cf_name + info_tmp.get_ref_str(1)); + p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), + info_tmp.get_error_str()); + p_left_chain->previous_state(); + p_right_chain->previous_state(); + return false; + } + p_left_chain->previous_state(); + p_right_chain->previous_state(); + } + p_info->set_needs_conversion(true); + p_info->add_type_conversion(p_type, this); + return true; } + case T_SEQOF: + if (!p_type->is_subtype_length_compatible(this)) { + p_info->set_is_erroneous(this, p_type, string("Incompatible record of/SEQUENCE " + "OF subtypes")); + return false; + } + // no break + case T_ARRAY: { + Type *p_of_type = p_type->get_ofType()->get_type_refd_last(); + if (p_type->typetype == T_ARRAY) { + if (p_of_type->get_typetype() == T_ARRAY) { + p_info->set_is_erroneous(this, p_type, string("record/SEQUENCE types are " + "compatible only with single-dimension " + "arrays")); + return false; + } + size_t nof_opt_fields = 0; + for (size_t i = 0; i < nof_comps; i++) + if (get_comp_byIndex(i)->get_is_optional()) nof_opt_fields++; + if (p_type->u.array.dimension->get_size() + < nof_comps - nof_opt_fields) { + p_info->set_is_erroneous(this, p_type, string("The dimension of the array " + "must be >= than the number of mandatory " + "fields in the record/SEQUENCE type")); + return false; + } + } + if (p_left_chain->empty()) p_left_chain->add(this); + if (p_right_chain->empty()) p_right_chain->add(p_type); + for (size_t i = 0; i < nof_comps; i++) { + Type *cf_type = get_comp_byIndex(i)->get_type()->get_type_refd_last(); + TypeCompatInfo info_tmp(p_info->get_my_module(), cf_type, p_of_type, + false, false); + p_left_chain->mark_state(); + p_right_chain->mark_state(); + p_left_chain->add(cf_type); + p_right_chain->add(p_of_type); + if (cf_type != p_of_type + && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) + && !cf_type->is_compatible(p_of_type, &info_tmp, p_left_chain, + p_right_chain)) { + p_info->append_ref_str(0, "." + get_comp_byIndex(i) + ->get_name().get_dispname() + info_tmp.get_ref_str(0)); + p_info->append_ref_str(1, "[]" + info_tmp.get_ref_str(1)); + p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), + info_tmp.get_error_str()); + p_left_chain->previous_state(); + p_right_chain->previous_state(); + return false; + } + p_left_chain->previous_state(); + p_right_chain->previous_state(); + } + p_info->set_needs_conversion(true); + p_info->add_type_conversion(p_type, this); + return true; } + case T_CHOICE_A: + case T_CHOICE_T: + case T_ANYTYPE: + // 6.3.2.4 makes our job very easy... + p_info->set_is_erroneous(this, p_type, string("union/CHOICE/anytype types are " + "compatible only with other " + "union/CHOICE/anytype types")); + return false; + case T_SET_A: + case T_SET_T: + case T_SETOF: + // Only set/set of types are compatible with other set/set of types. + // 6.3.2.3 is a little bit unclear about set of types, but we treat them + // this way. Otherwise, it would be possible to use compatibility with + // a "middle-man" set of variable between record/set types: + // type set S { integer f1, integer f2 } + // type record { integer f1, integer f2 } + // type set of integer SO + // var S s := { 1, 2 } + // var R r := { 1, 2 } + // var SO so + // so := s + // if (r == s) { ... } // Not allowed. + // if (r == so) { ... } // Not allowed. (?) + // Seems to be a fair decision. If we would want compatibility between + // variables of record/set types, we should allow it directly. + p_info->set_is_erroneous(this, p_type, string("set/SET and set of/SET OF " + "types are compatible only with other set/SET " + "set of/SET OF types")); + return false; + default: + return false; + } + } + + bool Type::is_compatible_record_of(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain, + TypeChain *p_right_chain) + { + if (typetype != T_SEQOF) FATAL_ERROR("Type::is_compatible_record_of()"); + if (this == p_type) return true; + else if (!use_runtime_2 || !p_info + || (p_info && p_info->is_strict())) return false; + switch (p_type->typetype) { + case T_SEQ_A: + case T_SEQ_T: { + if (!is_subtype_length_compatible(p_type)) { + p_info->set_is_erroneous(this, p_type, string("Incompatible " + "record of/SEQUENCE OF subtypes")); + return false; + } + Type *of_type = get_ofType()->get_type_refd_last(); + if (p_left_chain->empty()) p_left_chain->add(this); + if (p_right_chain->empty()) p_right_chain->add(p_type); + for (size_t i = 0; i < p_type->get_nof_comps(); i++) { + CompField *p_cf = p_type->get_comp_byIndex(i); + Type *p_cf_type = p_cf->get_type()->get_type_refd_last(); + TypeCompatInfo info_tmp(p_info->get_my_module(), of_type, p_cf_type, + false, false); + p_left_chain->mark_state(); + p_right_chain->mark_state(); + p_left_chain->add(of_type); + p_right_chain->add(p_cf_type); + if (of_type != p_cf_type + && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) + && !of_type->is_compatible(p_cf_type, &info_tmp, p_left_chain, + p_right_chain)) { + p_info->append_ref_str(0, "[]" + info_tmp.get_ref_str(0)); + p_info->append_ref_str(1, "." + p_cf->get_name().get_dispname() + + info_tmp.get_ref_str(1)); + p_info->set_is_erroneous(info_tmp.get_type(0), + info_tmp.get_type(1), + info_tmp.get_error_str()); + p_left_chain->previous_state(); + p_right_chain->previous_state(); + return false; + } + p_left_chain->previous_state(); + p_right_chain->previous_state(); + } + p_info->set_needs_conversion(true); + p_info->add_type_conversion(p_type, this); + return true; } + case T_SEQOF: + case T_ARRAY: { + if (!is_subtype_length_compatible(p_type)) { + p_info->set_is_erroneous(this, p_type, string("Incompatible " + "record of/SEQUENCE OF subtypes")); + return false; + } + Type *of_type = get_ofType()->get_type_refd_last(); + Type *p_of_type = p_type->get_ofType()->get_type_refd_last(); + if (p_left_chain->empty()) p_left_chain->add(this); + if (p_right_chain->empty()) p_right_chain->add(p_type); + TypeCompatInfo info_tmp(p_info->get_my_module(), of_type, p_of_type, + false, false); + p_left_chain->mark_state(); + p_right_chain->mark_state(); + p_left_chain->add(of_type); + p_right_chain->add(p_of_type); + if (of_type == p_of_type + || (p_left_chain->has_recursion() && p_right_chain->has_recursion()) + || of_type->is_compatible(p_of_type, &info_tmp, p_left_chain, + p_right_chain)) { + p_info->set_needs_conversion(true); + p_info->add_type_conversion(p_type, this); + p_left_chain->previous_state(); + p_right_chain->previous_state(); + return true; + } + p_left_chain->previous_state(); + p_right_chain->previous_state(); + p_info->append_ref_str(0, "[]" + info_tmp.get_ref_str(0)); + // Arrays already have the "[]" in their names. + if (p_type->get_typetype() != T_ARRAY) p_info->append_ref_str(1, string("[]")); + p_info->append_ref_str(1, info_tmp.get_ref_str(1)); + p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), + info_tmp.get_error_str()); + return false; } + case T_CHOICE_A: + case T_CHOICE_T: + case T_ANYTYPE: + p_info->set_is_erroneous(this, p_type, string("union/CHOICE/anytype types are " + "compatible only with other " + "union/CHOICE/anytype types")); + return false; + case T_SET_A: + case T_SET_T: + case T_SETOF: + p_info->set_is_erroneous(this, p_type, string("set/SET and set of/SET OF " + "types are compatible only with other set/SET " + "set of/SET OF types")); + return false; + default: + return false; + } + } + + bool Type::is_compatible_array(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain, + TypeChain *p_right_chain) + { + if (typetype != T_ARRAY) FATAL_ERROR("Type::is_compatible_array()"); + // Copied from the original checker code. The type of the elements and + // the dimension of the array must be the same. + if (this == p_type) return true; + if (p_type->typetype == T_ARRAY && u.array.element_type + ->is_compatible(p_type->u.array.element_type, NULL) + && u.array.dimension->is_identical(p_type->u.array.dimension)) + return true; + else if (!use_runtime_2 || !p_info + || (p_info && p_info->is_strict())) return false; + Type *of_type = get_ofType()->get_type_refd_last(); + switch (p_type->get_typetype()) { + case T_SEQ_A: + case T_SEQ_T: { + if (of_type->get_typetype() == T_ARRAY) { + p_info->set_is_erroneous(this, p_type, string("record/SEQUENCE types are " + "compatible only with single-dimension " + "arrays")); + return false; + } + size_t p_nof_comps = p_type->get_nof_comps(); + size_t p_nof_opt_fields = 0; + for (size_t i = 0; i < p_nof_comps; i++) + if (p_type->get_comp_byIndex(i)->get_is_optional()) + p_nof_opt_fields++; + if (u.array.dimension->get_size() < p_nof_comps - p_nof_opt_fields) { + p_info->set_is_erroneous(this, p_type, string("The dimension of the array " + "must be >= than the number of mandatory " + "fields in the record/SEQUENCE type")); + return false; + } + if (p_left_chain->empty()) p_left_chain->add(this); + if (p_right_chain->empty()) p_right_chain->add(p_type); + for (size_t i = 0; i < p_nof_comps; ++i) { + CompField *p_cf = p_type->get_comp_byIndex(i); + Type *p_cf_type = p_cf->get_type()->get_type_refd_last(); + string p_cf_name = p_cf->get_name().get_dispname(); + TypeCompatInfo info_tmp(p_info->get_my_module(), of_type, p_cf_type, + false, false); + p_left_chain->mark_state(); + p_right_chain->mark_state(); + p_left_chain->add(of_type); + p_right_chain->add(p_cf_type); + if (of_type != p_cf_type + && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) + && !of_type->is_compatible(p_cf_type, &info_tmp, p_left_chain, + p_right_chain)) { + p_info->append_ref_str(0, info_tmp.get_ref_str(0)); + p_info->append_ref_str(1, "." + p_cf->get_name().get_dispname() + + info_tmp.get_ref_str(1)); + p_info->set_is_erroneous(info_tmp.get_type(0), + info_tmp.get_type(1), + info_tmp.get_error_str()); + p_left_chain->previous_state(); + p_right_chain->previous_state(); + return false; + } + p_left_chain->previous_state(); + p_right_chain->previous_state(); + } + p_info->set_needs_conversion(true); + p_info->add_type_conversion(p_type, this); + return true; } + case T_SEQOF: + if (!p_type->is_subtype_length_compatible(this)) { + p_info->set_is_erroneous(this, p_type, string("Incompatible " + "record of/SEQUENCE OF subtypes")); + return false; + } // Don't break. + case T_ARRAY: { + if (p_type->get_typetype() == T_ARRAY + && !u.array.dimension->is_identical(p_type->u.array.dimension)) { + p_info->set_is_erroneous(this, p_type, string("Array types should have " + "the same dimension")); + return false; + } + Type *p_of_type = p_type->get_ofType()->get_type_refd_last(); + TypeCompatInfo info_tmp(p_info->get_my_module(), of_type, p_of_type, + false, false); + if (p_left_chain->empty()) p_left_chain->add(this); + if (p_right_chain->empty()) p_right_chain->add(p_type); + p_left_chain->mark_state(); + p_right_chain->mark_state(); + p_left_chain->add(of_type); + p_right_chain->add(p_of_type); + if (of_type == p_of_type + || (p_left_chain->has_recursion() && p_right_chain->has_recursion()) + || of_type->is_compatible(p_of_type, &info_tmp, p_left_chain, + p_right_chain)) { + p_info->set_needs_conversion(true); + p_info->add_type_conversion(p_type, this); + p_left_chain->previous_state(); + p_right_chain->previous_state(); + return true; + } + p_left_chain->previous_state(); + p_right_chain->previous_state(); + p_info->append_ref_str(0, info_tmp.get_ref_str(0)); + if (p_type->get_typetype() != T_ARRAY) p_info->append_ref_str(1, string("[]")); + p_info->append_ref_str(1, info_tmp.get_ref_str(1)); + p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), + info_tmp.get_error_str()); + return false; } + case T_CHOICE_A: + case T_CHOICE_T: + case T_ANYTYPE: + p_info->set_is_erroneous(this, p_type, string("union/CHOICE/anytype types are " + "compatible only with other " + "union/CHOICE/anytype types")); + return false; + case T_SET_A: + case T_SET_T: + case T_SETOF: + p_info->set_is_erroneous(this, p_type, string("set/SET and set of/SET OF " + "types are compatible only with other set/SET " + "set of/SET OF types")); + return false; + default: + return false; + } + } + + bool Type::is_compatible_set(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain, + TypeChain *p_right_chain) + { + if (typetype != T_SET_A && typetype != T_SET_T) + FATAL_ERROR("Type::is_compatible_set()"); + if (this == p_type) return true; + else if (!use_runtime_2 || !p_info + || (p_info && p_info->is_strict())) return false; + size_t nof_comps = get_nof_comps(); + switch (p_type->typetype) { + case T_SET_A: + case T_SET_T: { + // The standard is very generous. We don't need to check for a possible + // combination of compatible fields. According to 6.3.2.3, simply do + // the same thing as for T_SEQ_{A,T} types. The fields are in their + // textual order. + size_t p_nof_comps = p_type->get_nof_comps(); + if (nof_comps != p_nof_comps) { + p_info->set_is_erroneous(this, p_type, string("The number of fields in " + "set/SET types must be the same")); + return false; + } + if (p_left_chain->empty()) p_left_chain->add(this); + if (p_right_chain->empty()) p_right_chain->add(p_type); + for (size_t i = 0; i < nof_comps; i++) { + CompField *cf = get_comp_byIndex(i); + CompField *p_cf = p_type->get_comp_byIndex(i); + Type *cf_type = cf->get_type()->get_type_refd_last(); + Type *p_cf_type = p_cf->get_type()->get_type_refd_last(); + string cf_name = cf->get_name().get_dispname(); + string p_cf_name = p_cf->get_name().get_dispname(); + if (cf->get_is_optional() != p_cf->get_is_optional()) { + p_info->append_ref_str(0, "." + cf_name); + p_info->append_ref_str(1, "." + p_cf_name); + p_info->set_is_erroneous(cf_type, p_cf_type, string("The optionality of " + "fields in set/SET types must be the " + "same")); + return false; + } + TypeCompatInfo info_tmp(p_info->get_my_module(), cf_type, p_cf_type, + false, false); + p_left_chain->mark_state(); + p_right_chain->mark_state(); + p_left_chain->add(cf_type); + p_right_chain->add(p_cf_type); + if (cf_type != p_cf_type + && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) + && !cf_type->is_compatible(p_cf_type, &info_tmp, p_left_chain, + p_right_chain)) { + p_info->append_ref_str(0, "." + cf_name + info_tmp.get_ref_str(0)); + p_info->append_ref_str(1, "." + p_cf_name + info_tmp.get_ref_str(1)); + p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), + info_tmp.get_error_str()); + p_left_chain->previous_state(); + p_right_chain->previous_state(); + return false; + } + p_left_chain->previous_state(); + p_right_chain->previous_state(); + } + p_info->set_needs_conversion(true); + p_info->add_type_conversion(p_type, this); + return true; } + case T_SETOF: { + if (!p_type->is_subtype_length_compatible(this)) { + p_info->set_is_erroneous(this, p_type, string("Incompatible set of/SET OF " + "subtypes")); + return false; + } + if (p_left_chain->empty()) p_left_chain->add(this); + if (p_right_chain->empty()) p_right_chain->add(p_type); + Type *p_of_type = p_type->get_ofType()->get_type_refd_last(); + for (size_t i = 0; i < nof_comps; i++) { + Type *cf_type = get_comp_byIndex(i)->get_type()->get_type_refd_last(); + TypeCompatInfo info_tmp(p_info->get_my_module(), cf_type, p_of_type, + false, false); + p_left_chain->mark_state(); + p_right_chain->mark_state(); + p_left_chain->add(cf_type); + p_right_chain->add(p_of_type); + if (cf_type != p_of_type + && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) + && !cf_type->is_compatible(p_of_type, &info_tmp, p_left_chain, + p_right_chain)) { + p_info->append_ref_str(0, "." + get_comp_byIndex(i) + ->get_name().get_dispname() + info_tmp.get_ref_str(0)); + p_info->append_ref_str(1, "[]" + info_tmp.get_ref_str(1)); + p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), + info_tmp.get_error_str()); + p_left_chain->previous_state(); + p_right_chain->previous_state(); + return false; + } + p_left_chain->previous_state(); + p_right_chain->previous_state(); + } + p_info->set_needs_conversion(true); + p_info->add_type_conversion(p_type, this); + return true; } + case T_CHOICE_A: + case T_CHOICE_T: + case T_ANYTYPE: + p_info->set_is_erroneous(this, p_type, string("union/CHOICE/anytype types are " + "compatible only with other " + "union/CHOICE/anytype types")); + return false; + case T_SEQ_A: + case T_SEQ_T: + case T_SEQOF: + case T_ARRAY: + p_info->set_is_erroneous(this, p_type, string("set/SET and set of/SET OF " + "types are compatible only with other set/SET " + "set of/SET OF types")); + return false; + default: + return false; + } + } + + bool Type::is_compatible_set_of(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain, + TypeChain *p_right_chain) + { + if (typetype != T_SETOF) FATAL_ERROR("Type::is_compatible_set_of()"); + if (this == p_type) return true; + else if (!use_runtime_2 || !p_info + || (p_info && p_info->is_strict())) return false; + Type *of_type = get_ofType(); + switch (p_type->get_typetype()) { + case T_SET_A: + case T_SET_T: { + if (!is_subtype_length_compatible(p_type)) { + p_info->set_is_erroneous(this, p_type, string("Incompatible set of/SET OF " + "subtypes")); + return false; + } + if (p_left_chain->empty()) p_left_chain->add(this); + if (p_right_chain->empty()) p_right_chain->add(p_type); + for (size_t i = 0; i < p_type->get_nof_comps(); i++) { + CompField *p_cf = p_type->get_comp_byIndex(i); + Type *p_cf_type = p_cf->get_type()->get_type_refd_last(); + TypeCompatInfo info_tmp(p_info->get_my_module(), of_type, p_cf_type, + false, false); + p_left_chain->mark_state(); + p_right_chain->mark_state(); + p_left_chain->add(of_type); + p_right_chain->add(p_cf_type); + if (of_type != p_cf_type + && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) + && !of_type->is_compatible(p_cf_type, &info_tmp, p_left_chain, + p_right_chain)) { + p_info->append_ref_str(0, "[]" + info_tmp.get_ref_str(0)); + p_info->append_ref_str(1, "." + p_cf->get_name().get_dispname() + + info_tmp.get_ref_str(1)); + p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), + info_tmp.get_error_str()); + p_left_chain->previous_state(); + p_right_chain->previous_state(); + return false; + } + p_left_chain->previous_state(); + p_right_chain->previous_state(); + } + p_info->set_needs_conversion(true); + p_info->add_type_conversion(p_type, this); + return true; } + case T_SETOF: { + if (!is_subtype_length_compatible(p_type)) { + p_info->set_is_erroneous(this, p_type, string("Incompatible set of/SET OF " + "subtypes")); + return false; + } + if (p_left_chain->empty()) p_left_chain->add(this); + if (p_right_chain->empty()) p_right_chain->add(p_type); + Type *p_of_type = p_type->get_ofType()->get_type_refd_last(); + TypeCompatInfo info_tmp(p_info->get_my_module(), of_type, p_of_type, + false, false); + p_left_chain->mark_state(); + p_right_chain->mark_state(); + p_left_chain->add(of_type); + p_right_chain->add(p_of_type); + if (of_type == p_of_type + || (p_left_chain->has_recursion() && p_right_chain->has_recursion()) + || of_type->is_compatible(p_of_type, &info_tmp, p_left_chain, + p_right_chain)) { + p_info->set_needs_conversion(true); + p_info->add_type_conversion(p_type, this); + p_left_chain->previous_state(); + p_right_chain->previous_state(); + return true; + } + p_info->append_ref_str(0, "[]" + info_tmp.get_ref_str(0)); + p_info->append_ref_str(1, "[]" + info_tmp.get_ref_str(1)); + p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), + info_tmp.get_error_str()); + p_left_chain->previous_state(); + p_right_chain->previous_state(); + return false; } + case T_CHOICE_A: + case T_CHOICE_T: + case T_ANYTYPE: + p_info->set_is_erroneous(this, p_type, string("union/CHOICE/anytype " + "types are compatible only with other " + "union/CHOICE/anytype types")); + return false; + case T_SEQ_A: + case T_SEQ_T: + case T_SEQOF: + case T_ARRAY: + p_info->set_is_erroneous(this, p_type, string("set/SET and set of/SET OF " + "types are compatible only with other set/SET " + "set of/SET OF types")); + return false; + default: + return false; + } + } + + bool Type::is_compatible_choice_anytype(Type *p_type, + TypeCompatInfo *p_info, + TypeChain *p_left_chain, + TypeChain *p_right_chain) + { + if (typetype != T_ANYTYPE && typetype != T_CHOICE_A + && typetype != T_CHOICE_T) + FATAL_ERROR("Type::is_compatible_choice_anytype()"); + if (this == p_type) return true; // Original "true" leaf... + else if (!use_runtime_2 || !p_info + || (p_info && p_info->is_strict())) return false; // ...and "false". + if ((typetype == T_ANYTYPE && p_type->get_typetype() != T_ANYTYPE) + || (p_type->get_typetype() == T_ANYTYPE && typetype != T_ANYTYPE)) { + p_info->set_is_erroneous(this, p_type, string("Type anytype is compatible only " + "with other anytype types")); + return false; + } + switch (p_type->get_typetype()) { + case T_SEQ_A: + case T_SEQ_T: + case T_SEQOF: + case T_ARRAY: + case T_SET_A: + case T_SET_T: + case T_SETOF: + p_info->set_is_erroneous(this, p_type, string("union/CHOICE/anytype types are " + "compatible only with other union/CHOICE/anytype " + "types")); + return false; + case T_CHOICE_A: + case T_CHOICE_T: + if (typetype != T_CHOICE_A && typetype != T_CHOICE_T) { + p_info->set_is_erroneous(this, p_type, string("union/CHOICE types are " + "compatible only with other union/CHOICE " + "types")); + return false; + } + // no break + case T_ANYTYPE: { + if (p_left_chain->empty()) p_left_chain->add(this); + if (p_right_chain->empty()) p_right_chain->add(p_type); + // Find a field with the same name and with compatible type. There can + // be more alternatives, we need to generate all conversion functions. + // The same field types must be avoided. (For anytypes the "field + // name = module name + field name".) + bool alles_okay = false; + for (size_t i = 0; i < get_nof_comps(); i++) { + CompField *cf = get_comp_byIndex(i); + Type *cf_type = cf->get_type()->get_type_refd_last(); + for (size_t j = 0; j < p_type->get_nof_comps(); ++j) { + CompField *p_cf = p_type->get_comp_byIndex(j); + Type *p_cf_type = p_cf->get_type()->get_type_refd_last(); + if (cf->get_name().get_name() != p_cf->get_name().get_name()) + continue; + // Don't report errors for each incompatible field, it would be a + // complete mess. Use this temporary for all fields. And forget + // the contents. + TypeCompatInfo info_tmp(p_info->get_my_module(), cf_type, p_cf_type, + false, false); + p_left_chain->mark_state(); + p_right_chain->mark_state(); + p_left_chain->add(cf_type); + p_right_chain->add(p_cf_type); + if (cf_type == p_cf_type + || (p_left_chain->has_recursion() && p_right_chain->has_recursion()) + || cf_type->is_compatible(p_cf_type, &info_tmp, p_left_chain, + p_right_chain)) { + if (cf_type != p_cf_type && cf_type->is_structured_type() + && p_cf_type->is_structured_type()) { + if (typetype == T_ANYTYPE && cf_type->get_my_scope() + ->get_scope_mod() != p_cf_type->get_my_scope() + ->get_scope_mod()) { + p_left_chain->previous_state(); + p_right_chain->previous_state(); + continue; + } + p_info->add_type_conversion(p_cf_type, cf_type); + } + alles_okay = true; + } + p_left_chain->previous_state(); + p_right_chain->previous_state(); + } + } + if (alles_okay) { + p_info->set_needs_conversion(true); + p_info->add_type_conversion(p_type, this); + return true; + } + p_info->set_is_erroneous(this, p_type, string("No compatible " + "union/CHOICE/anytype field found")); + return false; + } + default: + return false; + } + } + + /** \todo consider subtype constraints */ + bool Type::is_identical(Type *p_type) + { + chk(); + p_type->chk(); + Type *t1 = get_type_refd_last(); + Type *t2 = p_type->get_type_refd_last(); + if (t2->typetype == T_ERROR) return true; + switch (t1->typetype) { + case T_ERROR: + // error type is identical to everything + return true; + case T_ENUM_A: + case T_ENUM_T: + case T_CHOICE_T: + case T_CHOICE_A: + case T_ANYTYPE: + case T_SEQOF: + case T_SETOF: + case T_SEQ_A: + case T_SEQ_T: + case T_SET_A: + case T_SET_T: + case T_SIGNATURE: + case T_PORT: + case T_COMPONENT: + case T_OPENTYPE: + case T_FUNCTION: + case T_ALTSTEP: + case T_TESTCASE: + // user-defined structured types must be identical + return t1 == t2; + case T_ARRAY: + // the embedded type and the dimension must be identical in case of arrays + return t2->typetype == T_ARRAY && + t1->u.array.element_type->is_identical(t2->u.array.element_type) && + t1->u.array.dimension->is_identical(t2->u.array.dimension); + default: + // in case of built-in types the TTCN-3 view of typetype must be the same + return get_typetype_ttcn3(t1->typetype) == + get_typetype_ttcn3(t2->typetype); + } + } + + void Type::tr_compsof(ReferenceChain *refch) + { + if (typetype!=T_SEQ_A && typetype!=T_SET_A) + FATAL_ERROR("Type::tr_compsof()"); + if (u.secho.tr_compsof_ready) return; + if (u.secho.block) parse_block_Se(); + bool auto_tagging=u.secho.ctss->needs_auto_tags(); + if (refch) { + refch->mark_state(); + if (refch->add(get_fullname())) u.secho.ctss->tr_compsof(refch, false); + refch->prev_state(); + u.secho.tr_compsof_ready = true; + u.secho.ctss->tr_compsof(0, true); + } else { + ReferenceChain refch2(this, "While resolving COMPONENTS OF"); + refch2.add(get_fullname()); + Error_Context cntxt(this, "While resolving COMPONENTS OF"); + u.secho.ctss->tr_compsof(&refch2, false); + u.secho.tr_compsof_ready = true; + u.secho.ctss->tr_compsof(0, true); + } + if(auto_tagging) u.secho.ctss->add_auto_tags(); + } + + bool Type::is_startable() + { + if(typetype != T_FUNCTION) + FATAL_ERROR("Type::is_startable()"); + if(!checked) chk(); + return u.fatref.is_startable; + } + + bool Type::is_list_type(bool allow_array) + { + switch (get_type_refd_last()->get_typetype_ttcn3()) { + case Type::T_ARRAY: + return allow_array; + case Type::T_CSTR: + case Type::T_USTR: + case Type::T_BSTR: + case Type::T_HSTR: + case Type::T_OSTR: + case Type::T_SEQOF: + case Type::T_SETOF: + return true; + default: + return false; + } + } + + void Type::chk_coding(bool encode) { + string& coding_str = encode ? encoding_str : decoding_str; + if (!coding_str.empty()) + return; + coding_by_function = false; + + if (!w_attrib_path) { + error("No coding rule specified for type '%s'", get_typename().c_str()); + return; + } + Type::MessageEncodingType_t coding = CT_UNDEF; + + // Checking extension attributes + Ttcn::ExtensionAttributes * extatrs = parse_extattributes(w_attrib_path); + if (extatrs != 0) { // NULL means parsing error + for (size_t k = 0; k < extatrs->size(); ++k) { + Ttcn::ExtensionAttribute &ea = extatrs->get(k); + Ttcn::TypeMappings *inmaps = 0, *maps = 0; + Ttcn::TypeMapping* mapping = 0; + Ttcn::TypeMappingTarget* target = 0; + Type* t = 0; + switch (ea.get_type()) { + case Ttcn::ExtensionAttribute::ENCDECVALUE: + ea.get_encdecvalue_mappings(inmaps, maps); + maps = encode ? maps : inmaps; + maps->set_my_scope(this->get_my_scope()); + maps->chk(); + // look for coding settings + t = encode ? this : Type::get_pooltype(T_BSTR); + mapping = maps->get_mapping_byType(t); + if (mapping->get_nof_targets() == 0) + goto end_ext; + else { + for (size_t ind = 0; ind < mapping->get_nof_targets(); ind++) { + target = mapping->get_target_byIndex(ind); + t = target->get_target_type(); + if ((encode && (t->get_typetype() == T_BSTR)) || + (!encode && (t->get_typename() == this->get_typename()))) + { + if (target->get_mapping_type() == + Ttcn::TypeMappingTarget::TM_FUNCTION) { + if (!coding_str.empty()) + target->error("Multiple definition of this target"); + coding_str = target->get_function()-> + get_genname_from_scope(my_scope); + coding_by_function = true; + } else { + target->error("Only function is supported to do this mapping"); + } + } + } + if (coding_str.empty()) { + ea.warning("Extension attribute is found for %s but without " + "typemappings", encode ? "encvalue" : "decvalue"); + } + } + break; + + case Ttcn::ExtensionAttribute::ANYTYPELIST: + break; // ignore (may be inherited from the module) + + case Ttcn::ExtensionAttribute::NONE: + break; // ignore erroneous attribute + + default: + ea.error("A type can only have type mapping extension attribute: " + "in(...) or out(...)"); + break; + } + } + delete extatrs; + } + + if (!coding_str.empty()) + return; +end_ext: + + const vector& real_attribs + = w_attrib_path->get_real_attrib(); + bool found = false; + for (size_t i = real_attribs.size(); i > 0 && !found; i--) { + if (real_attribs[i-1]->get_attribKeyword() + == SingleWithAttrib::AT_ENCODE) { + found = true; + coding = get_enc_type(*real_attribs[i-1]); + if (coding == CT_UNDEF) { + // "encode" attribute found, but the spec didn't match any known encodings + error("Unknown encoding '%s'", real_attribs[i-1]->get_attribSpec().get_spec().c_str()); + return; + } + } + } + if (coding == CT_UNDEF) { + // no "encode" attribute found + error("No coding rule specified for type '%s'", get_typename().c_str()); + return; + } + if (!has_encoding(coding)) { + error("Type '%s' cannot be coded with the selected method '%s'", + get_typename().c_str(), + get_encoding_name(coding)); + return; + } + switch (coding) { + case CT_RAW: + coding_str = "RAW"; + break; + case CT_TEXT: + coding_str = "TEXT"; + break; + case CT_PER: + coding_str = "PER"; + break; + case CT_XER: + coding_str = "XER, XER_EXTENDED"; // TODO: fine tuning this parameter + break; + case CT_JSON: + coding_str = "JSON"; + break; + case CT_BER: { + coding_str = "BER, "; + BerAST* ber = berattrib; + if (!ber) // use default settings if attributes are not specified + ber = new BerAST; + if (encode) + coding_str += ber->get_encode_str(); + else + coding_str += ber->get_decode_str(); + if (!berattrib) + delete ber; + break; } + default: + error("Unknown coding selected for type '%s'", get_typename().c_str()); + break; + } + coding_by_function = false; + } + + bool Type::is_coding_by_function() const { + return coding_by_function; + } + + const string& Type::get_coding(bool encode) const { + if (encode) + return encoding_str; + else + return decoding_str; + } + + namespace { // unnamed + const string ex_emm_ell("XML"), ex_ee_arr("XER"); + } + + Type::MessageEncodingType_t Type::get_enc_type(const SingleWithAttrib& atr) { + const string& enc = atr.get_attribSpec().get_spec(); + if (enc == "RAW") + return CT_RAW; + else if (enc == "TEXT") + return CT_TEXT; + else if (enc == "JSON") + return CT_JSON; + else if (enc == "BER:2002" || enc == "CER:2002" || enc == "DER:2002") + return CT_BER; + else if (enc == ex_emm_ell) + return CT_XER; + else if (enc == ex_ee_arr) { + atr.warning("The correct name of the encoding is ''XML''"); + return CT_XER; + } + else if (enc == "PER") + return CT_PER; + else + return CT_UNDEF; + } + bool Type::has_ei_withName(const Identifier& p_id) const + { + switch (typetype) { + case T_ENUM_T: + case T_ENUM_A: + if (checked) break; + // no break + default: + FATAL_ERROR("Type::has_ei_withName()"); + } + return u.enums.eis->has_ei_withName(p_id); + } + + EnumItem *Type::get_ei_byName(const Identifier& p_id) const + { + switch (typetype) { + case T_ENUM_T: + case T_ENUM_A: + if (checked) break; + // no break + default: + FATAL_ERROR("Type::get_ei_byName()"); + } + return u.enums.eis->get_ei_byName(p_id); + } + + EnumItem *Type::get_ei_byIndex(size_t n) const + { + switch (typetype) { + case T_ENUM_T: + case T_ENUM_A: + if (checked) break; + // no break + default: + FATAL_ERROR("Type::get_ei_byIndex()"); + } + return u.enums.eis->get_ei_byIndex(n); + } + + size_t Type::get_nof_comps() + { + switch(typetype) { + case T_ANYTYPE: + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + case T_OPENTYPE: + return u.secho.cfm->get_nof_comps(); + case T_SEQ_A: + case T_SET_A: + if(u.secho.block) parse_block_Se(); + return u.secho.ctss->get_nof_comps(); + case T_CHOICE_A: + if(u.secho.block) parse_block_Choice(); + return u.secho.ctss->get_nof_comps(); + case T_ARRAY: + return u.array.dimension->get_size(); + case T_SIGNATURE: + if (u.signature.parameters) + return u.signature.parameters->get_nof_params(); + else return 0; + default: + FATAL_ERROR("Type::get_nof_comps(%d)", typetype); + return 0; + } // switch + } + + const Identifier& Type::get_comp_id_byIndex(size_t n) + { + switch (typetype) { + case T_ANYTYPE: + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + case T_OPENTYPE: + return u.secho.cfm->get_comp_byIndex(n)->get_name(); + case T_SEQ_A: + case T_SET_A: + if(u.secho.block) parse_block_Se(); + return u.secho.ctss->get_comp_byIndex(n)->get_name(); + case T_CHOICE_A: + if(u.secho.block) parse_block_Choice(); + return u.secho.ctss->get_comp_byIndex(n)->get_name(); + case T_SIGNATURE: + return u.signature.parameters->get_param_byIndex(n)->get_id(); + default: + FATAL_ERROR("Type::get_comp_id_byIndex()"); + } // switch + // to avoid warnings + const Identifier *fake = 0; + return *fake; + } + + CompField* Type::get_comp_byIndex(size_t n) + { + switch(typetype) { + case T_ANYTYPE: + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + case T_OPENTYPE: + return u.secho.cfm->get_comp_byIndex(n); + case T_SEQ_A: + case T_SET_A: + if(u.secho.block) parse_block_Se(); + return u.secho.ctss->get_comp_byIndex(n); + case T_CHOICE_A: + if(u.secho.block) parse_block_Choice(); + return u.secho.ctss->get_comp_byIndex(n); + default: + FATAL_ERROR("Type::get_comp_byIndex()"); + return 0; + } // switch + } + + size_t Type::get_comp_index_byName(const Identifier& p_name) + { + Type *t = get_type_refd_last(); + if (!t->is_secho()) + FATAL_ERROR("Type::get_comp_index_byName()"); + if (!t->u.secho.field_by_name) { + t->u.secho.field_by_name = new map; + size_t nof_comps = t->get_nof_comps(); + for (size_t i = 0; i < nof_comps; i++) { + const string& field_name = + t->get_comp_byIndex(i)->get_name().get_name(); + if (!t->u.secho.field_by_name->has_key(field_name)) + t->u.secho.field_by_name->add(field_name, new size_t(i)); + } + } + return *(*t->u.secho.field_by_name)[p_name.get_name()]; + } + + size_t Type::get_eis_index_byName(const Identifier& p_name) + { + Type *t = get_type_refd_last(); + switch (t->typetype) { + case T_ENUM_A: + case T_ENUM_T: + break; + default: + FATAL_ERROR("Type::get_eis_index_byName()"); + } + if (!t->u.enums.eis_by_name) { + t->u.enums.eis_by_name = new map; + size_t nof_eis = t->u.enums.eis->get_nof_eis(); + for (size_t i = 0; i < nof_eis; i++) { + const string& enum_name = + t->u.enums.eis->get_ei_byIndex(i)->get_name().get_name(); + if (!t->u.enums.eis_by_name->has_key(enum_name)) + t->u.enums.eis_by_name->add(enum_name, new size_t(i)); + } + } + return *(*t->u.enums.eis_by_name)[p_name.get_name()]; + } + + const Int& Type::get_enum_val_byId(const Identifier& p_name) + { + if(!checked) FATAL_ERROR("Type::get_enum_val_byId(): Not checked."); + switch(typetype) { + case T_ENUM_T: + case T_ENUM_A: + break; + default: + FATAL_ERROR("Type::get_enum_val_byId()"); + } + return u.enums.eis->get_ei_byName(p_name)->get_value() + ->get_value_refd_last()->get_val_Int()->get_val(); + } + + size_t Type::get_nof_root_comps() + { + switch(typetype) { + case T_SEQ_A: + case T_SET_A: + if(u.secho.block) parse_block_Se(); + return u.secho.ctss->get_nof_root_comps(); + break; + default: + FATAL_ERROR("Type::get_nof_root_comps()"); + return 0; + } // switch + } + + CompField* Type::get_root_comp_byIndex(size_t n) + { + switch(typetype) { + case T_SEQ_A: + case T_SET_A: + if(u.secho.block) parse_block_Se(); + return u.secho.ctss->get_root_comp_byIndex(n); + break; + default: + FATAL_ERROR("Type::get_root_comp_byIndex()"); + return 0; + } // switch + } + + bool Type::has_comp_withName(const Identifier& p_name) + { + Type *t = get_type_refd_last(); + switch (t->typetype) { + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + case T_OPENTYPE: + case T_ANYTYPE: + return t->u.secho.cfm->has_comp_withName(p_name); + case T_SEQ_A: + case T_SET_A: + if (t->u.secho.block) t->parse_block_Se(); + return t->u.secho.ctss->has_comp_withName(p_name); + case T_CHOICE_A: + if (t->u.secho.block) t->parse_block_Choice(); + return t->u.secho.ctss->has_comp_withName(p_name); + case T_SIGNATURE: + if (t->u.signature.parameters) + return t->u.signature.parameters->has_param_withName(p_name); + else return false; + default: + FATAL_ERROR("Type::has_comp_withName()"); + return 0; + } // switch + } + + CompField* Type::get_comp_byName(const Identifier& p_name) + { + Type *t = get_type_refd_last(); + switch (t->typetype) { + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + case T_OPENTYPE: + case T_ANYTYPE: + return t->u.secho.cfm->get_comp_byName(p_name); + case T_SEQ_A: + case T_SET_A: + if (t->u.secho.block) t->parse_block_Se(); + return t->u.secho.ctss->get_comp_byName(p_name); + case T_CHOICE_A: + if(t->u.secho.block) t->parse_block_Choice(); + return t->u.secho.ctss->get_comp_byName(p_name); + default: + FATAL_ERROR("Type::get_comp_byName()"); + return 0; + } // switch + } + + void Type::add_comp(CompField *p_cf) + { + switch(typetype) { + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + case T_OPENTYPE: + case T_ANYTYPE: + u.secho.cfm->add_comp(p_cf); + break; + default: + FATAL_ERROR("Type::add_comp()"); + } // switch + } + + Type *Type::get_ofType() + { + Type *t=get_type_refd_last(); + switch (t->typetype) { + case T_SEQOF: + case T_SETOF: + return t->u.seof.ofType; + case T_ARRAY: + return t->u.array.element_type; + default: + FATAL_ERROR("Type::get_ofType()"); + return 0; + } + } + + OC_defn* Type::get_my_oc() + { + switch(typetype) { + case T_OCFT: + return u.ref.oc_defn; + break; + case T_OPENTYPE: + return u.secho.oc_defn; + break; + default: + FATAL_ERROR("Type::get_my_oc()"); + return 0; + } // switch + } + + const Identifier& Type::get_oc_fieldname() + { + switch(typetype) { + case T_OCFT: + return *u.ref.oc_fieldname; + break; + case T_OPENTYPE: + return *u.secho.oc_fieldname; + break; + default: + FATAL_ERROR("Type::get_oc_fieldname()"); + // to avoid warning... + return *u.secho.oc_fieldname; + } // switch + } + + void Type::set_my_tableconstraint(const TableConstraint *p_tc) + { + switch(typetype) { + case T_OPENTYPE: + u.secho.my_tableconstraint=p_tc; + break; + default: + FATAL_ERROR("Type::set_my_tableconstraint()"); + } // switch + } + + const TableConstraint* Type::get_my_tableconstraint() + { + switch(typetype) { + case T_OPENTYPE: + return u.secho.my_tableconstraint; + break; + default: + FATAL_ERROR("Type::get_my_tableconstraint()"); + return 0; + } // switch + } + + Ttcn::ArrayDimension *Type::get_dimension() const + { + if (typetype != T_ARRAY) FATAL_ERROR("Type::get_dimension()"); + return u.array.dimension; + } + + Ttcn::PortTypeBody *Type::get_PortBody() const + { + if (typetype != T_PORT) FATAL_ERROR("Type::get_PortBody()"); + return u.port; + } + + ComponentTypeBody *Type::get_CompBody() const + { + if (typetype != T_COMPONENT) FATAL_ERROR("Type::get_CompBody()"); + return u.component; + } + + SignatureParamList *Type::get_signature_parameters() const + { + if (typetype != T_SIGNATURE || !checked) + FATAL_ERROR("Type::get_signature_parameters()"); + return u.signature.parameters; + } + + SignatureExceptions *Type::get_signature_exceptions() const + { + if (typetype != T_SIGNATURE || !checked) + FATAL_ERROR("Type::get_signature_exceptions()"); + return u.signature.exceptions; + } + + Type *Type::get_signature_return_type() const + { + if (typetype != T_SIGNATURE || !checked) + FATAL_ERROR("Type::get_signature_return_type()"); + return u.signature.return_type; + } + + bool Type::is_nonblocking_signature() const + { + if (typetype != T_SIGNATURE || !checked) + FATAL_ERROR("Type::is_nonblocking_signature()"); + return u.signature.no_block; + } + + Ttcn::FormalParList *Type::get_fat_parameters() + { + if(!checked) FATAL_ERROR("Type::get_fat_parameteres()"); + switch(typetype) { + case T_FUNCTION: + case T_ALTSTEP: + case T_TESTCASE: + return u.fatref.fp_list; + default: + FATAL_ERROR("Type::get_fat_parameteres()"); + return 0; + } + } + + Type *Type::get_function_return_type() + { + if(!checked) FATAL_ERROR("Type::get_function_return_type()"); + switch(typetype) { + case T_FUNCTION: + return u.fatref.return_type; + default: + FATAL_ERROR("Type::get_function_return_type()"); + return 0; + } + } + + Type *Type::get_fat_runs_on_type() + { + if(!checked) FATAL_ERROR("Type::get_fat_runs_on_type()"); + switch(typetype) { + case T_FUNCTION: + case T_ALTSTEP: + case T_TESTCASE: + return u.fatref.runs_on.type; + default: + FATAL_ERROR("Type::get_fat_runs_on_type()"); + return 0; + } + } + + bool Type::get_fat_runs_on_self() + { + if(!checked) FATAL_ERROR("Type::get_fat_runs_on_self()"); + switch(typetype) { + case T_FUNCTION: + case T_ALTSTEP: + case T_TESTCASE: + return u.fatref.runs_on.self; + default: + FATAL_ERROR("Type::get_fat_runs_on_self()"); + return false; + } + } + + bool Type::get_returns_template() + { + if (!checked || typetype != T_FUNCTION) + FATAL_ERROR("Type::Returns_template()"); + return u.fatref.returns_template; + } + + void Type::add_tag(Tag *p_tag) + { + if(!tags) tags=new Tags(); + tags->add_tag(p_tag); + } + + void Type::add_constraints(Constraints *p_constraints) + { + if(!p_constraints) return; + if(constraints) + FATAL_ERROR("This type already has its constraints"); + constraints=p_constraints; + constraints->set_my_type(this); + } + + Reference* Type::get_Reference() + { + return u.ref.ref; + } + + void Type::chk_table_constraints() + { + if(!tbl_cons_checked) { + tbl_cons_checked=true; + if (constraints) constraints->chk_table(); + switch (typetype) { + case T_CHOICE_A: + case T_CHOICE_T: + case T_SEQ_A: + case T_SEQ_T: + case T_SET_A: + case T_SET_T: + case T_OPENTYPE: + for(size_t i=0; iget_type()->chk_table_constraints(); + break; + case T_SEQOF: + case T_SETOF: + u.seof.ofType->chk_table_constraints(); + break; + default: + break; + } + } + } + + void Type::check_subtype_constraints() + { + if (sub_type!=NULL) FATAL_ERROR("Type::check_subtype_constraints()"); + + // get parent subtype or NULL if it doesn't exist + SubType* parent_subtype = NULL; + if (is_ref()) parent_subtype = get_type_refd()->sub_type; + + // if the parent subtype is erroneous then ignore it, the error was already + // reported there + if ( (parent_subtype!=NULL) && + (parent_subtype->get_subtypetype()==SubtypeConstraint::ST_ERROR) ) + parent_subtype = NULL; + + // return if there are neither inherited nor own constraints + if ( (parent_subtype==NULL) && (parsed_restr==NULL) && (constraints==NULL) + && (SubtypeConstraint::get_asn_type_constraint(this)==NULL) ) return; + + // the subtype type is determined by the type of this type + if (get_type_refd_last()->get_typetype()==T_ERROR) return; + SubtypeConstraint::subtype_t s_t = get_subtype_type(); + if (s_t==SubtypeConstraint::ST_ERROR) { + error("Subtype constraints are not applicable to type `%s'", + get_typename().c_str()); + return; + } + + // create the aggregate subtype for this type + sub_type = new SubType(s_t, this, parent_subtype, parsed_restr, constraints); + sub_type->chk(); + } + + bool Type::has_multiple_tags() + { + if (tags) return false; + switch (typetype) { + case T_CHOICE_A: + case T_CHOICE_T: + return true; + case T_REFD: + case T_SELTYPE: + case T_REFDSPEC: + case T_OCFT: + return get_type_refd()->has_multiple_tags(); + default: + return false; + } + } + + Tag *Type::get_tag() + { + if (tags) { + Tag *tag=tags->get_tag_byIndex(tags->get_nof_tags()-1); + tag->chk(); + return tag; + } + else return get_default_tag(); + } + + void Type::get_tags(TagCollection& coll, map& chain) + { + if(typetype!=T_CHOICE_A) + FATAL_ERROR("Type::get_tags()"); + if (chain.has_key(this)) return; + chain.add(this, 0); + if(u.secho.block) parse_block_Choice(); + size_t n_alts = u.secho.ctss->get_nof_comps(); + for(size_t i=0; iget_comp_byIndex(i); + Type *type = cf->get_type(); + if(type->has_multiple_tags()) { + type=type->get_type_refd_last(); + type->get_tags(coll, chain); + } + else { + const Tag *tag=type->get_tag(); + if(coll.hasTag(tag)) + error("Alternative `%s' in CHOICE has non-distinct tag", + cf->get_name().get_dispname().c_str()); + else coll.addTag(tag); + } + } // for i + if(u.secho.ctss->has_ellipsis()) coll.setExtensible(); + } + + Tag *Type::get_smallest_tag() + { + if(!has_multiple_tags()) return get_tag()->clone(); + Type *t=get_type_refd_last(); + TagCollection tagcoll; + map chain; + t->get_tags(tagcoll, chain); + chain.clear(); + return tagcoll.getSmallestTag()->clone(); + } + + bool Type::needs_explicit_tag() + { + switch (typetype) { + case T_CHOICE_A: + case T_CHOICE_T: + case T_ANY: + case T_OPENTYPE: + return true; + case T_REFD: { + if(!dynamic_cast(u.ref.ref)) { + Scope *s=u.ref.ref->get_refd_assignment()->get_my_scope(); + if(s->get_parent_scope()!=s->get_scope_mod()) { + // Not in the module scope, so it is a dummyreference (X.680 + // 30.6c) + /* + WARNING("%s is a dummyreference, i give him an explicit tag :)", + get_fullname().c_str()); + WARNING("0: %s", s->get_scope_name().c_str()); + WARNING("1: %s", s->get_parent_scope()->get_scope_name().c_str()); + WARNING("2: %s", s->get_scope_mod()->get_scope_name().c_str()); + */ + return true; + } + } + // no break; + } // case T_REFD + case T_SELTYPE: + case T_REFDSPEC: + case T_OCFT: { + Type *t = get_type_refd(); + if(t->is_tagged()) return false; + else return t->needs_explicit_tag(); + break;} + default: + // T_ANYTYPE probably does not need explicit tagging + return false; + } + } + + void Type::cut_auto_tags() + { + if (tags) { + tags->cut_auto_tags(); + if (tags->get_nof_tags() == 0) { + delete tags; + tags = 0; + } + } + } + + /** + * I suppose in this function that tags->chk() and + * tags->set_plicit() are already done. + */ + Tags* Type::build_tags_joined(Tags *p_tags) + { + if(!p_tags) p_tags=new Tags(); + switch(typetype) { + // is_ref() true: + case T_REFD: + case T_SELTYPE: + case T_REFDSPEC: + case T_OCFT: + get_type_refd()->build_tags_joined(p_tags); + break; + case T_CHOICE_A: + case T_CHOICE_T: + //TODO case T_ANYTYPE: for build_tags_joined ? + case T_OPENTYPE: + case T_ANY: + break; + default: + p_tags->add_tag(get_default_tag()->clone()); + break; + } // switch + if(tags) { + for(size_t i=0; iget_nof_tags(); i++) { + Tag *tag=tags->get_tag_byIndex(i); + switch(tag->get_plicit()) { + case Tag::TAG_EXPLICIT: + p_tags->add_tag(tag->clone()); + break; + case Tag::TAG_IMPLICIT: { + Tag *t_p_tag=p_tags->get_tag_byIndex(p_tags->get_nof_tags()-1); + t_p_tag->set_tagclass(tag->get_tagclass()); + t_p_tag->set_tagvalue(tag->get_tagvalue()); + break;} + default: + FATAL_ERROR("Type::build_tags_joined()"); + } // switch + } // for + } // if tags + return p_tags; + } + + void Type::set_with_attr(Ttcn::MultiWithAttrib* p_attrib) + { + if(!w_attrib_path) + { + w_attrib_path = new WithAttribPath(); + } + + w_attrib_path->set_with_attr(p_attrib); + } + + void Type::set_parent_path(WithAttribPath* p_path) + { + if(!w_attrib_path) + { + w_attrib_path = new WithAttribPath(); + } + w_attrib_path->set_parent(p_path); + if (typetype == T_COMPONENT) + u.component->set_parent_path(w_attrib_path); + } + + WithAttribPath* Type::get_attrib_path() const + { + return w_attrib_path; + } + + bool Type::hasRawAttrs() + { + if(rawattrib) return true; + + if(w_attrib_path) + { + if(w_attrib_path->get_had_global_variants()) return true; + + vector const &real_attribs + = w_attrib_path->get_real_attrib(); + + for (size_t i = 0; i < real_attribs.size(); i++) + if (real_attribs[i]->get_attribKeyword() + == SingleWithAttrib::AT_VARIANT) + { + return true; + } + + MultiWithAttrib* temp_attrib = w_attrib_path->get_with_attr(); + if(temp_attrib) + for(size_t i = 0; i < temp_attrib->get_nof_elements(); i++) + if(temp_attrib->get_element(i)->get_attribKeyword() + == SingleWithAttrib::AT_VARIANT + && (!temp_attrib->get_element(i)->get_attribQualifiers() + || temp_attrib->get_element(i)->get_attribQualifiers() + ->get_nof_qualifiers() == 0)) + { + w_attrib_path->set_had_global_variants( true ); + return true; + } + } + + return false; + } + + bool Type::hasNeedofRawAttrs() + { + if(rawattrib) return true; + size_t nof_comps; + switch(typetype){ + case T_CHOICE_T: + case T_ANYTYPE: + case T_SEQ_T: + case T_SET_T: + nof_comps = get_nof_comps(); + for(size_t i=0; i < nof_comps; i++) + { + if(get_comp_byIndex(i)->get_type()->hasNeedofRawAttrs()) + { + return true; + } + } + break; + default: + break; + } + return false; + } + + bool Type::hasNeedofTextAttrs() + { + if(textattrib) return true; + size_t nof_comps; + switch(typetype){ + case T_CHOICE_T: + case T_ANYTYPE: + case T_SEQ_T: + case T_SET_T: + nof_comps = get_nof_comps(); + for(size_t i=0; i < nof_comps; i++) + { + if(get_comp_byIndex(i)->get_type()->hasNeedofTextAttrs()) + { + return true; + } + } + break; + default: + break; + } + return false; + } + + bool Type::hasNeedofJsonAttrs() + { + if(jsonattrib) return true; + size_t nof_comps; + switch(typetype) { + case T_CHOICE_T: + case T_ANYTYPE: + case T_SEQ_T: + case T_SET_T: + nof_comps = get_nof_comps(); + for (size_t i = 0; i < nof_comps; ++i) + { + if (get_comp_byIndex(i)->get_type()->hasNeedofJsonAttrs()) + { + return true; + } + } + break; + default: + break; + } + return false; + } + + bool Type::hasNeedofXerAttrs() + { + if(xerattrib && !xerattrib->empty()) return true; + size_t nof_comps; + switch(typetype){ + case T_CHOICE_T: + case T_ANYTYPE: + case T_SEQ_T: + case T_SET_T: + nof_comps = get_nof_comps(); + for(size_t i=0; i < nof_comps; i++) + { + if(get_comp_byIndex(i)->get_type()->hasNeedofXerAttrs()) + { + return true; + } + } + break; + default: + break; + } + return false; + } + + bool Type::hasVariantAttrs() + { + if(w_attrib_path) + { + if(w_attrib_path->get_had_global_variants()) return true; + + vector const &real_attribs + = w_attrib_path->get_real_attrib(); + + for (size_t i = 0; i < real_attribs.size(); i++) + if (real_attribs[i]->get_attribKeyword() + == SingleWithAttrib::AT_VARIANT) + { + return true; + } + + MultiWithAttrib* temp_attrib = w_attrib_path->get_with_attr(); + if(temp_attrib) + for(size_t i = 0; i < temp_attrib->get_nof_elements(); i++) + if(temp_attrib->get_element(i)->get_attribKeyword() + == SingleWithAttrib::AT_VARIANT + && (!temp_attrib->get_element(i)->get_attribQualifiers() + || temp_attrib->get_element(i)->get_attribQualifiers() + ->get_nof_qualifiers() != 0)) + { + w_attrib_path->set_had_global_variants( true ); + return true; + } + } + + return false; + } + + bool Type::hasEncodeAttr(const MessageEncodingType_t encoding_type) + { + if (CT_JSON == encoding_type && + (is_asn1() || (is_ref() && get_type_refd()->is_asn1()))) { + // ASN.1 types automatically support JSON encoding + return true; + } + // Check the type itself first, then the root type + WithAttribPath *aps[2] = { 0, 0 }; + size_t num_aps = ((aps[0] = get_attrib_path()) != 0); + // assign, compare, then add 0 or 1 + if (is_ref()) { + num_aps += ((aps[num_aps] = get_type_refd()->get_attrib_path()) != 0); + } + for (size_t a = 0; a < num_aps; ++a) { + const vector& real = aps[a]->get_real_attrib(); + const size_t num_atr = real.size(); + for (size_t i = 0; i < num_atr; ++i) { + const SingleWithAttrib& s = *real[i]; + if (s.get_attribKeyword() == SingleWithAttrib::AT_ENCODE) { + const string& spec = s.get_attribSpec().get_spec(); + if (spec == get_encoding_name(encoding_type)) { + return true; + } else { + // if it has an encode other than the one we're looking for, quit now + return false; + } + } // if ENCODE + } // for + } // next a + return false; + } + + namespace { // unnamed + + enum state { PROCESSING = -1, ANSWER_NO, ANSWER_YES }; + + struct memoizer : private map { + memoizer() : map() {} + + ~memoizer() { + for (int i = size()-1; i >= 0; --i) { + delete get_nth_elem(i); + } + clear(); + } + + bool remember (Type *t, state s) { + if (has_key(t)) { + *operator[](t) = s; + } + else { + add(t, new state(s)); + } + return s == ANSWER_YES; + } + + bool has_key(Type *t) { + return map::has_key(t); + } + + state* get(Type *t) { + return operator [](t); + } + }; + + } + + bool Type::has_encoding(MessageEncodingType_t encoding_type) + { + static memoizer memory; + static memoizer json_mem; + Type *t = this; + switch (encoding_type) { + case CT_BER: + case CT_PER: + for ( ; ; ) { + if (t->is_asn1()) return true; + else if (t->is_ref()) t = t->get_type_refd(); + else { + switch (t->typetype) { + case T_ERROR: + case T_BOOL: + case T_INT: + case T_REAL: + case T_BSTR: + case T_OSTR: + case T_OID: + // these basic TTCN-3 types have ASN.1 equivalents + return true; + default: + return false; + } + } + } + + case CT_XER: { + if (memory.has_key(this)) { + state *s = memory.get(this); + switch (*s){ + case PROCESSING: + break; + case ANSWER_NO: + return false; + case ANSWER_YES: + return true; + } + } + + for (;;) { + // For ASN.1 types, the answer depends solely on the -a switch. + // They are all considered to have Basic (i.e. useless) XER, + // unless the -a switch says removes XER from all ASN.1 types. + if (t->is_asn1()) return memory.remember(t, + asn1_xer ? ANSWER_YES : ANSWER_NO); + else if (t->is_ref()) t = t->get_type_refd(); + else { // at the end of the ref. chain + switch (t->typetype) { + case T_BOOL: + case T_INT: + case T_REAL: + case T_BSTR: + case T_OSTR: + // The octetstring type can always be encoded in XER. + // XSD:base64Binary is only needed for Type::is_charenc() + case T_OID: + case T_HSTR: // TTCN-3 hexstring + case T_VERDICT: // TTCN-3 verdict + case T_CSTR: // TTCN3 charstring + case T_USTR: // TTCN3 universal charstring + return memory.remember(t, ANSWER_YES); + + case T_ENUM_T: + break; // the switch; skip to checking if it has encode "XML"; + + case T_PORT: // TTCN-3 port (the list of in's, out's, inout's) + case T_COMPONENT: // TTCN-3 comp. type (extends, and { ... }) + case T_DEFAULT: // TTCN-3 + case T_SIGNATURE: // TTCN-3 + case T_FUNCTION: // TTCN-3 + case T_ALTSTEP: // TTCN-3 + case T_TESTCASE: // TTCN-3 + case T_ANYTYPE: // TTCN-3 anytype + return memory.remember(t, ANSWER_NO); + + case T_UNDEF: + case T_ERROR: + case T_REFDSPEC: + return false; // why don't we remember these ? + + case T_SEQ_T: + case T_SET_T: + case T_CHOICE_T: { + // No field may reject XER + size_t ncomp = t->get_nof_comps(); + for (size_t i = 0; i < ncomp; ++i) { + Type *t2 = t->get_comp_byIndex(i)->get_type(); + bool subresult = false; + if (memory.has_key(t2)) { + switch (*memory.get(t2)) { + case PROCESSING: + // This type contains itself and is in the process + // of being checked. Pretend it doesn't exist. + // The answer will be determined by the other fields, + // and it will propagate back up. + // Avoids infinite recursion for self-referencing types. + continue; + case ANSWER_NO: + subresult = false; + break; + case ANSWER_YES: + subresult = true; + break; + } + } + else { + memory.remember(t2, PROCESSING); + subresult = t2->has_encoding(CT_XER); + } + + if (subresult) memory.remember(t2, ANSWER_YES); + else return memory.remember(t2, ANSWER_NO); + // Note: return only if the answer (false) is known. + // If the answer is true, keep checking. + } // next i + // Empty record, or all fields supported XER: answer maybe yes. + break; } + + case T_SEQOF: + case T_SETOF: { + bool subresult = false; + Type *t2 = t->u.seof.ofType; + if (memory.has_key(t2)) { + switch (*memory.get(t2)) { + case PROCESSING: + // Recursive record-of. This is OK because the recursion + // can always be broken with an empty record-of. + subresult = true; + break; + case ANSWER_NO: + subresult = false; + break; + case ANSWER_YES: + subresult = true; + break; + } + } + else { + memory.remember(t2, PROCESSING); + // Check the contained type + subresult = t2->has_encoding(CT_XER); + } + if (subresult) break; // continue checking + else return memory.remember(t, ANSWER_NO); // No means no. + } + + case T_NULL: // ASN.1 null + case T_INT_A: // ASN.1 integer + case T_ENUM_A:// ASN.1 enum + case T_BSTR_A:// ASN.1 bitstring + case T_UTF8STRING: // ASN.1 + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_IA5STRING: + case T_GRAPHICSTRING: + case T_VISIBLESTRING: + case T_GENERALSTRING: + case T_UNIVERSALSTRING: + case T_BMPSTRING: + case T_UNRESTRICTEDSTRING: // still ASN.1 + case T_UTCTIME: // ASN.1 string + case T_GENERALIZEDTIME: // ASN.1 string + case T_OBJECTDESCRIPTOR: // ASN.1 string + case T_ROID: // relative OID (ASN.1) + + case T_CHOICE_A: // + case T_SEQ_A: // ASN.1 versions of choice,sequence,set + case T_SET_A: // + + case T_OCFT: // ObjectClassFieldType (ASN.1) + case T_OPENTYPE: // ASN.1 open type + case T_ANY: // deprecated ASN.1 ANY + + case T_EXTERNAL: // ASN.1 external + case T_EMBEDDED_PDV: // ASN.1 embedded pdv + case T_SELTYPE: // selection type (ASN.1) + FATAL_ERROR("Type::has_encoding(): typetype %d should be asn1", + t->typetype); + break; // not reached + + case T_REFD: // reference to another type + case T_ADDRESS: // TTCN-3 address type + case T_ARRAY: // TTCN-3 array + default: // FIXME: if compiling with -Wswitch, the default should be removed + return memory.remember(t, ANSWER_NO); + } // switch t->typetype + + // Check to see if it has an encode "XML"; first the type itself, + // then the root type. + WithAttribPath *aps[2] = {0,0}; + size_t num_aps = ((aps[0] = this->get_attrib_path()) != 0); + // assign, compare, then add 0 or 1 + if (this != t) { + num_aps += ((aps[num_aps] = t->get_attrib_path()) != 0); + } + for (size_t a = 0; a < num_aps; ++a) { + const vector& real = aps[a]->get_real_attrib(); + const size_t num_atr = real.size(); + for (size_t i = 0; i < num_atr; ++i) { + const SingleWithAttrib& s = *real[i]; + if (s.get_attribKeyword() == SingleWithAttrib::AT_ENCODE) { + const string& spec = s.get_attribSpec().get_spec(); + if (spec == ex_emm_ell // the right answer + ||spec == ex_ee_arr) // the acceptable answer + return memory.remember(t, ANSWER_YES); + else // if it has an encode other than XER, quit now + return memory.remember(t, ANSWER_NO); + } // if ENCODE + } // for + } // next a + return memory.remember(t, ANSWER_NO); // no encode XER + } // if(!asn1) + } // for(ever) + return memory.remember(t, ANSWER_NO); } + + case CT_RAW: + for ( ; ; ) { + if (t->rawattrib) return true; + else if (t->is_ref()) t = t->get_type_refd(); + else { + switch (t->typetype) { + case T_ERROR: + case T_BOOL: + case T_INT: + case T_REAL: + case T_BSTR: + case T_HSTR: + case T_OSTR: + case T_CSTR: + // these basic types support RAW encoding by default + return true; + default: + return false; + } + } + } + + case CT_TEXT: + for ( ; ; ) { + if (t->textattrib) return true; + else if (t->is_ref()) t = t->get_type_refd(); + else { + switch (t->typetype) { + case T_ERROR: + case T_BOOL: + case T_INT: + case T_OSTR: + case T_CSTR: + // these basic types support TEXT encoding by default + return true; + default: + return false; + } + } + } + + case CT_JSON: + while (true) { + if (json_mem.has_key(t)) { + switch (*json_mem.get(t)) { + case PROCESSING: + break; + case ANSWER_NO: + return false; + case ANSWER_YES: + return true; + } + } + if (t->jsonattrib) { + return json_mem.remember(t, ANSWER_YES); + } + if (t->is_ref()) { + t = t->get_type_refd(); + } + else { + switch (t->typetype) { + case T_ERROR: + case T_BOOL: + case T_INT: + case T_INT_A: + case T_REAL: + case T_BSTR: + case T_BSTR_A: + case T_HSTR: + case T_OSTR: + case T_CSTR: + case T_USTR: + case T_UTF8STRING: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_IA5STRING: + case T_GRAPHICSTRING: + case T_VISIBLESTRING: + case T_GENERALSTRING: + case T_UNIVERSALSTRING: + case T_BMPSTRING: + case T_VERDICT: + // 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_SET_T: + case T_SET_A: + case T_CHOICE_T: + case T_CHOICE_A: + case T_ANYTYPE: { + // all fields must also support JSON encoding + size_t ncomp = t->get_nof_comps(); + for (size_t i = 0; i < ncomp; ++i) { + Type *t2 = t->get_comp_byIndex(i)->get_type(); + if (json_mem.has_key(t2)) { + switch (*json_mem.get(t2)) { + case ANSWER_YES: + // This field is OK, but we still need to check the others + case PROCESSING: + // This type contains itself and is in the process + // of being checked. Pretend it doesn't exist. + // The answer will be determined by the other fields, + // and it will propagate back up. + // Avoids infinite recursion for self-referencing types. + continue; + case ANSWER_NO: + // One field is not OK => the structure is not OK + return json_mem.remember(t, ANSWER_NO); + } + } + else { + json_mem.remember(t2, PROCESSING); + bool enabled = t2->has_encoding(CT_JSON); + json_mem.remember(t2, enabled ? ANSWER_YES : ANSWER_NO); + if (!enabled) { + // One field is not OK => the structure is not OK + return json_mem.remember(t, ANSWER_NO); + } + } + } + break; // check for an encode attribute + } + case T_SEQOF: + case T_SETOF: + case T_ARRAY: { + Type *t2 = t->u.seof.ofType; + if (json_mem.has_key(t2)) { + switch (*json_mem.get(t2)) { + case ANSWER_YES: + // Continue checking + case PROCESSING: + // Recursive record-of. This is OK because the recursion + // can always be broken with an empty record-of. + break; + case ANSWER_NO: + return json_mem.remember(t, ANSWER_NO); + break; + } + } + else { + json_mem.remember(t2, PROCESSING); + bool enabled = t2->has_encoding(CT_JSON); + json_mem.remember(t2, enabled ? ANSWER_YES : ANSWER_NO); + if (!enabled) { + // One field is not OK => the structure is not OK + return json_mem.remember(t, ANSWER_NO); + } + } + break; // check for an encode attribute + } + case T_ENUM_T: + case T_ENUM_A: + break; // check for an encode attribute + default: + return json_mem.remember(t, ANSWER_NO); + } // switch + return json_mem.remember(t, hasEncodeAttr(CT_JSON) ? ANSWER_YES : ANSWER_NO); + } // else + } // while + + default: + FATAL_ERROR("Type::has_encoding()"); + return false; + } + } + + + bool Type::is_pure_refd() + { + switch (typetype) { + case T_REFD: + // ASN.1 parameterized references are not pure :) + if(dynamic_cast(u.ref.ref)) return false; + // no break; + case T_REFDSPEC: + case T_SELTYPE: + case T_OCFT: + if (sub_type || constraints) return false; + else if (tags && enable_ber()) return false; + else if (rawattrib && enable_raw()) return false; + else if (textattrib && enable_text()) return false; + else if (enable_xer()) return false; + else if (jsonattrib && enable_json()) return false; + else return true; + default: + return false; + } + } + + string Type::create_stringRepr() + { + if(is_tagged() || hasRawAttrs()) + return get_genname_own(); + switch(typetype) { + case T_NULL: + return string("NULL"); + case T_BOOL: + return string("BOOLEAN"); + case T_INT: + case T_INT_A: + return string("INTEGER"); + case T_REAL: + return string("REAL"); + case T_BSTR: + case T_BSTR_A: + return string("BIT__STRING"); + case T_HSTR: + return string("HEX__STRING"); + case T_OSTR: + return string("OCTET__STRING"); + case T_CSTR: + return string("CHAR__STRING"); + case T_USTR: + return string("UNIVERSAL__CHARSTRING"); + case T_UTF8STRING: + return string("UTF8String"); + case T_NUMERICSTRING: + return string("NumericString"); + case T_PRINTABLESTRING: + return string("PrintableString"); + case T_TELETEXSTRING: + return string("TeletexString"); + case T_VIDEOTEXSTRING: + return string("VideotexString"); + case T_IA5STRING: + return string("IA5String"); + case T_GRAPHICSTRING: + return string("GraphicString"); + case T_VISIBLESTRING: + return string("VisibleString"); + case T_GENERALSTRING: + return string("GeneralString"); + case T_UNIVERSALSTRING: + return string("UniversalString"); + case T_BMPSTRING: + return string("BMPString"); + case T_UNRESTRICTEDSTRING: + return string("CHARACTER__STRING"); + case T_UTCTIME: + return string("UTCTime"); + case T_GENERALIZEDTIME: + return string("GeneralizedTime"); + case T_OBJECTDESCRIPTOR: + return string("ObjectDescriptor"); + case T_OID: + return string("OBJECT__IDENTIFIER"); + case T_ROID: + return string("RELATIVE__OID"); + case T_ANY: + return string("ANY"); + case T_REFD: + case T_SELTYPE: + case T_REFDSPEC: + case T_OCFT: + if (tags || constraints || + (w_attrib_path && w_attrib_path->has_attribs())) + return get_genname_own(); + else return get_type_refd()->get_stringRepr(); + case T_ERROR: + return string(""); + default: + return get_genname_own(); + } // switch + } + + Identifier Type::get_otaltname(bool& is_strange) + { + string s; + if (is_tagged() || is_constrained() || hasRawAttrs()) { + s = get_genname_own(); + is_strange = true; + } else if (typetype == T_REFD) { + Ref_simple* t_ref=dynamic_cast(u.ref.ref); + if (t_ref) { + const Identifier *id = t_ref->get_id(); + const string& dispname = id->get_dispname(); + if (dispname.find('.') < dispname.size()) { + // id is not regular because t_ref is a parameterized reference + // use that id anyway + s += id->get_name(); + is_strange = true; + } else { + Scope *ass_scope = t_ref->get_refd_assignment()->get_my_scope(); + if (ass_scope->get_parent_scope() == ass_scope->get_scope_mod()) { + // t_ref points to an assignment at module scope + // use the simple id of the reference (in lowercase) + s = id->get_name(); + is_strange = false; + } else { + // t_ref is a dummy reference in a parameterized assignment + // (i.e. it points to a parameter assignment of an instantiation) + // perform the same examination recursively on the referenced type + // (which is the actual parameter) + return get_type_refd()->get_otaltname(is_strange); + } + } + } else { + // the type comes from an information object [class] + // examine the referenced type recursively + return get_type_refd()->get_otaltname(is_strange); + } + } else { + s = get_stringRepr(); + // throw away the leading @ if this is an instantiated type + // (e.g. an in-line SEQUENCE from a parameterized reference) + if (!strncmp(s.c_str(), "_root_", 6)) s.replace(0, 6, ""); + // the name is strange if it contains a single underscore + string s2(s); + // transform "__" -> "-" + for (size_t pos = 0; ; ) { + pos = s2.find("__", pos); + if (pos < s2.size()) { + s2.replace(pos, 2, "-"); + pos++; + } else break; + } + is_strange = s2.find('_') < s2.size(); + } + /* + size_t pos=s.find_if(0, s.size(), isupper); + if(pos==s.size()) FATAL_ERROR("Type::get_otaltname() (`%s')", s.c_str()); + s[pos]=tolower(s[pos]); + */ + s[0]=tolower(s[0]); + Identifier tmp_id(Identifier::ID_NAME, s, true); + /* This is because the origin of the returned ID must be ASN. */ + return Identifier(Identifier::ID_ASN, tmp_id.get_asnname()); + } + + string Type::get_genname_value(Scope *p_scope) + { + Type *t = get_type_refd_last(); + switch (t->typetype) { + case T_UNDEF: + case T_ERROR: + case T_UNRESTRICTEDSTRING: + case T_OCFT: + case T_EXTERNAL: + case T_EMBEDDED_PDV: + case T_REFD: + case T_REFDSPEC: + case T_SELTYPE: + FATAL_ERROR("Type::get_genname_value()"); + case T_NULL: + return string("ASN_NULL"); + case T_BOOL: + return string("BOOLEAN"); + case T_INT: + case T_INT_A: + return string("INTEGER"); + case T_REAL: + return string("FLOAT"); + case T_BSTR: + case T_BSTR_A: + return string("BITSTRING"); + case T_HSTR: + return string("HEXSTRING"); + case T_OSTR: + return string("OCTETSTRING"); + case T_CSTR: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + return string("CHARSTRING"); + case T_USTR: // ttcn3 universal charstring + case T_UTF8STRING: + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_GRAPHICSTRING: + case T_GENERALSTRING: + case T_UNIVERSALSTRING: + case T_BMPSTRING: + case T_OBJECTDESCRIPTOR: + return string("UNIVERSAL_CHARSTRING"); + case T_OID: + case T_ROID: + return string("OBJID"); + case T_ANY: + return string("ASN_ANY"); + case T_VERDICT: + return string("VERDICTTYPE"); + case T_COMPONENT: + return string("COMPONENT"); + case T_DEFAULT: + return string("DEFAULT"); + case T_ARRAY: + if (!t->u.array.in_typedef) + return t->u.array.dimension->get_value_type(t->u.array.element_type, + p_scope); + // no break + default: + return t->get_genname_own(p_scope); + } // switch + } + + string Type::get_genname_template(Scope *p_scope) + { + Type *t = get_type_refd_last(); + string ret_val; + switch (t->typetype) { + case T_ERROR: + case T_PORT: + // template classes do not exist for these types + FATAL_ERROR("Type::get_genname_template()"); + case T_ARRAY: + // a template class has to be instantiated in case of arrays + // outside type definitions + if (!t->u.array.in_typedef) { + ret_val = t->u.array.dimension->get_template_type( + t->u.array.element_type, p_scope); + break; + } + // no break + default: + // in case of other types the name of the template class is derived + // from the value class by appending a suffix + ret_val = t->get_genname_value(p_scope); + ret_val += "_template"; + break; + } + return ret_val; + } + + string Type::get_genname_altname() + { + Type *t_last = get_type_refd_last(); + Scope *t_scope = t_last->get_my_scope(); + switch (t_last->typetype) { + case T_UNDEF: + case T_ERROR: + case T_UNRESTRICTEDSTRING: + case T_OCFT: + case T_EXTERNAL: + case T_EMBEDDED_PDV: + case T_REFD: + case T_REFDSPEC: + case T_SELTYPE: + FATAL_ERROR("Type::get_genname_altname()"); + case T_ENUM_A: + case T_ENUM_T: + case T_CHOICE_A: + case T_CHOICE_T: + case T_SEQOF: + case T_SETOF: + case T_SEQ_A: + case T_SEQ_T: + case T_SET_A: + case T_SET_T: + case T_OPENTYPE: + case T_ANYTYPE: // FIXME this does not yet work + case T_PORT: + case T_COMPONENT: + case T_ARRAY: + case T_SIGNATURE: + case T_FUNCTION: + case T_ALTSTEP: + case T_TESTCASE: { + // user-defined types + // always use the qualified name (including module identifier) + string ret_val(t_scope->get_scope_mod_gen()->get_modid().get_name()); + ret_val += '_'; + ret_val += t_last->get_genname_own(); + return ret_val; } + default: + // built-in types + // use the simple class name from the base library + return t_last->get_genname_value(t_scope); + } + } + + string Type::get_typename() + { + Type *t = get_type_refd_last(); + const char* tn = get_typename_builtin(t->typetype); + if (tn != 0) return string(tn); + switch (t->typetype) { + case T_COMPONENT: + case T_SIGNATURE: + case T_CHOICE_A: + case T_CHOICE_T: + case T_ANYTYPE: + case T_SEQ_A: + case T_SEQ_T: + case T_SET_A: + case T_SET_T: + case T_SEQOF: + case T_SETOF: + case T_ENUM_A: + case T_ENUM_T: + case T_PORT: + case T_FUNCTION: + case T_ALTSTEP: + case T_TESTCASE: + return t->get_fullname(); + case T_ARRAY: { + string dimensions(t->u.array.dimension->get_stringRepr()); + t = t->u.array.element_type; + while (t->typetype == T_ARRAY) { + dimensions += t->u.array.dimension->get_stringRepr(); + t = t->u.array.element_type; + } + return t->get_typename() + dimensions; } + default: + FATAL_ERROR("Type::get_typename()"); + return string(); + } // switch + } + + // static + const char* Type::get_typename_builtin(typetype_t tt) + { + switch (tt) { + case T_ERROR: + return "Erroneous type"; + case T_NULL: + return "NULL"; + case T_BOOL: + return "boolean"; + case T_INT: + case T_INT_A: + return "integer"; + case T_REAL: + return "float"; + case T_BSTR: + case T_BSTR_A: + return "bitstring"; + case T_HSTR: + return "hexstring"; + case T_OSTR: + return "octetstring"; + case T_CSTR: + return "charstring"; + case T_USTR: + return "universal charstring"; + case T_UTF8STRING: + return "UTF8String"; + case T_NUMERICSTRING: + return "NumericString"; + case T_PRINTABLESTRING: + return "PrintableString"; + case T_TELETEXSTRING: + return "TeletexString"; + case T_VIDEOTEXSTRING: + return "VideotexString"; + case T_IA5STRING: + return "IA5String"; + case T_GRAPHICSTRING: + return "GraphicString"; + case T_VISIBLESTRING: + return "VisibleString"; + case T_GENERALSTRING: + return "GeneralString"; + case T_UNIVERSALSTRING: + return "UniversalString"; + case T_BMPSTRING: + return "BMPString"; + case T_UTCTIME: + return "UTCTime"; + case T_GENERALIZEDTIME: + return "GeneralizedTime"; + case T_OBJECTDESCRIPTOR: + return "ObjectDescriptor"; + case T_OID: + case T_ROID: + return "objid"; + case T_ANY: + return "ANY"; + case T_VERDICT: + return "verdicttype"; + case T_DEFAULT: + return "default"; + case T_EXTERNAL: + return "EXTERNAL"; + case T_EMBEDDED_PDV: + return "EMBEDDED PDV"; + case T_UNRESTRICTEDSTRING: + return "CHARACTER STRING"; + case T_OPENTYPE: + return "open type"; + case T_ADDRESS: + return "address"; + default: + return 0; + } + } + + string Type::get_genname_typedescriptor(Scope *p_scope) + { + Type *t = this; + for ( ; ; ) { + /* If it has tags or encoding attributes, then its encoding may be + * different from the other "equivalent" types and needs to have its own + * descriptor. + */ + if (t->is_tagged() || t->rawattrib || t->textattrib || t->jsonattrib || + (t->xerattrib && !t->xerattrib->empty() )) + { + return t->get_genname_own(p_scope); + } + else if (t->is_ref()) { + if (t->has_encoding(CT_XER)) { + // just fetch the referenced type and return + return t->get_type_refd()->get_genname_own(p_scope); + } + else + { // follow the white rabbit + t = t->get_type_refd(); + } + } + else break; + } + return t->get_genname_typename(p_scope); + } + + string Type::get_genname_typename(Scope *p_scope) + { + Type *t = get_type_refd_last(); + switch (t->typetype) { + case T_UTF8STRING: + return string("UTF8String"); + case T_NUMERICSTRING: + return string("NumericString"); + case T_PRINTABLESTRING: + return string("PrintableString"); + case T_TELETEXSTRING: + return string("TeletexString"); + case T_VIDEOTEXSTRING: + return string("VideotexString"); + case T_IA5STRING: + return string("IA5String"); + case T_GRAPHICSTRING: + return string("GraphicString"); + case T_VISIBLESTRING: + return string("VisibleString"); + case T_GENERALSTRING: + return string("GeneralString"); + case T_UNIVERSALSTRING: + return string("UniversalString"); + case T_BMPSTRING: + return string("BMPString"); + case T_UTCTIME: + return string("ASN_UTCTime"); + case T_GENERALIZEDTIME: + return string("ASN_GeneralizedTime"); + case T_OBJECTDESCRIPTOR: + return string("ObjectDescriptor"); + case T_ROID: + return string("ASN_ROID"); + default: + return t->get_genname_value(p_scope); + } // switch + } + + string Type::get_genname_berdescriptor() + { + Type *t = this; + for ( ; ; ) { + if (t->is_tagged()) return t->get_genname_own(my_scope); + else if (t->is_ref()) t = t->get_type_refd(); + else break; + } + switch (t->typetype) { + case T_ENUM_A: + case T_ENUM_T: + return string("ENUMERATED"); + case T_CHOICE_A: + case T_CHOICE_T: + case T_OPENTYPE: + return string("CHOICE"); + case T_SEQ_A: + case T_SEQ_T: + case T_SEQOF: + return string("SEQUENCE"); + case T_SET_A: + case T_SET_T: + case T_SETOF: + return string("SET"); + default: + return t->get_genname_typename(my_scope); + } // switch + } + + string Type::get_genname_rawdescriptor() + { + Type *t = this; + for ( ; ; ) { + if (t->rawattrib) return t->get_genname_own(my_scope); + else if (t->is_ref()) t = t->get_type_refd(); + else break; + } + return t->get_genname_typename(my_scope); + } + + string Type::get_genname_textdescriptor() + { + Type *t = this; + for ( ; ; ) { + if (t->textattrib) return t->get_genname_own(my_scope); + else if (t->is_ref()) t = t->get_type_refd(); + else break; + } + return t->get_genname_typename(my_scope); + } + + string Type::get_genname_xerdescriptor() + { + if (T_REFDSPEC == typetype) { + return get_genname_typedescriptor(my_scope); + } + else return genname; + } + + string Type::get_genname_jsondescriptor() + { + Type *t = this; + while (true) { + if (t->jsonattrib) return t->get_genname_own(my_scope); + else if (t->is_ref()) t = t->get_type_refd(); + else break; + } + return t->get_genname_typename(my_scope); + } + + const char* Type::get_genname_typedescr_asnbasetype() + { + switch (get_type_refd_last()->typetype) { + case T_BMPSTRING: + return "BMPSTRING"; + case T_UNIVERSALSTRING: + return "UNIVERSALSTRING"; + case T_UTF8STRING: + return "UTF8STRING"; + case T_TELETEXSTRING: + return "TELETEXSTRING"; + case T_VIDEOTEXSTRING: + return "VIDEOTEXSTRING"; + case T_OBJECTDESCRIPTOR: + case T_GRAPHICSTRING: + return "GRAPHICSTRING"; + case T_GENERALSTRING: + return "GENERALSTRING"; + case T_OID: + return "OBJID"; + case T_ROID: + return "ROID"; + default: + return "DONTCARE"; + } // switch + } + + void Type::dump(unsigned level) const + { + DEBUG(level, "Type @ %p, '%s'", (const void*)this, get_fullname().c_str()); + switch(typetype) { + case T_ERROR: + DEBUG(level, "Type: "); + break; + case T_NULL: + DEBUG(level, "Type: NULL"); + break; + case T_BOOL: + DEBUG(level, "Type: boolean"); + break; + case T_INT: + DEBUG(level, "Type: integer"); + break; + case T_INT_A: + DEBUG(level, "Type: INTEGER"); + if(u.namednums.block) + DEBUG(level, "with unparsed block"); + if(u.namednums.nvs) { + DEBUG(level, "with named numbers (%lu pcs.)", + (unsigned long) u.namednums.nvs->get_nof_nvs()); + u.namednums.nvs->dump(level+1); + } + break; + case T_REAL: + DEBUG(level, "Type: float/REAL"); + break; + case T_ENUM_A: + case T_ENUM_T: + DEBUG(level, "Type: enumerated"); + u.enums.eis->dump(level+1); + break; + case T_BSTR: + DEBUG(level, "Type: bitstring"); + break; + case T_BSTR_A: + DEBUG(level, "Type: BIT STRING"); + if(u.namednums.block) + DEBUG(level, "with unparsed block"); + if(u.namednums.nvs) { + DEBUG(level, "with named numbers (%lu pcs.)", + (unsigned long) u.namednums.nvs->get_nof_nvs()); + u.namednums.nvs->dump(level+1); + } + break; + case T_HSTR: + DEBUG(level, "Type: hexstring"); + break; + case T_OSTR: + DEBUG(level, "Type: octetstring"); + break; + case T_CSTR: + DEBUG(level, "Type: charstring"); + break; + case T_USTR: + DEBUG(level, "Type: universal charstring"); + break; + case T_UTF8STRING: + DEBUG(level, "Type: UTF8String"); + break; + case T_NUMERICSTRING: + DEBUG(level, "Type: NumericString"); + break; + case T_PRINTABLESTRING: + DEBUG(level, "Type: PrintableString"); + break; + case T_TELETEXSTRING: + DEBUG(level, "Type: TeletexString"); + break; + case T_VIDEOTEXSTRING: + DEBUG(level, "Type: VideotexString"); + break; + case T_IA5STRING: + DEBUG(level, "Type: IA5String"); + break; + case T_GRAPHICSTRING: + DEBUG(level, "Type: GraphicString"); + break; + case T_VISIBLESTRING: + DEBUG(level, "Type: VisibleString"); + break; + case T_GENERALSTRING: + DEBUG(level, "Type: GeneralString"); + break; + case T_UNIVERSALSTRING: + DEBUG(level, "Type: UniversalString"); + break; + case T_BMPSTRING: + DEBUG(level, "Type: BMPString"); + break; + case T_UNRESTRICTEDSTRING: + DEBUG(level, "Type: CHARACTER STRING"); + break; + case T_UTCTIME: + DEBUG(level, "Type: UTCTime"); + break; + case T_GENERALIZEDTIME: + DEBUG(level, "Type: GeneralizedTime"); + break; + case T_OBJECTDESCRIPTOR: + DEBUG(level, "Type: OBJECT DESCRIPTOR"); + break; + case T_OID: + DEBUG(level, "Type: objid/OBJECT IDENTIFIER"); + break; + case T_ROID: + DEBUG(level, "Type: RELATIVE-OID"); + break; + case T_ANYTYPE: + DEBUG(level, "Type: anytype!!!"); + u.secho.cfm->dump(level+1); + break; + case T_CHOICE_T: + DEBUG(level, "Type: union"); + u.secho.cfm->dump(level+1); + break; + case T_CHOICE_A: + DEBUG(level, "Type: CHOICE"); + if(u.secho.block) + DEBUG(level, "with unparsed block"); + if(u.secho.ctss) { + DEBUG(level, "with alternatives (%lu pcs.)", + (unsigned long) u.secho.ctss->get_nof_comps()); + u.secho.ctss->dump(level+1); + } + break; + case T_SEQOF: + DEBUG(level, "Type: record of/SEQUENCE OF"); + DEBUG(level+1, "of type:"); + u.seof.ofType->dump(level+2); + break; + case T_SETOF: + DEBUG(level, "Type: set of/SET OF"); + DEBUG(level+1, "of type:"); + u.seof.ofType->dump(level+2); + break; + case T_SEQ_T: + DEBUG(level, "Type: record"); + u.secho.cfm->dump(level+1); + break; + case T_SET_T: + DEBUG(level, "Type: set"); + u.secho.cfm->dump(level+1); + break; + case T_SEQ_A: + DEBUG(level, "Type: SEQUENCE"); + if(u.secho.block) + DEBUG(level, "with unparsed block"); + if(u.secho.ctss) { + DEBUG(level, "with components (%lu pcs.)", + (unsigned long) u.secho.ctss->get_nof_comps()); + u.secho.ctss->dump(level+1); + } + break; + case T_SET_A: + DEBUG(level, "Type: SET"); + if(u.secho.block) + DEBUG(level, "with unparsed block"); + if(u.secho.ctss) { + DEBUG(level, "with components (%lu pcs.)", + (unsigned long) u.secho.ctss->get_nof_comps()); + u.secho.ctss->dump(level+1); + } + break; + case T_OCFT: + DEBUG(level, "Type: ObjectClassFieldType (%s)", + const_cast(this)->get_type_refd()->get_stringRepr().c_str()); + break; + case T_OPENTYPE: + DEBUG(level, "Type: opentype (mapped to CHOICE)"); + u.secho.cfm->dump(level+1); + break; + case T_ANY: + DEBUG(level, "Type: ANY"); + break; + case T_EXTERNAL: + DEBUG(level, "Type: EXTERNAL"); + break; + case T_EMBEDDED_PDV: + DEBUG(level, "Type: EMBEDDED PDV"); + break; + case T_REFD: + DEBUG(level, "Type: reference"); + u.ref.ref->dump(level+1); + if(u.ref.type_refd && u.ref.type_refd->typetype==T_OPENTYPE) + u.ref.type_refd->dump(level+1); + break; + case T_REFDSPEC: + DEBUG(level, "Type: reference (spec) to %s:", + u.ref.type_refd->get_fullname().c_str()); + u.ref.type_refd->dump(level + 1); + break; + case T_SELTYPE: + DEBUG(level, "Type: selection type"); + DEBUG(level+1, "`%s' <", u.seltype.id->get_dispname().c_str()); + u.seltype.type->dump(level+1); + break; + case T_VERDICT: + DEBUG(level, "Type: verdicttype"); + break; + case T_PORT: + DEBUG(level, "Type: port"); + u.port->dump(level + 1); + break; + case T_COMPONENT: + DEBUG(level, "Type: component"); + u.component->dump(level + 1); + break; + case T_ADDRESS: + DEBUG(level, "Type: address"); + break; + case T_DEFAULT: + DEBUG(level, "Type: default"); + break; + case T_ARRAY: + DEBUG(level, "Type: array"); + DEBUG(level + 1, "element type:"); + u.array.element_type->dump(level + 2); + DEBUG(level + 1, "dimension:"); + u.array.dimension->dump(level + 2); + break; + case T_SIGNATURE: + DEBUG(level, "Type: signature"); + if (u.signature.parameters) { + DEBUG(level+1,"parameter(s):"); + u.signature.parameters->dump(level+2); + } + if (u.signature.return_type) { + DEBUG(level+1,"return type"); + u.signature.return_type->dump(level+2); + } + if (u.signature.no_block) DEBUG(level+1,"no block"); + if (u.signature.exceptions) { + DEBUG(level+1,"exception(s):"); + u.signature.exceptions->dump(level+2); + } + break; + case T_FUNCTION: + DEBUG(level, "Type: function"); + DEBUG(level+1, "Parameters:"); + u.fatref.fp_list->dump(level+2); + if (u.fatref.return_type) { + if (!u.fatref.returns_template) { + DEBUG(level+1, "Return type:"); + } else { + if (u.fatref.template_restriction==TR_OMIT) + DEBUG(level+1, "Returns template of type:"); + else + DEBUG(level+1, "Returns template(%s) of type:", + Template::get_restriction_name(u.fatref.template_restriction)); + } + u.fatref.return_type->dump(level+2); + } + if(u.fatref.runs_on.ref) { + DEBUG(level+1, "Runs on clause:"); + u.fatref.runs_on.ref->dump(level+2); + } else { + if (u.fatref.runs_on.self) DEBUG(level+1, "Runs on self"); + } + break; + case T_ALTSTEP: + DEBUG(level, "Type: altstep"); + DEBUG(level+1, "Parameters:"); + u.fatref.fp_list->dump(level+2); + if(u.fatref.runs_on.ref) { + DEBUG(level+1, "Runs on clause:"); + u.fatref.runs_on.ref->dump(level+2); + } else { + if (u.fatref.runs_on.self) DEBUG(level+1, "Runs on self"); + } + break; + case T_TESTCASE: + DEBUG(level, "Type: testcase"); + DEBUG(level+1, "Parameters:"); + u.fatref.fp_list->dump(level+2); + if(u.fatref.runs_on.ref) { + DEBUG(level+1, "Runs on clause:"); + u.fatref.runs_on.ref->dump(level+2); + } + if(u.fatref.system.ref) { + DEBUG(level+1, "System clause:"); + u.fatref.system.ref->dump(level+2); + } + break; + default: + DEBUG(level, "type (%d - %s)", typetype, const_cast(this)->get_stringRepr().c_str()); + } // switch + DEBUG(level, "ownertype %2d", ownertype); + if(sub_type!=NULL) { + DEBUG(level, "with subtype"); + sub_type->dump(level+1); + } + if(tags) { + DEBUG(level, "with tags"); + tags->dump(level+1); + } + + if(w_attrib_path && w_attrib_path->get_with_attr()) + { + DEBUG(level, "Attributes"); + w_attrib_path->dump(level); + //w_attrib_path->get_with_attr()->dump(level); + } + + if (xerattrib) { + xerattrib->print(get_fullname().c_str()); + } + } + + SubtypeConstraint::subtype_t Type::get_subtype_type() + { + Type* t = get_type_refd_last(); + switch (t->get_typetype()) { + case T_INT: + case T_INT_A: + return SubtypeConstraint::ST_INTEGER; + case T_REAL: + return SubtypeConstraint::ST_FLOAT; + case T_BOOL: + return SubtypeConstraint::ST_BOOLEAN; + case T_VERDICT: + return SubtypeConstraint::ST_VERDICTTYPE; + case T_OID: + case T_ROID: + return SubtypeConstraint::ST_OBJID; + case T_BSTR: + case T_BSTR_A: + return SubtypeConstraint::ST_BITSTRING; + case T_HSTR: + return SubtypeConstraint::ST_HEXSTRING; + case T_OSTR: + return SubtypeConstraint::ST_OCTETSTRING; + case T_TELETEXSTRING: + case T_VIDEOTEXSTRING: + case T_GRAPHICSTRING: + case T_GENERALSTRING: + case T_OBJECTDESCRIPTOR: + // iso2022str + case T_CSTR: + case T_NUMERICSTRING: + case T_PRINTABLESTRING: + case T_IA5STRING: + case T_VISIBLESTRING: + case T_UTCTIME: + case T_GENERALIZEDTIME: + return SubtypeConstraint::ST_CHARSTRING; + case T_USTR: + case T_UTF8STRING: + case T_UNIVERSALSTRING: + case T_BMPSTRING: + return SubtypeConstraint::ST_UNIVERSAL_CHARSTRING; + case T_ENUM_T: + case T_ENUM_A: + case T_NULL: // FIXME: this should have it's own ST_NULL case + return SubtypeConstraint::ST_ENUM; + case T_CHOICE_T: + case T_CHOICE_A: + case T_ANYTYPE: // (titan's hacked anytype is a choice) + case T_OPENTYPE: + return SubtypeConstraint::ST_UNION; + case T_SEQOF: + return SubtypeConstraint::ST_RECORDOF; + case T_SETOF: + return SubtypeConstraint::ST_SETOF; + case T_SEQ_T: + case T_SEQ_A: + case T_EXTERNAL: // associated ASN.1 type is a SEQUENCE + case T_EMBEDDED_PDV: // associated ASN.1 type is a SEQUENCE + case T_UNRESTRICTEDSTRING: // associated ASN.1 type is a SEQUENCE + return SubtypeConstraint::ST_RECORD; + case T_SET_T: + case T_SET_A: + return SubtypeConstraint::ST_SET; + case T_FUNCTION: + return SubtypeConstraint::ST_FUNCTION; + case T_ALTSTEP: + return SubtypeConstraint::ST_ALTSTEP; + case T_TESTCASE: + return SubtypeConstraint::ST_TESTCASE; + default: + return SubtypeConstraint::ST_ERROR; + } + } + + void Type::set_parsed_restrictions(vector *stp) + { + if(!parsed_restr)parsed_restr=stp; + else FATAL_ERROR("Type::set_parsed_restrictions(): restrictions " + "are already set."); + } + + bool Type::is_component_internal() + { + if (!checked) chk(); + switch (typetype) { + case T_DEFAULT: + case T_PORT: + return true; + case T_FUNCTION: + case T_ALTSTEP: + return u.fatref.runs_on.self; + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + return u.secho.component_internal; + case T_SEQOF: + case T_SETOF: + return u.seof.component_internal; + case T_ARRAY: + return u.array.component_internal; + case T_SIGNATURE: + return u.signature.component_internal; + case T_REFD: + case T_REFDSPEC: + return u.ref.component_internal; + default: + return false; + } //switch + } + + void Type::chk_component_internal(map& type_chain, + const char* p_what) + { + Type* t_last = get_type_refd_last(); + switch (t_last->typetype) { + // types that cannot be sent + case T_DEFAULT: + error("Default type cannot be %s", p_what); + break; + case T_PORT: + error("Port type `%s' cannot be %s", t_last->get_typename().c_str(), + p_what); + break; + case T_FUNCTION: + if (t_last->u.fatref.runs_on.self) { + error("Function type `%s' with 'runs on self' clause cannot be %s", + t_last->get_typename().c_str(), p_what); + } + break; + case T_ALTSTEP: + if (t_last->u.fatref.runs_on.self) { + error("Altstep type `%s' with 'runs on self' clause cannot be %s", + t_last->get_typename().c_str(), p_what); + } + break; + // structured types that may contain types that cannot be sent + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + case T_SEQOF: + case T_SETOF: + case T_ARRAY: + case T_SIGNATURE: { + if (type_chain.has_key(t_last)) break; + type_chain.add(t_last, 0); + Error_Context cntxt(this, "In type `%s'", get_typename().c_str()); + switch (t_last->typetype) { + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: { + size_t nof_comps = t_last->get_nof_comps(); + for (size_t i=0; iget_comp_byIndex(i)->get_type(); + if (t->is_component_internal()) + t->chk_component_internal(type_chain, p_what); + } + } break; + case T_SEQOF: + case T_SETOF: + if (t_last->u.seof.ofType->is_component_internal()) + t_last->u.seof.ofType->chk_component_internal(type_chain, p_what); + break; + case T_ARRAY: + if (t_last->u.array.element_type->is_component_internal()) + t_last->u.array.element_type->chk_component_internal(type_chain, + p_what); + break; + case T_SIGNATURE: + if (t_last->u.signature.parameters) { + size_t nof_params = t_last->u.signature.parameters->get_nof_params(); + for (size_t i=0; iu.signature.parameters-> + get_param_byIndex(i)->get_type(); + if (t->is_component_internal()) + t->chk_component_internal(type_chain, p_what); + } + } + if (t_last->u.signature.return_type && + t_last->u.signature.return_type->is_component_internal()) { + t_last->u.signature.return_type->chk_component_internal(type_chain, + p_what); + } + if (t_last->u.signature.exceptions) { + size_t nof_types = t_last->u.signature.exceptions->get_nof_types(); + for (size_t i=0; iu.signature.exceptions->get_type_byIndex(i); + if (t->is_component_internal()) + t->chk_component_internal(type_chain, p_what); + } + } + break; + default: + FATAL_ERROR("Type::chk_component_internal()"); + } + type_chain.erase(t_last); + } break; + default: //all other types are Ok. + break; + } // switch + } + + Type::typetype_t Type::search_for_not_allowed_type(map& type_chain, + map& not_allowed) + { + if (!checked) chk(); + Type* t_last = get_type_refd_last(); + Type::typetype_t ret = t_last->typetype; + + if (not_allowed.has_key(t_last->typetype)) { + return ret; + } + + switch (t_last->typetype) { + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: + case T_SEQOF: + case T_SETOF: + case T_ARRAY: { + if (type_chain.has_key(t_last)) { + break; + } + type_chain.add(t_last, 0); + switch (t_last->typetype) { + case T_CHOICE_T: + case T_SEQ_T: + case T_SET_T: { + size_t nof_comps = t_last->get_nof_comps(); + for (size_t i = 0; i < nof_comps; ++i) { + Type* t = t_last->get_comp_byIndex(i)->get_type(); + ret = t->search_for_not_allowed_type(type_chain, not_allowed); + if (not_allowed.has_key(ret)) { + return ret; + } + } + } break; + case T_SEQOF: + case T_SETOF: + case T_ARRAY: + ret = t_last->get_ofType()->search_for_not_allowed_type(type_chain, not_allowed); + if (not_allowed.has_key(ret)) { + return ret; + } + break; + default: + break; + } + type_chain.erase(t_last); + } + break; + default: + break; + } + return t_last->typetype; + } + + 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()) { + pos = dispname.find("__", pos); + if (pos == dispname.size()) { + break; + } + dispname.replace(pos, 1, ""); + ++pos; + } + return dispname; + } + +} // namespace Common + diff --git a/compiler2/Type.hh b/compiler2/Type.hh new file mode 100644 index 0000000..f15b4e5 --- /dev/null +++ b/compiler2/Type.hh @@ -0,0 +1,1161 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#ifndef _Common_Type_HH +#define _Common_Type_HH + +#include "Setting.hh" +#include "Code.hh" +#include "Int.hh" +#include "subtype.hh" +#include "ttcn3/rawASTspec.h" +#include "ttcn3/RawAST.hh" +#include "ttcn3/TextAST.hh" +#include "ttcn3/BerAST.hh" +#include "ttcn3/JsonAST.hh" +#include + +class XerAttributes; +enum namedbool { INCOMPLETE_NOT_ALLOWED = 0, INCOMPLETE_ALLOWED = 1, + NO_SUB_CHK = 0, SUB_CHK = 2, OMIT_NOT_ALLOWED = 0, OMIT_ALLOWED = 3, + ANY_OR_OMIT_NOT_ALLOWED = 0, ANY_OR_OMIT_ALLOWED = 4, + NOT_IMPLICIT_OMIT = 0, IMPLICIT_OMIT = 5, NOT_STR_ELEM = 0, IS_STR_ELEM = 6 +}; + +namespace Asn { + // not defined here + class Tags; + class Tag; + class TagCollection; + class Block; + class OC_defn; + class TableConstraint; +} // namespace Asn + +namespace Ttcn { + // not defined here + class ArrayDimension; + class FieldOrArrayRefs; + class Template; + class Definitions; + class Definition; + class SingleWithAttrib; + class MultiWithAttrib; + class WithAttribPath; + class FormalPar; + class FormalParList; + class Reference; + class PortTypeBody; + class Def_Type; + class Ref_pard; +} // namespace Ttcn + +// not defined here +class JSON_Tokenizer; + +namespace Common { + + /** + * \ingroup AST + * + * \defgroup AST_Type Type + * @{ + */ + using Asn::Tag; + using Asn::Tags; + using Asn::TagCollection; + using Asn::Block; + using Asn::OC_defn; + using Asn::TableConstraint; + using Ttcn::Template; + + class Type; + + // not defined here + class Identifier; + class Constraints; + class Value; + class CompField; + class CompFieldMap; + class EnumItem; + class EnumItems; + class ExcSpec; + class NamedValues; + class CTs_EE_CTs; + class TypeSet; + class TypeChain; + class TypeCompatInfo; + class ComponentTypeBody; + class SignatureParam; + class SignatureParamList; + class SignatureExceptions; + class CodeGenHelper; + + /** + * This is the base class for types. + */ + class Type : public Governor { + public: + + /** type of type */ + enum typetype_t { + /** Undefined. + * There is never a Type object with this typetype. + * It may be returned by Value::get_expr_returntype() or + * ValueRange::get_expr_returntype(). */ + T_UNDEF, + T_ERROR, /**< erroneous (e.g. nonexistent reference) */ + T_NULL, /**< null (ASN.1) */ + T_BOOL, /**< boolean */ + T_INT, /**< integer */ + T_INT_A, /**< integer / ASN */ + T_REAL, /**< real/float */ + T_ENUM_A, /**< enumerated / ASN */ + T_ENUM_T, /**< enumerated / TTCN */ + T_BSTR, /**< bitstring */ + T_BSTR_A, /**< bitstring */ + T_HSTR, /**< hexstring (TTCN-3) */ + T_OSTR, /**< octetstring */ + T_CSTR, /**< charstring (TTCN-3) */ + T_USTR, /**< universal charstring (TTCN-3) */ + T_UTF8STRING, /**< UTF8String (ASN.1) */ + T_NUMERICSTRING, /**< NumericString (ASN.1) */ + T_PRINTABLESTRING, /**< PrintableString (ASN.1) */ + T_TELETEXSTRING, /**< TeletexString (ASN.1) */ + T_VIDEOTEXSTRING, /**< VideotexString (ASN.1) */ + T_IA5STRING, /**< IA5String (ASN.1) */ + T_GRAPHICSTRING, /**< GraphicString (ASN.1) */ + T_VISIBLESTRING, /**< VisibleString (ASN.1) */ + T_GENERALSTRING, /**< GeneralString (ASN.1) */ + T_UNIVERSALSTRING, /**< UniversalString (ASN.1) */ + T_BMPSTRING, /**< BMPString (ASN.1) */ + T_UNRESTRICTEDSTRING, /**< UnrestrictedCharacterString (ASN.1) */ + T_UTCTIME, /**< UTCTime (ASN.1) */ + T_GENERALIZEDTIME, /**< GeneralizedTime (ASN.1) */ + T_OBJECTDESCRIPTOR, /** Object descriptor, a kind of string (ASN.1) */ + T_OID, /**< object identifier */ + T_ROID, /**< relative OID (ASN.1) */ + T_CHOICE_A, /**< choice /ASN, uses u.secho */ + T_CHOICE_T, /**< union /TTCN, uses u.secho */ + T_SEQOF, /**< sequence (record) of */ + T_SETOF, /**< set of */ + T_SEQ_A, /**< sequence /ASN, uses u.secho */ + T_SEQ_T, /**< record /TTCN, uses u.secho */ + T_SET_A, /**< set /ASN, uses u.secho */ + T_SET_T, /**< set /TTCN, uses u.secho */ + T_OCFT, /**< ObjectClassFieldType (ASN.1) */ + T_OPENTYPE, /**< open type (ASN.1) */ + T_ANY, /**< ANY (deprecated ASN.1) */ + T_EXTERNAL, /**< %EXTERNAL (ASN.1) */ + T_EMBEDDED_PDV, /**< EMBEDDED PDV (ASN.1) */ + T_REFD, /**< referenced */ + T_REFDSPEC, /**< special referenced (by pointer, not by name) */ + T_SELTYPE, /**< selection type (ASN.1) */ + T_VERDICT, /**< verdict type (TTCN-3) */ + T_PORT, /**< port type (TTCN-3) */ + T_COMPONENT, /**< component type (TTCN-3) */ + T_ADDRESS, /**< address type (TTCN-3) */ + T_DEFAULT, /**< default type (TTCN-3) */ + T_ARRAY, /**< array (TTCN-3), uses u.array */ + T_SIGNATURE, /**< signature (TTCN-3) */ + T_FUNCTION, /**< function reference (TTCN-3) */ + T_ALTSTEP, /**< altstep reference (TTCN-3) */ + T_TESTCASE, /**< testcase reference (TTCN-3) */ + T_ANYTYPE, /**< anytype (TTCN-3) */ + // WRITE new type before this line + T_LAST + }; //DO NOT FORGET to update type_as_string[] in Type.cc + + /** + * Enumeration to represent message encoding types. + */ + enum MessageEncodingType_t { + CT_UNDEF, /**< undefined/unused */ + CT_BER, /**< ASN.1 BER */ + CT_PER, /**< ASN.1 PER (not supported yet) */ + CT_RAW, /**< TTCN-3 RAW */ + CT_TEXT, /**< TTCN-3 TEXT */ + CT_XER, /**< ASN.1 XER */ + CT_JSON /**< TTCN-3 JSON */ + }; + + /** selector for value checking algorithms */ + enum expected_value_t { + /** the value must be known at compile time (i.e. it may refer + * to a TTCN-3 constant or an ASN.1 value) */ + EXPECTED_CONSTANT, + /** the value must be static at execution time, but may be + * unknown at compilation time (i.e. it may refer to a TTCN-3 + * module parameter as well) */ + EXPECTED_STATIC_VALUE, + /** the value is known only at execution time (i.e. it may refer + * to a variable in addition to static values) */ + EXPECTED_DYNAMIC_VALUE, + /** the reference may point to a dynamic value or a template + * (this selector is also used in template bodies where the + * variable references are unaccessible because of the scope + * hierarchy) */ + EXPECTED_TEMPLATE + }; + + /** Enumeration to represent the owner of the type. + * Also align OT_UNKNOWN at line 200. */ + enum TypeOwner_t { + OT_UNKNOWN, + OT_TYPE_ASS, ///< ASN.1 type assignment (Ass_T) + OT_VAR_ASS, ///< ASN.1 variable assignment (Ass_V) + OT_VSET_ASS, ///< ASN.1 value set assignment (Ass_VS) + OT_TYPE_FLD, ///< ASN.1 TypeFieldSpec (FieldSpec_T) + OT_FT_V_FLD, ///< ASN.1 FixedTypeValueFieldSpec (FieldSpec_V_FT) + OT_TYPE_MAP, ///< TTCN-3 TypeMapping + OT_TYPE_MAP_TARGET, ///< TTCN-3 TypeMappingTarget + OT_TYPE_DEF, ///< TTCN-3 type definition (Def_Type) + OT_CONST_DEF, ///< TTCN-3 constant definition (DefConst, Def_ExtCOnst) + OT_MODPAR_DEF, ///< TTCN-3 module parameter definition (Def_Modulepar) + OT_VAR_DEF, ///< TTCN-3 variable definition (Def_Var) + OT_VARTMPL_DEF, ///< TTCN-3 var template definition (Def_Var_Template) + OT_FUNCTION_DEF, ///< TTCN-3 function (Def_Function, Def_ExtFunction) + OT_TEMPLATE_DEF, ///< TTCN-3 template definition (Def_Template) + OT_ARRAY, ///< another Type: TTCN-3 array(T_ARRAY) + OT_RECORD_OF, ///< another Type (T_SEQOF, T_SETOF), ASN.1 or TTCN-3 + OT_FUNCTION, ///< another Type: TTCN-3 function (T_FUNCTION) + OT_SIGNATURE, ///< another Type: TTCN-3 signature (T_SIGNATURE) + OT_REF, ///< another Type (T_REFD) + OT_REF_SPEC, ///< another Type (T_REFDSPEC) + OT_COMP_FIELD, ///< a field of a record/set/union (CompField) + OT_COMPS_OF, ///< ASN.1 "COMPONENTS OF" (CT_CompsOf) + OT_FORMAL_PAR, ///< formal parameter (FormalPar), TTCN-3 + OT_TYPE_LIST, ///< TypeList for a 'with "extension anytype t1,t2..." ' + OT_FIELDSETTING, ///< ASN.1 FieldSetting_Type + OT_SELTYPE, ///< another Type (T_SELTYPE), ASN.1 selection type + OT_OCFT, ///< another Type (T_OCFT), ASN.1 obj.class field type + OT_TEMPLATE_INST, ///< a TemplateInstance (TTCN-3) + OT_RUNSON_SCOPE, ///< a RunsOnScope (TTCN-3) + OT_EXC_SPEC, ///< exception Specification (ExcSpec) + OT_SIG_PAR, ///< signature parameter (SignatureParam) + OT_POOL ///< It's a pool type, owned by the type pool + }; + + /** Returns the display string of \a encoding_type. */ + static const char *get_encoding_name(MessageEncodingType_t encoding_type); + /** Returns a pool type that represents the encoded stream of the given + * \a encoding_type. */ + static Type *get_stream_type(MessageEncodingType_t encoding_type); + + enum truth { + No, Maybe, Yes + }; + + private: + typetype_t typetype; + bool tags_checked; + bool tbl_cons_checked; + bool text_checked; + bool json_checked; + bool raw_parsed; + bool raw_checked; + bool xer_checked; + bool raw_length_calculated; + bool has_opentypes; + bool opentype_outermost; + bool code_generated; + bool embed_values_possible; + bool use_nil_possible; + bool use_order_possible; + int raw_length; + Type *parent_type; + Tags *tags; + Constraints *constraints; + /// The type's attributes (with context) + Ttcn::WithAttribPath* w_attrib_path; + /** A copy of all the AT_ENCODEs */ + Ttcn::WithAttribPath* encode_attrib_path; + RawAST *rawattrib; + TextAST *textattrib; + XerAttributes *xerattrib; + BerAST *berattrib; + JsonAST *jsonattrib; + + vector *parsed_restr; ///< parsed subtype restrictions are stored here until they are moved to the sub_type member + SubType *sub_type; ///< effective/aggregate subtype of this type, NULL if neither inherited nor own subtype restrictions exist + + string encoding_str; // needed by codegen for encvalue() and decvalue() + string decoding_str; + bool coding_by_function; // false - coding attribute is set, true - coding via coding function + /** What kind of AST element owns the type. + * It may not be known at creation type, so it's initially OT_UNKNOWN. + * We want this information so we don't have to bother with XER + * if the type is an ASN.1 construct, or it's the type in a "runs on" scope, + * the type of a variable declaration/module par/const, etc. */ + TypeOwner_t ownertype; + Node *owner; + + union { + struct { + Block *block; + NamedValues *nvs; + } namednums; + struct { + EnumItems *eis; ///< Final set of enum items + Int first_unused; ///< First unused >=0 value (for UNKNOWN_VALUE) + Int second_unused; ///< Second unused >=0 value (for UNBOUND_VALUE) + Block *block; ///< ASN.1 block to be parsed + EnumItems *eis1; ///< First set of enum items before the ellipsis + bool ellipsis; ///< true if there was an ellipsis, false otherwise + ExcSpec *excSpec; ///< Exception specification + EnumItems *eis2; ///< Second set of enum items after the ellipsis + map *eis_by_name; + } enums; + struct { + CompFieldMap *cfm; + Block *block; ///< Unparsed block; will be 0 after parse_block_...() + CTs_EE_CTs *ctss; + bool tr_compsof_ready; + bool component_internal; + map *field_by_name; + OC_defn *oc_defn; /**< link to... */ + const Identifier *oc_fieldname; /**< link to... */ + const TableConstraint *my_tableconstraint; /**< link to... */ + bool has_single_charenc; /**< Has a single character-encodable field + * with the UNTAGGED encoding instruction. + * X693amd1 32.2.2 applies to the field. */ + } secho; /**< data for T_(SEQUENCE|SET_CHOICE)_[AT] */ + struct { + Type *ofType; + bool component_internal; + } seof; /**< data for SEQUENCE OF/SET OF */ + struct { + Reference *ref; + Type *type_refd; /**< link to... */ + OC_defn *oc_defn; /**< link to... */ + const Identifier *oc_fieldname; /**< link to... */ + bool component_internal; + } ref; + struct { + Identifier *id; + Type *type; + Type *type_refd; + } seltype; + struct { + Type *element_type; + Ttcn::ArrayDimension *dimension; + bool in_typedef; + bool component_internal; + } array; + Ttcn::PortTypeBody *port; + ComponentTypeBody *component; + Type *address; /**< link to... */ + struct { + SignatureParamList *parameters; + Type *return_type; + bool no_block; + bool component_internal; + SignatureExceptions *exceptions; + } signature; + struct { + Ttcn::FormalParList *fp_list; + struct { + bool self; + Ttcn::Reference *ref; + Type *type; // useful only after check + } runs_on; + union { + Type *return_type; + struct { + Ttcn::Reference *ref; + Type *type; // useful only after check + } system; + }; + bool returns_template; + template_restriction_t template_restriction; + bool is_startable; + } fatref; + } u; + static const char* type_as_string[]; + + /** True if chk() has finished running. + * Prevents force_raw() from running chk_raw(), chk_text() or chk_json() on unchecked types. */ + bool chk_finished; + + /** Copy constructor, for the use of Type::clone() only. */ + Type(const Type& p); + /** Assignment disabled */ + Type& operator=(const Type& p); + /** Set fields to their default values */ + void init(); + /** Free up resources */ + void clean_up(); + /** Returns the default tag of the type. */ + Tag *get_default_tag(); + /** Returns the number in UNIVERSAL tag class that belongs to ASN.1 type + * type \a p_tt. In case of invalid argument -1 is returned */ + static int get_default_tagnumber(typetype_t p_tt); + /** Container for the allocated tags that do not belong to a particular + * Type object */ + static map *default_tags; + static void destroy_default_tags(); + /** Container for the allocated pool types */ + static map *pooltypes; + /** Drops the elements of \a pooltypes */ + static void destroy_pooltypes(); + /** Returns the TTCN-3 equivalent of \a p_tt. */ + static typetype_t get_typetype_ttcn3(typetype_t p_tt); + + public: + /** @name Constructors + * @{ */ + /// Construct a predefined type (including anytype and address) + Type(typetype_t p_tt); + /// Construct a TTCN enumerated type + Type(typetype_t p_tt, EnumItems *p_eis); + /** Construct an ASN.1 enum, sequence, set, choice, integer with + * named numbers, or a bitstring with named bits */ + Type(typetype_t p_tt, Block *p_block); + /// Construct an ASN.1 enum, with or without extension + Type(typetype_t p_tt, + EnumItems *p_eis1, bool p_ellipsis, EnumItems *p_eis2); + /// Construct a TTCN3 sequence, set or choice + Type(typetype_t p_tt, CompFieldMap *p_cfm); + /** Construct a type with an embedded type: a record-of, set-of, + * or a special reference (involved in: ASN.1 table constraint, + * TTCN3 (ext)const definition, module parameter, variable instance) */ + Type(typetype_t p_tt, Type *p_type); + /// Create an ASN.1 selection type + Type(typetype_t p_tt, Identifier *p_id, Type *p_type); + /// ASN.1 ObjectClassFieldType + Type(typetype_t p_tt, Type *p_type, OC_defn *p_oc_defn, + const Identifier *p_id); + /// Create a TTCN3 array + Type(typetype_t p_tt, Type *p_type, Ttcn::ArrayDimension *p_dim, + bool p_in_typedef); + /// Create an ASN.1 open type + Type(typetype_t p_tt, OC_defn *p_oc_defn, const Identifier *p_id); + /// Create a reference + Type(typetype_t p_tt, Reference *p_ref); + /// Create a TTCN3 port type + Type(typetype_t p_tt, Ttcn::PortTypeBody *p_pb); + /// Create a TTCN3 component type + Type(typetype_t p_tt, ComponentTypeBody *p_cb); + /// Create a TTCN3 signature + Type(typetype_t p_tt, SignatureParamList *p_params, Type *p_returntype, + bool p_noblock, SignatureExceptions *p_exceptions); + /// Create a TTCN3 function reference + Type(typetype_t p_tt,Ttcn::FormalParList *p_params, + Ttcn::Reference* p_runs_on_ref, bool p_runs_on_self, + Type *p_returntype, bool p_returns_template, + template_restriction_t p_template_restriction); + /// Create a TTCN3 altstep + Type(typetype_t p_tt,Ttcn::FormalParList *p_params, + Ttcn::Reference* p_runs_on_ref, bool p_runs_on_self); + /// Create a TTCN3 testcase + Type(typetype_t p_tt,Ttcn::FormalParList *p_params, + Ttcn::Reference* p_runs_on_ref, Ttcn::Reference *p_system_ref); + /** @} */ + virtual ~Type(); + /** This function must be called to clean up the pool types, + * tags, etc. It is called by main() */ + static void free_pools(); + /** Create a (partial) copy of the object */ + virtual Type* clone() const; + /** Return the type of type. */ + typetype_t get_typetype() const { return typetype; } + /** Returns the TTCN-3 equivalent of \a typetype. */ + typetype_t get_typetype_ttcn3() const + { return get_typetype_ttcn3(typetype); } + /** Returns a simple/built-in type from the pool */ + static Type* get_pooltype(typetype_t p_typetype); + /** Returns whether the type is defined in an ASN.1 module. */ + bool is_asn1() const; + /** Returns true if it is a type reference. */ + bool is_ref() const; + /** Returns true if it is a Sequence, Set or Choice. */ + bool is_secho() const; + /** Returns true if this is a character-encodable type. + * Being character-encodable is a requirement for a type to be + * encoded as an XML attribute. */ + truth is_charenc(); + /** Return true if at least one abstract value of the type + * has an empty "ExtendedXMLValue" encoding (only possible with EXER). + * Possible for record/set when all components are optional, + * and record-of/set-of when 0 length is not forbidden. */ + bool has_empty_xml(); + /** Returns whether \a this is a sequence-of/record-of or set-of type. */ + bool is_seof() const { return typetype == T_SEQOF || typetype == T_SETOF; } + /** Returns the \a sub_type member */ + SubType* get_sub_type() const { return sub_type; } + /** If this is a reference, returns the referenced type. + * Otherwise, it's a fatal error. */ + Type* get_type_refd(ReferenceChain *refch=0); + /** Walk through all references to the referenced type */ + Type* get_type_refd_last(ReferenceChain *refch=0); + /** Returns the type of the field, which is referenced by \a subrefs from + * \a this. It checks the array indices against \a expected_index. In case + * of error NULL is returned. + * Special case: if \a interrupt_if_optional is true then return NULL if an + * optional field has been reached. Using this bool parameter it can be + * checked if a referenced field is on an optional path (used by template + * restriction checking code) */ + Type *get_field_type(Ttcn::FieldOrArrayRefs *subrefs, + expected_value_t expected_index, ReferenceChain *refch = 0, + bool interrupt_if_optional = false); + /** subrefs must point to an existing field, get_field_type() should be used + * to check. subrefs_array will be filled with the indexes of the fields, + * type_array will be filled with types whose field indexes were collected, + * if an invalid index is encountered false will be returned */ + bool get_subrefs_as_array(const Ttcn::FieldOrArrayRefs *subrefs, + dynamic_array& subrefs_array, dynamic_array& type_array); + /** Returns whether the last field referenced by \a subrefs is an optional + * record/SEQUENCE or set/SET field. It can be used only after a successful + * semantic check (e.g. during code generation) or the behaviour will be + * unpredictable. */ + bool field_is_optional(Ttcn::FieldOrArrayRefs *subrefs); + /** Returns whether this type instance is the type of an optional field. */ + bool is_optional_field() const; + virtual void set_fullname(const string& p_fullname); + /** Sets the internal pointer my_scope to \a p_scope. */ + virtual void set_my_scope(Scope *p_scope); + /** Checks the type (including tags). */ + virtual void chk(); + /** Return whether the two typetypes are compatible. Sometimes, this is + * just a question of \p p_tt1 == \p p_tt2. When there are multiple + * typetypes for a type (e.g. T_ENUM_A and T_ENUM_T) then all + * combinations of those are compatible. */ + static bool is_compatible_tt_tt(typetype_t p_tt1, typetype_t p_tt2, + bool p_is_asn11, bool p_is_asn12); + /** Returns whether the type is compatible with \a p_tt. Used if the + * other value is unfoldable, but we can determine its expr_typetype. + * Note: The compatibility relation is asymmetric. The function returns + * true if the set of possible values in \a p_type is a subset of + * possible values in \a this. */ + bool is_compatible_tt(typetype_t p_tt, bool p_is_asn1); + /** Returns whether this type is compatible with \a p_type. Note: The + * compatibility relation is asymmetric. The function returns true if + * the set of possible values in \a p_type is a subset of possible values + * in \a this. It returns false if the two types cannot be compatible + * ever. If the two types are compatible, but they need additional + * "type" conversion code generated with run-time checks \p p_info will + * provide more information. \p p_info is used to collect type + * information to report more precise errors. \p p_left_chain and + * \p p_right_chain are there to prevent infinite recursion. + * \p p_left_chain contains the type chain of the left operand from the + * "root" type to this point in the type's structure. \p p_right_chain + * is the same for the right operand. */ + bool is_compatible(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain = NULL, + TypeChain *p_right_chain = NULL); + /** Check if the restrictions of a T_SEQOF/T_SETOF are "compatible" with + * the given type \a p_type. Can be called only as a T_SEQOF/T_SETOF. + * Currently, used for structured types only. \a p_type can be any kind + * of structured type. */ + bool is_subtype_length_compatible(Type *p_type); + /** Check if it's a structured type. Return true if the current type is a + * structured type, false otherwise. */ + bool is_structured_type() const; + /** returns the type as a string */ + virtual const char* asString() const; + static const char* asString(typetype_t type); + + private: + /** Helper functions for is_compatible(). These functions can be called + * only for a Type that the name suggests. \p p_type is the Type we're + * checking compatibility against. \p p_info is used to collect type + * information to report more precise errors. \p p_left_chain and + * \p p_right_chain are there to prevent infinite recursion. + * \p p_left_chain contains the type chain of the left operand from the + * "root" type to this point in the type's structure. \p p_right_chain + * is the same for the right operand. */ + bool is_compatible_record(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain = NULL, + TypeChain *p_right_chain = NULL); + bool is_compatible_record_of(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain = NULL, + TypeChain *p_right_chain = NULL); + bool is_compatible_set(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain = NULL, + TypeChain *p_right_chain = NULL); + bool is_compatible_set_of(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain = NULL, + TypeChain *p_right_chain = NULL); + bool is_compatible_array(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain = NULL, + TypeChain *p_right_chain = NULL); + bool is_compatible_choice_anytype(Type *p_type, TypeCompatInfo *p_info, + TypeChain *p_left_chain = NULL, + TypeChain *p_right_chain = NULL); + public: + /** Returns whether this type is identical to \a p_type from TTCN-3 point + * of view. Note: This relation is symmetric. The function returns true + * only if the sets of possible values are the same in both types. */ + bool is_identical(Type *p_type); + /** Tasks: Decides whether the type needs automatic tagging, performs the + * COMPONENTS OF transformations (recursively) and adds the automatic + * tags. */ + void tr_compsof(ReferenceChain *refch = 0); + /** Returns whether the T_FUNCTION is startable. + * @pre typetype is T_FUNCTION, or else FATAL_ERROR occurs. */ + bool is_startable(); + + /** Returns true if this is a list type (string, rec.of, set.of or array */ + bool is_list_type(bool allow_array); + + void chk_coding(bool encode); + bool is_coding_by_function() const; + const string& get_coding(bool encode) const; + private: + static MessageEncodingType_t get_enc_type(const Ttcn::SingleWithAttrib& enc); + + void chk_Int_A(); + void chk_Enum_A(); + void chk_Enum_item(EnumItem *ei, bool after_ellipsis, + map& value_map); + void chk_Enum_T(); + void chk_BStr_A(); + void chk_SeCho_T(); + void chk_Choice_A(); + void chk_Se_A(); + void chk_SeOf(); + void chk_refd(); + void chk_seltype(); + void chk_Array(); + void chk_Signature(); + void chk_Fat(); + public: + /** Checks whether the type can be the TTCN-3 address type. Not allowed: + * the default type, references pointing to port types, component types + * and signatures */ + void chk_address(); + /** Checks whether the type can be a component of another type definition + * (e.g. field of a structured type, parameter/return type/exception of a + * signature). + * Not allowed types: ports, signatures. + * Default type is allowed only within structured types. + * The text for the end of the error message is passed as parameter. + */ + void chk_embedded(bool default_allowed, const char *error_msg); + /** Checks for circular references within embedded types */ + void chk_recursions(ReferenceChain& refch); + /** Checks that the structured type does not have fields + * with the name of its definition. + */ + void chk_constructor_name(const Identifier& p_id); + bool chk_startability(); + /** Checks if it can be a return type */ + void chk_as_return_type(bool as_value, const char* what); + private: + void parse_block_Int(); + void parse_block_Enum(); + void parse_block_BStr(); + void parse_block_Choice(); + void parse_block_Se(); + int get_length_multiplier(); + void parse_attributes(); + void chk_raw(); + /** If the type does not have a rawattrib, create one. */ + void force_raw(); + void chk_text(); + void chk_text_matching_values(textAST_matching_values *matching_values, + const char *attrib_name); + /** If the type does not have a textattrib, create one. */ + void force_text(); + + void chk_json(); + void chk_json_default(); + /** If the type does not have a jsonattrib, create one. */ + void force_json(); + + void chk_xer(); + void chk_xer_any_attributes(); + void chk_xer_any_element(); + void chk_xer_attribute(); + void chk_xer_dfe(); + Value *new_value_for_dfe(Type *last, const char *dfe_str); + void target_of_text(string& text); + void chk_xer_embed_values(int num_attributes); + void chk_xer_text(); + void chk_xer_untagged(); + void chk_xer_use_nil(); + void chk_xer_use_order(int num_attributes); + void chk_xer_use_type(); + void chk_xer_use_union(); + + bool is_root_basic(); + int get_raw_length(); + public: + void set_parent_type(Type *p_parent_type) {parent_type=p_parent_type;} + Type* get_parent_type() const {return parent_type;} + void set_has_opentypes() {has_opentypes=true;} + bool get_has_opentypes() const {return has_opentypes;} + void set_opentype_outermost() {opentype_outermost=true;} + bool get_is_opentype_outermost() const {return opentype_outermost;} + /** If \a value is an undef lowerid, then this member decides + * whether it is a reference or a lowerid value (e.g., enum, named + * number). */ + void chk_this_value_ref(Value *value); + bool chk_this_value(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, namedbool incomplete_allowed, + namedbool omit_allowed, namedbool sub_chk, + namedbool implicit_omit = NOT_IMPLICIT_OMIT, + namedbool str_elem = NOT_STR_ELEM); + /** Checks the given referenced value */ + bool chk_this_refd_value(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, ReferenceChain *refch=0, + namedbool str_elem = NOT_STR_ELEM); + /** Checks the given invocation */ + void chk_this_invoked_value(Value *value, Common::Assignment *lhs, + expected_value_t expected_value); + private: + void chk_this_value_Null(Value *value); + void chk_this_value_Bool(Value *value); + void chk_this_value_Int(Value *value); + void chk_this_value_Int_A(Value *value); + void chk_this_value_Real(Value *value); + void chk_this_value_Enum(Value *value); + void chk_this_value_BStr(Value *value); + void chk_this_value_namedbits(Value *value); + void chk_this_value_BStr_A(Value *value); + void chk_this_value_HStr(Value *value); + void chk_this_value_OStr(Value *value); + void chk_this_value_CStr(Value *value); + void chk_this_value_OID(Value *value); + void chk_this_value_ROID(Value *value); + void chk_this_value_Any(Value *value); + bool chk_this_value_Choice(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, namedbool incomplete_allowed, + namedbool implicit_omit = NOT_IMPLICIT_OMIT); + bool chk_this_value_Se(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, namedbool incomplete_allowed, + namedbool implicit_omit = NOT_IMPLICIT_OMIT); + bool chk_this_value_Se_T(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, namedbool incomplete_allowed, + namedbool implicit_omit = NOT_IMPLICIT_OMIT); + bool chk_this_value_Seq_T(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, namedbool incomplete_allowed, + namedbool implicit_omit = NOT_IMPLICIT_OMIT); + bool chk_this_value_Set_T(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, namedbool incomplete_allowed, + namedbool implicit_omit = NOT_IMPLICIT_OMIT); + bool chk_this_value_Se_A(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, namedbool implicit_omit); + bool chk_this_value_Seq_A(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, namedbool implicit_omit); + bool chk_this_value_Set_A(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, namedbool implicit_omit); + bool chk_this_value_SeOf(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, namedbool incomplete_allowed, + namedbool implicit_omit = NOT_IMPLICIT_OMIT); + void chk_this_value_Verdict(Value *value); + void chk_this_value_Default(Value *value); + bool chk_this_value_Array(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, namedbool incomplete_allowed, + namedbool implicit_omit); + bool chk_this_value_Signature(Value *value, Common::Assignment *lhs, + expected_value_t expected_value, namedbool incomplete_allowed); + void chk_this_value_Component(Value *value); + void chk_this_value_FAT(Value *value); + public: + /** Checks whether template \a t is a specific value and the embedded value + * is a referenced one. If the reference in the value points to a + * template-like entity then it sets the template type to TEMPLATE_REFD, + * otherwise it leaves everything as is. */ + void chk_this_template_ref(Template *t); + /** Checks for self references in functions returning templates (external or otherwise) + * and in parametrised templates. Returns true if the reference in assignment \a lhs + * is found. + * Recursive: calls itself incase of multiple embedded functions / parametrised templates.*/ + bool chk_this_template_ref_pard(Ttcn::Ref_pard* ref_pard, Common::Assignment* lhs); + bool chk_this_template_generic(Template *t, namedbool incomplete_allowed, + namedbool allow_omit, namedbool allow_any_or_omit, namedbool sub_chk, + namedbool implicit_omit, Common::Assignment *lhs); + private: + bool chk_this_refd_template(Template *t, Common::Assignment *lhs); + void chk_this_template_length_restriction(Template *t); + bool chk_this_template(Template *t, namedbool is_modified, namedbool sub_chk, + namedbool implicit_omit, Common::Assignment *); + void chk_this_template_Str(Template *t); + /** Checks whether \a v is a correct range boundary for this type. + * Applicable to the following types: integer, float, charstring, + * universal charstring. + * Argument \a v might be NULL in case of + or - infinity. + * Argument \a which shall contain the word "lower" or "upper". + * Argument \a loc is used for error reporting if \a v is NULL (it points + * to the surrounding template). + * 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_this_template_builtin(Template *t); + void chk_this_template_Int_Real(Template *t); + void chk_this_template_Enum(Template *t); + bool chk_this_template_Choice(Template *t, namedbool is_modified, + namedbool implicit_omit, Common::Assignment *lhs); + bool chk_this_template_Seq(Template *t, namedbool is_modified, + namedbool implicit_omit, Common::Assignment *lhs); + bool chk_this_template_Set(Template *t, namedbool is_modified, + namedbool implicit_omit, Common::Assignment *lhs); + bool chk_this_template_SeqOf(Template *t, namedbool is_modified, + namedbool implicit_omit, Common::Assignment *lhs); + bool chk_this_template_SetOf(Template *t, namedbool is_modified, + namedbool implicit_omit, Common::Assignment *lhs); + bool chk_this_template_array(Template *t, namedbool is_modified, + namedbool implicit_omit, Common::Assignment *lhs); + void chk_this_template_Fat(Template *t); + void chk_this_template_Signature(Template *t, namedbool is_modified); + public: + /** Check whether there is an enum item with the given name. + * + * @pre typetype is T_ENUM_T or T_ENUM_A */ + bool has_ei_withName(const Identifier& p_id) const; + + /** Return the enum item with the given name. + * + * @pre typetype is T_ENUM_T or T_ENUM_A */ + EnumItem *get_ei_byName(const Identifier& p_id) const; + + /** Return the enum item with the given index. + * + * @pre typetype is T_ENUM_T or T_ENUM_A */ + EnumItem *get_ei_byIndex(size_t i) const; + + /** Get the number of components. + * + * @return the number of components from the appropriate alternative + * depending on the \a typetype. + * + * @pre \a typetype is one of T_CHOICE_T, T_SEQ_T, T_SET_T, T_OPENTYPE, + * T_SEQ_A, T_SET_A, T_CHOICE_A, T_ARRAY, T_SIGNATURE, T_ANYTYPE */ + size_t get_nof_comps(); + + /** Get the name (id) of the component with the given index. + * + * @pre \a typetype is one of T_CHOICE_T, T_SEQ_T, T_SET_T, T_OPENTYPE, + * T_SEQ_A, T_SET_A, T_CHOICE_A, T_SIGNATURE, T_ANYTYPE + * + * @note Not valid for T_ARRAY */ + const Identifier& get_comp_id_byIndex(size_t n); + + /** Get the component with the given index. + * + * @pre \a typetype is one of T_CHOICE_T, T_SEQ_T, T_SET_T, T_OPENTYPE, + * T_SEQ_A, T_SET_A, T_CHOICE_A, T_ANYTYPE + * + * @note Not valid for T_ARRAY or T_SIGNATURE */ + CompField* get_comp_byIndex(size_t n); + + /** Get the index of the component with the given name + * + * @pre \a typetype of the last referenced type is one of + * T_CHOICE_T, T_SEQ_T, T_SET_T, T_OPENTYPE, + * T_SEQ_A, T_SET_A, T_CHOICE_A, T_ANYTYPE */ + size_t get_comp_index_byName(const Identifier& p_name); + + /** Get the index of the enum item with the given name + * + * @pre typetype is T_ENUM_T or T_ENUM_A */ + size_t get_eis_index_byName(const Identifier& p_name); + + const Int& get_enum_val_byId(const Identifier& p_name); + + size_t get_nof_root_comps(); + CompField* get_root_comp_byIndex(size_t n); + + /** Get the name (id) of the component with the given index. + * + * @pre \a typetype is one of T_CHOICE_T, T_SEQ_T, T_SET_T, T_OPENTYPE, + * T_SEQ_A, T_SET_A, T_CHOICE_A, T_SIGNATURE, T_ANYTYPE + * + * @note Not valid for T_ARRAY */ + bool has_comp_withName(const Identifier& p_name); + CompField* get_comp_byName(const Identifier& p_name); + void add_comp(CompField *p_cf); + + /** Returns the embedded type of 'sequence/record of', 'set of' or array + * types. */ + Type *get_ofType(); + + OC_defn* get_my_oc(); + const Identifier& get_oc_fieldname(); + void set_my_tableconstraint(const TableConstraint *p_tc); + const TableConstraint* get_my_tableconstraint(); + + /** Returns the array dimension. Applicable only if typetype == T_ARRAY. */ + Ttcn::ArrayDimension *get_dimension() const; + + /** Returns the PortTypeBody if typetype == T_PORT */ + Ttcn::PortTypeBody *get_PortBody() const; + + /** Returns the ComponentTypeBody if typetype == T_COMPONENT */ + ComponentTypeBody *get_CompBody() const; + + /** Returns the parameters of a signature. + * Applicable only if typetype == T_SIGNATURE. */ + SignatureParamList *get_signature_parameters() const; + /** Returns the parameters of a signature. + * Applicable only if typetype == T_SIGNATURE. */ + SignatureExceptions *get_signature_exceptions() const; + /** Returns the return type of a signature. + * Applicable only if typetype == T_SIGNATURE. */ + Type *get_signature_return_type() const; + /** Returns whether the type is a non-blocking signature. + * Applicable only if typetype == T_SIGNATURE. */ + bool is_nonblocking_signature() const; + /** Returns the parameters of a functionreference + * Applicable only if typetype == T_FUNCTION or T_ALTSTEP or T_TESTCASE */ + Ttcn::FormalParList *get_fat_parameters(); + /** Returns the return type of a functionreference + * Applicable only if typetype == T_FUNCTION */ + Type *get_function_return_type(); + /** Returns the runs on type of a functionreference + * Appliacable only if typetype == T_FUNCTION or T_ALTSTEP or T_TESTCASE */ + Type *get_fat_runs_on_type(); + /** Returns if a functionreference 'runs on self' + * Appliacable only if typetype == T_FUNCTION or T_ALTSTEP or T_TESTCASE */ + bool get_fat_runs_on_self(); + /** Applicable only if typetype == T_FUNCTION */ + bool get_returns_template(); + + /** Retruns true if it is a tagged type.*/ + bool is_tagged() const {return tags!=0;} + void add_tag(Tag *p_tag); + bool is_constrained() const {return constraints!=0;} + void add_constraints(Constraints *p_constraints); + Constraints* get_constraints() const {return constraints;} + Reference * get_Reference(); + private: + void chk_table_constraints(); + public: + /** Returns true if the type has multiple alternative tags + * (i.e. it is a non-tagged CHOICE type). */ + bool has_multiple_tags(); + /** Returns the tag of type. If this type is tagged, then the + * outermost tag is returned. */ + Tag *get_tag(); + void get_tags(TagCollection& coll, map& chain); + /** Returns the smallest possible tag. If !has_multiple_tags() + * then returns get_tag(). Used is SET CER encoding, see X.690 + * 9.3... */ + Tag *get_smallest_tag(); + /** Returns whether the type needs explicit tagging. */ + bool needs_explicit_tag(); + /** Removes the tag(s) from the type that was added during + * automatic tagging transformation. Needed for the implementation + * of COMPONENTS OF transformation. */ + void cut_auto_tags(); + Tags* build_tags_joined(Tags *p_tags=0); + void set_with_attr(Ttcn::MultiWithAttrib* p_attrib); + void set_parent_path(Ttcn::WithAttribPath* p_path); + Ttcn::WithAttribPath* get_attrib_path() const; + bool hasRawAttrs(); + bool hasNeedofRawAttrs(); + bool hasNeedofTextAttrs(); + bool hasNeedofJsonAttrs(); + bool hasNeedofXerAttrs(); + bool hasVariantAttrs(); + /** Returns whether the type has the encoding attribute specified by + * the parameter (either in its own 'with' statement or in the module's) */ + bool hasEncodeAttr(const MessageEncodingType_t encoding_type); + /** Returns whether \a this can be encoded according to rules + * \a p_encoding. + * @note Should be called only during code generation, after the entire + * AST has been checked, or else the compiler might choke on code like: + * type MyRecordOfType[-] ElementTypeAlias; */ + bool has_encoding(const MessageEncodingType_t encoding_type); + /** Generates the C++ equivalent class(es) of the type. */ + void generate_code(output_struct *target); + size_t get_codegen_index(size_t index); + private: + /** Generates code for the case when the C++ classes are implemented by + * hand, includes the header file with name sourcefile and extension hh + */ + void generate_code_include(const string& sourcefile, output_struct *target); + /** Generates code for the embedded types the C++ classes of which must be + * placed before the classes of this type (e.g. the types of mandatory + * record/set fields). */ + void generate_code_embedded_before(output_struct *target); + /** Generates code for the embedded types the C++ classes of which can be + * placed after the classes of this type (e.g. the types of union fields + * and optional record/set fields). */ + void generate_code_embedded_after(output_struct *target); + void generate_code_typedescriptor(output_struct *target); + void generate_code_berdescriptor(output_struct *target); + void generate_code_rawdescriptor(output_struct *target); + void generate_code_textdescriptor(output_struct *target); + void generate_code_jsondescriptor(output_struct *target); + void generate_code_xerdescriptor(output_struct *target); + void generate_code_alias(output_struct *target); + void generate_code_Enum(output_struct *target); + void generate_code_Choice(output_struct *target); + Opentype_t *generate_code_ot(stringpool& pool); + void free_code_ot(Opentype_t* p_ot); + void generate_code_Se(output_struct *target); + void generate_code_SeOf(output_struct *target); + void generate_code_Array(output_struct *target); + void generate_code_Fat(output_struct *target); + void generate_code_Signature(output_struct *target); + /** Returns whether the type needs an explicit C++ typedef alias and/or + * an alias to a type descriptor of another type. It returns true for those + * types that are defined in module-level type definitions hence are + * directly accessible by the users of C++ API (in test ports, external + * functions). */ + bool needs_alias(); + /** Returns whether this is a pure referenced type that has no tags or + * encoding attributes. */ + bool is_pure_refd(); + void generate_code_done(output_struct *target); + + /** Helper function used in generate_code_ispresentbound() for the + ispresent() function in case of template parameter. Returns true + if the referenced field which is embedded into a "?" is always present, + otherwise returns false. **/ + bool ispresent_anyvalue_embedded_field(Type* t, + Ttcn::FieldOrArrayRefs *subrefs, size_t begin_index); + public: + /** Generates type specific call for the reference used in isbound call + * into argument \a expr. Argument \a subrefs holds the reference path + * that needs to be checked. Argument \a module is the actual module of + * the reference and is used to gain access to temporal identifiers. + * Argument \a global_id is the name of the bool variable where the result + * of the isbound check is calculated. Argument \a external_id is the name + * of the assignment where the call chain starts. + * Argument \a is_template tells if the assignment is a template or not. + * Argument \a isbound tells if the function is isbound or ispresent. + */ + void generate_code_ispresentbound(expression_struct *expr, + Ttcn::FieldOrArrayRefs *subrefs, Common::Module* module, + const string& global_id, const string& external_id, + const bool is_template, const bool isbound); + + /** Extension attribute for optimized code generation of structured types: + * with { extension "optimize:xxx" } + * xxx tells what to optimize for (e.g.: memory, performance, etc.) + * returns empty if none given + */ + string get_optimize_attribute(); + /** Extension attribute for hand written TTCN-3 types: + * with { extension "sourcefile:xxx" } + * filename is xxx, source files: xxx.hh and xxx.cc + * returns empty if none given + */ + string get_sourcefile_attribute(); + bool has_done_attribute(); + /** Generates the declaration and definition of a C++ value or template + * object governed by \a this into \a cdef. Argument \a p_scope points to + * the scope of the object to be generated. Argument \a name contains the + * identifier of the target C++ object. If argument \a prefix is not NULL + * the real object will be generated as static, its name will be + * prefixed with \a prefix and a const (read-only) reference will be + * exported with name \a name. This function shall be used when there is no + * Value or Template object in the AST (e.g. in case of variables). */ + void generate_code_object(const_def *cdef, Scope* p_scope, + const string& name, const char *prefix, bool is_template); + /** Generates the declaration and definition of a C++ value or template + * object governed by \a this into \a cdef based on the attributes of + * \a p_setting. */ + void generate_code_object(const_def *cdef, GovernedSimple *p_setting); + private: + virtual string create_stringRepr(); + public: + /** If this type is added to an opentype, then this name is used + * as the name of the alternative. */ + Identifier get_otaltname(bool& is_strange); + /** Returns the name of the C++ value class that represents \a this at + * runtime. The class is either pre-defined (written manually in the Base + * Library) or generated by the compiler. The reference is valid in the + * module that \a p_scope belongs to. */ + string get_genname_value(Scope *p_scope); + /** Returns the name of the C++ class that represents \a this template at + * runtime. The class is either pre-defined (written manually in the Base + * Library) or generated by the compiler. The reference is valid in the + * module that \a p_scope belongs to. */ + string get_genname_template(Scope *p_scope); + /** Returns a C++ identifier that can be used to distinguish the type in + * the union that carries signature exceptions. */ + string get_genname_altname(); + /** User visible (not code generator) type name */ + string get_typename(); + /** User visible type name for built-in types */ + static const char * get_typename_builtin(typetype_t tt); + string get_genname_typedescriptor(Scope *p_scope); + private: + /** Returns the name prefix of type descriptors, etc. that belong to the + * equivalent C++ class referenced from the module of scope \a p_scope. + * It differs from \a get_genname() only in case of special ASN.1 types + * like RELATIVE-OID or various string types. */ + string get_genname_typename(Scope *p_scope); + /** Return the name of the BER descriptor structure. + * It is either the name of the type itself; + * one of "ENUMERATED", "CHOICE", "SEQUENCE", "SET"; + * or one of the core classes e.g. ASN_ROID, UTF8String, etc. + * The _ber_ suffix needs to be appended by the caller. */ + string get_genname_berdescriptor(); + string get_genname_rawdescriptor(); + string get_genname_textdescriptor(); + string get_genname_xerdescriptor(); + string get_genname_jsondescriptor(); + /** Return the ASN base type to be written into the type descriptor */ + const char* get_genname_typedescr_asnbasetype(); + /** parse subtype information and add parent's subtype information to + create the effective/aggregate subtype of this type */ + void check_subtype_constraints(); + public: + /** Return the type of subtype that is associated with this type */ + SubtypeConstraint::subtype_t get_subtype_type(); + virtual void dump(unsigned level) const; + void set_parsed_restrictions(vector *stp); + /** Returns true if the values of this type can be used only in 'self'. + * Some types (default, function reference with 'runs on self') are + * invalid outside of the component they were created in, they should not + * be sent/received in ports or used in compref.start(). All structured + * types that may contain such internal types are also internal. */ + bool is_component_internal(); + /** Prints error messages for types that cannot leave the component. + * Should be called only if is_component_internal() returned true. + * \a type_chain is used to escape infinite recursion by maintaining a + * chain of structured types that call this function recursively, + * \a p_what tells what is the reason of the error. */ + void chk_component_internal(map& type_chain, + const char* p_what); + /** Prints error messages for type that cannot be a type of given ones (parameter: array of typetype_t) + * \a type_chain is used to escape infinite recursion by maintaining a + * chain of structured types that call this function recursively, + * \returns the original type or a not allowed one */ + typetype_t search_for_not_allowed_type(map& type_chain, + map& not_allowed); + /** Set the owner and its type type */ + void set_ownertype(TypeOwner_t ot, Node *o) { ownertype = ot; owner = o; } + + bool is_untagged() const; + + /** Calculates the type's display name from the genname (replaces double + * underscore characters with single ones) */ + string get_dispname() const; + + /** Generates the JSON schema segment that would validate this type and + * inserts it into the main schema. + * @param json JSON tokenizer containing the main JSON schema + * @param embedded true if the type is embedded in another type's definition; + * false if it has its own definition + * @param as_value true if this type is a field of a union with the "as value" + * coding instruction */ + void generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_value); + + /** Generates the JSON schema segment that would validate a record of, set of + * or array type and inserts it into the main schema. */ + void generate_json_schema_array(JSON_Tokenizer& json); + + /** Generates the JSON schema segment that would validate a record or set type + * and inserts it into the main schema. */ + void generate_json_schema_record(JSON_Tokenizer& json); + + /** 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); + }; + + /** @} end of AST_Type group */ + +} // namespace Common + +#endif // _Common_Type_HH diff --git a/compiler2/TypeCompat.cc b/compiler2/TypeCompat.cc new file mode 100644 index 0000000..4e58d7a --- /dev/null +++ b/compiler2/TypeCompat.cc @@ -0,0 +1,881 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2000-2014 Ericsson Telecom AB +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +#include "TypeCompat.hh" + +#include "AST.hh" +#include "Type.hh" +#include "CompField.hh" +#include "ttcn3/ArrayDimensions.hh" +#include "ttcn3/TtcnTemplate.hh" +#include "main.hh" + +namespace Common { + +TypeCompatInfo::TypeCompatInfo(Module *p_my_module, Type *p_type1, + Type *p_type2, bool p_add_ref_str, + bool p_strict, bool p_is_temp) : + m_my_module(p_my_module), m_type1(p_type1), m_type2(p_type2), + m_strict(p_strict), m_is_temp(p_is_temp), m_needs_conversion(false), + m_erroneous(false), str1_elem(false), str2_elem(false) +{ + if (p_type1 && p_add_ref_str) m_ref_str1 = p_type1->get_typename(); + if (p_type2 && p_add_ref_str) m_ref_str2 = p_type2->get_typename(); +} + +void TypeCompatInfo::set_is_erroneous(Type *p_type1, Type *p_type2, + const string& p_error_str) +{ + m_erroneous = true; + m_type1 = p_type1; + m_type2 = p_type2; + m_error_str = p_error_str; +} + +string TypeCompatInfo::get_error_str_str() const +{ + // The resulting string should look like: "`f1.f2.f3...fn' [of type `tn'] + // and `g1.g2.g3...gm' [of type `tm']". In run-time a simple error will + // occure with a similarly simple error message. + string ret_val = "Type mismatch: `" + m_ref_str1; + if (m_ref_str1 != m_type1->get_typename()) + ret_val += ("' of type `" + m_type1->get_typename()); + ret_val += ("' and `" + m_ref_str2); + if (m_ref_str2 != m_type2->get_typename()) + ret_val += ("' of type `" + m_type2->get_typename()); + ret_val += "' are not compatible"; + if (m_error_str.size() > 0) ret_val += (": " + m_error_str); + return ret_val; +} + +void TypeCompatInfo::add_type_conversion(Type *p_from_type, Type *p_to_type) +{ + if (!m_my_module) FATAL_ERROR("TypeCompatInfo::add_type_conversion()"); + if (p_from_type == p_to_type) return; + TypeConv *conv = new TypeConv(p_from_type, p_to_type, m_is_temp); + m_my_module->add_type_conv(conv); +} + +void TypeCompatInfo::append_ref_str(int p_ref_no, const string& p_ref_str) +{ + string& ref_str = p_ref_no == 0 ? m_ref_str1 : m_ref_str2; + ref_str += p_ref_str; +} + +string TypeConv::get_conv_func(Type *p_from, Type *p_to, Module *p_mod) +{ + const char *from_name = p_from->get_genname_own().c_str(); + const char *to_name = p_to->get_genname_own().c_str(); + Module *from_mod = p_from->get_my_scope()->get_scope_mod(); + Module *to_mod = p_to->get_my_scope()->get_scope_mod(); + string ret_val = "conv_" + (from_mod != p_mod + ? (from_mod->get_modid().get_name() + "_") : string()) + from_name + "_" + + (to_mod != p_mod ? (to_mod->get_modid().get_name() + "_") : string()) + + to_name; + return ret_val; +} + +bool TypeConv::needs_conv_redir(TemplateInstance *p_ti, Reference *p_ref) +{ + if (!use_runtime_2) FATAL_ERROR("TypeConv::needs_conv_redir()"); + if (!p_ref) + return false; + Template *templ_body = p_ti->get_Template(); + Template::templatetype_t templ_body_tt = templ_body->get_templatetype(); + switch (templ_body_tt) { + case Template::SPECIFIC_VALUE: + if (templ_body->get_specific_value()->get_needs_conversion()) + return true; + break; + default: + // If the first parameter needs conversion, go ahead. It's most + // probably a reference. + if (templ_body->get_needs_conversion()) + return true; + break; + } + // Check if the value and the type specified for the template instance + // match. If not, we'll need a conversion. + if (p_ti->get_Type()) { + Type *ti_type = p_ti->get_Type()->get_type_refd_last(); + Type *val_type = p_ref->get_refd_assignment()->get_Type() + ->get_field_type(p_ref->get_subrefs(), Type::EXPECTED_DYNAMIC_VALUE) + ->get_type_refd_last(); + if (ti_type->is_structured_type() && val_type->is_structured_type() + && ti_type != val_type) + return true; + } + return false; +} + +void TypeConv::gen_conv_code_redir(expression_struct *p_expr, + TemplateInstance *p_ti, Reference *p_ref) +{ + if (!use_runtime_2) FATAL_ERROR("TypeConv::gen_conv_code_redir()"); + Template *templ_body = p_ti->get_Template(); + Template::templatetype_t templ_body_tt = templ_body->get_templatetype(); + expression_struct expr_tmp; + Code::init_expr(&expr_tmp); + const string& tmp_id1 = templ_body->get_temporary_id(); + const char *tmp_id_str1 = tmp_id1.c_str(); + const string& tmp_id2 = templ_body->get_temporary_id(); + const char *tmp_id_str2 = tmp_id2.c_str(); + const string& tmp_id3 = templ_body->get_temporary_id(); + const char *tmp_id_str3 = tmp_id3.c_str(); + Type *my_gov = p_ref->get_refd_assignment()->get_Type() + ->get_field_type(p_ref->get_subrefs(), Type::EXPECTED_DYNAMIC_VALUE) + ->get_type_refd_last(); + Type *orig_type = NULL; + switch (templ_body_tt) { + case Template::SPECIFIC_VALUE: { + Value *val = templ_body->get_specific_value(); + if (val->get_valuetype() == Value::V_REFD) + orig_type = val->get_reference()->get_refd_assignment()->get_Type() + ->get_field_type(val->get_reference()->get_subrefs(), + Type::EXPECTED_DYNAMIC_VALUE)->get_type_refd_last(); + break; } + case Template::TEMPLATE_REFD: { + Reference *ref = templ_body->get_reference(); + if (!ref) FATAL_ERROR("TypeConv::gen_conv_code_redir()"); + orig_type = ref->get_refd_assignment()->get_Type()->get_field_type(ref + ->get_subrefs(), Type::EXPECTED_TEMPLATE)->get_type_refd_last(); + break; } + default: + break; + } + bool needs_back_conv = orig_type != my_gov; + // Try the template instance's explicit type specification. This will be + // the winner if we already have the type. + if (p_ti->get_Type()) { + if (p_ti->get_Type()->get_type_refd_last() != my_gov) { + orig_type = p_ti->get_Type()->get_type_refd_last(); + needs_back_conv = false; + } + } + if (!orig_type || !my_gov) FATAL_ERROR("TypeConv::gen_conv_code_redir()"); + p_expr->preamble = mputprintf(p_expr->preamble, + "%s %s;\n" // For back-conversion. + "%s %s;\n" // To store the result of the operation, the "&()" part. + "%s %s;\n", + orig_type->get_genname_template(templ_body->get_my_scope()).c_str(), + tmp_id_str1, orig_type->get_genname_value(templ_body->get_my_scope()) + .c_str(), tmp_id_str2, my_gov->get_genname_template(templ_body + ->get_my_scope()).c_str(), tmp_id_str3); + expr_tmp.expr = mputprintf(expr_tmp.expr, "%s = ", + !needs_back_conv ? tmp_id_str1 : tmp_id_str3); + p_ti->generate_code(&expr_tmp); + p_expr->preamble = Code::merge_free_expr(p_expr->preamble, &expr_tmp); + if (needs_back_conv) { + TypeConv *back_conv = new TypeConv(my_gov, orig_type, true); + templ_body->get_my_scope()->get_scope_mod()->add_type_conv(back_conv); + p_expr->preamble = mputprintf(p_expr->preamble, + "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' and " + "`%s' are not compatible at run-time\");\n", + TypeConv::get_conv_func(my_gov, orig_type, templ_body->get_my_scope() + ->get_scope_mod()).c_str(), tmp_id_str1, tmp_id_str3, my_gov + ->get_typename().c_str(), orig_type->get_typename().c_str()); + } + // The back-converted template is the first argument. + p_expr->expr = mputprintf(p_expr->expr, "%s, &(%s)", + tmp_id_str1, tmp_id_str2); + Code::init_expr(&expr_tmp); + p_ref->generate_code(&expr_tmp); + // Hand-merge 1. + if (expr_tmp.preamble) + p_expr->postamble = mputstr(p_expr->postamble, expr_tmp.preamble); + // Finally, convert back to the original value. TODO: Simplify. Don't + // let the conversion die due to an unsuccessful receive operation. + p_expr->postamble = mputprintf(p_expr->postamble, + "if (%s.is_bound() && !%s(%s, %s)) TTCN_error(\"Values or templates " + "of types `%s' and `%s' are not compatible at run-time\");\n", + tmp_id_str2, TypeConv::get_conv_func(orig_type, my_gov, templ_body + ->get_my_scope()->get_scope_mod()).c_str(), expr_tmp.expr, tmp_id_str2, + orig_type->get_typename().c_str(), my_gov->get_typename().c_str()); + // Hand-merge 2. + if (expr_tmp.postamble) + p_expr->postamble = mputstr(p_expr->postamble, expr_tmp.postamble); + Code::free_expr(&expr_tmp); +} + +bool TypeConv::needs_conv_refd(GovernedSimple *p_val_or_temp) +{ + if (!use_runtime_2) FATAL_ERROR("TypeConv::needs_conv_refd()"); + Type *original_type = NULL; + Type *current_type = NULL; + switch (p_val_or_temp->get_st()) { + case Setting::S_TEMPLATE: { + Template *p_temp = static_cast