1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
26 * Szabo, Janos Zoltan – initial implementation
27 * Zalanyi, Balazs Andor
29 ******************************************************************************/
30 /* Main program for the merged compiler */
40 #if defined SOLARIS || defined SOLARIS8
41 # include <sys/utsname.h>
45 #include "../common/usage_stats.hh"
49 #include "../common/dbgnew.hh"
50 #include "../common/path.h"
51 #include "../common/version_internal.h"
52 #include "../common/userinfo.h"
53 #include "datatypes.h"
56 #include "asn1/asn1_preparser.h"
57 #include "asn1/asn1.hh"
58 #include "ttcn3/ttcn3_preparser.h"
59 #include "ttcn3/compiler.h"
62 #include "asn1/AST_asn1.hh"
63 #include "ttcn3/AST_ttcn3.hh"
65 #include "CodeGenHelper.hh"
66 #include "Stopwatch.hh"
68 #include "ttcn3/Ttcn2Json.hh"
70 #include "ttcn3/profiler.h"
73 #include "../common/license.h"
76 using namespace Common
;
78 const char *output_dir
= NULL
;
79 const char *tcov_file_name
= NULL
;
80 const char *profiler_file_name
= NULL
;
81 tcov_file_list
*tcov_files
= NULL
;
82 expstring_t effective_module_lines
= NULL
;
83 expstring_t effective_module_functions
= NULL
;
85 size_t nof_top_level_pdus
= 0;
86 const char **top_level_pdu
= NULL
;
88 boolean generate_skeleton
= FALSE
, force_overwrite
= FALSE
,
89 include_line_info
= FALSE
, include_location_info
= FALSE
,
90 duplicate_underscores
= FALSE
, parse_only
= FALSE
,
91 semantic_check_only
= FALSE
, output_only_linenum
= FALSE
,
92 default_as_optional
= FALSE
, enable_set_bound_out_param
= FALSE
,
93 use_runtime_2
= FALSE
, gcc_compat
= FALSE
, asn1_xer
= FALSE
,
94 check_subtype
= TRUE
, suppress_context
= FALSE
, display_up_to_date
= FALSE
,
95 implicit_json_encoding
= FALSE
, json_refs_for_all_types
= TRUE
,
96 force_gen_seof
= FALSE
, omit_in_value_list
= FALSE
,
97 warnings_for_bad_variants
= FALSE
, debugger_active
= FALSE
,
98 legacy_unbound_union_fields
= FALSE
;
100 // Default code splitting mode is set to 'no splitting'.
101 CodeGenHelper::split_type code_splitting_mode
= CodeGenHelper::SPLIT_NONE
;
103 #if defined SOLARIS || defined SOLARIS8
104 /** Automatic detection of Solaris version based on uname() system call.
105 * Distinguishing is needed because some socket functions use socklen_t
106 * (which is an alias for unsigned int) as length arguments on Solaris 8.
107 * On Solaris 2.6 the argument type is simply int and no socklen_t or other
109 * Note: It was discovered later that Solaris 7 (which is used rarely within
110 * Ericsson) already uses socklen_t thus the SOLARIS8 platform identifier is a
112 static const char *get_platform_string(void)
116 if (uname(&name
) < 0) {
117 WARNING("System call uname() failed: %s", strerror(errno
));
121 if (sscanf(name
.release
, "%d.%d", &major
, &minor
) == 2 && major
== 5) {
122 if (minor
<= 6) return "SOLARIS";
123 else return "SOLARIS8";
125 ERROR("Invalid OS release: %s", name
.release
);
130 #define get_platform_string() "LINUX"
131 #elif defined FREEBSD
132 #define get_platform_string() "FREEBSD"
134 #define get_platform_string() "WIN32"
135 #elif defined INTERIX
136 #define get_platform_string() "INTERIX"
138 #error Platform was not set.
142 const char *expected_platform
= get_platform_string();
145 Modules
*modules
= NULL
;
147 // Features can be disabled in the license or by commandline switches
148 static bool raw_disabled
= false, ber_disabled
= false, per_disabled
= false,
149 text_disabled
= false, xer_disabled
= false, json_disabled
= false;
150 static bool attribute_validation_disabled
= FALSE
;
152 static bool has_raw_feature
= false, has_ber_feature
= false,
153 has_per_feature
= false, has_text_feature
= false, has_xer_feature
= false;
158 if (raw_disabled
) return FALSE
;
160 if (!has_raw_feature
) {
161 WARNING("The license key does not allow the generation of "
162 "RAW encoder/decoder functions.");
172 if (ber_disabled
) return FALSE
;
174 if (!has_ber_feature
) {
175 WARNING("The license key does not allow the generation of "
176 "BER encoder/decoder functions.");
186 if (per_disabled
) return FALSE
;
188 if (!has_per_feature
) {
189 WARNING("The license key does not allow the generation of "
190 "PER encoder/decoder functions.");
198 boolean
enable_text()
200 if (text_disabled
) return FALSE
;
202 if (!has_text_feature
) {
203 WARNING("The license key does not allow the generation of "
204 "TEXT encoder/decoder functions.");
205 text_disabled
= true;
214 if (xer_disabled
) return FALSE
;
216 if (!has_xer_feature
) {
217 WARNING("The license key does not allow the generation of "
218 "XER encoder/decoder functions.");
226 boolean
enable_json()
228 return !json_disabled
;
231 boolean
disable_attribute_validation()
233 if (attribute_validation_disabled
) return TRUE
;
238 char *canonize_input_file(const char *path_name
)
240 switch (get_path_status(path_name
)) {
242 ERROR("Input file `%s' does not exist.", path_name
);
245 ERROR("Argument `%s' is a directory.", path_name
);
250 char *dir_name
= get_dir_from_path(path_name
);
251 char *abs_dir
= get_absolute_dir(dir_name
, NULL
, true);
253 char *file_name
= get_file_from_path(path_name
);
254 char *ret_val
= compose_path_name(abs_dir
, file_name
);
260 struct module_struct
{
261 const char *file_name
;
263 Module::moduletype_t module_type
;
264 bool need_codegen
; /**< Code is generated for a module if
265 - the module appears on the command line after the dash, or
266 - there is no dash (code is generated for all modules) */
269 static void add_module(size_t& n_modules
, module_struct
*& module_list
,
270 const char *file_name
, Module::moduletype_t module_type
)
272 char *absolute_path
= canonize_input_file(file_name
);
273 if (absolute_path
== NULL
) return;
274 for (size_t i
= 0; i
< n_modules
; i
++) {
275 const module_struct
*module
= module_list
+ i
;
276 if (module
->module_type
== module_type
&&
277 !strcmp(module
->absolute_path
, absolute_path
)) {
278 ERROR("Input file `%s' was given more than once.", file_name
);
283 module_list
= (module_struct
*)
284 Realloc(module_list
, (n_modules
+ 1) * sizeof(module_struct
));
285 module_struct
*module
= module_list
+ n_modules
;
286 module
->file_name
= file_name
;
287 module
->absolute_path
= absolute_path
;
288 module
->module_type
= module_type
;
289 module
->need_codegen
= false;
293 const char *get_tcov_file_name(const char *file_name
)
295 tcov_file_list
*tcov_file
= tcov_files
;
296 expstring_t file_name_pp
= mputprintf(NULL
, "%spp", file_name
);
297 while (tcov_file
!= NULL
) {
298 // This name can be a `.ttcnpp' too.
299 const char *real_file_name
= static_cast<const char *>(tcov_file
->file_name
);
300 if (!strcmp(file_name
, real_file_name
) ||
301 !strcmp(static_cast<const char *>(file_name_pp
), real_file_name
)) {
303 return real_file_name
;
305 tcov_file
= tcov_file
->next
;
311 boolean
in_tcov_files(const char *file_name
)
313 return get_tcov_file_name(file_name
) ? TRUE
: FALSE
;
316 static bool check_file_list(const char *file_name
, module_struct
*module_list
,
317 size_t n_modules
, tcov_file_list
*&file_list_head
)
319 FILE *fp
= fopen(file_name
, "r");
321 ERROR("File `%s' does not exist.", file_name
);
325 #define PATH_MAX 1024
328 bool unlisted_files
= false;
329 while (fgets(line
, sizeof(line
), fp
) != NULL
) {
330 // Remove trailing '\n'.
331 size_t line_len
= strlen(line
) - 1;
332 if (line
[line_len
] == '\n')
334 // Handle `.ttcnpp' files in input file.
336 char last
= line
[line_len
- 1];
337 char before_last
= line
[line_len
- 2];
338 if (last
== 'p' && before_last
== 'p')
344 for (; i
< n_modules
; ++i
) {
345 const module_struct
*module
= module_list
+ i
;
346 if (!strncmp(module
->file_name
, line
, line_len
)) {
347 tcov_file_list
*next_file
= (tcov_file_list
*)Malloc(sizeof(tcov_file_list
));
348 next_file
->next
= file_list_head
;
349 // We'll need the `.ttcnpp' file name.
350 next_file
->file_name
= mcopystr(line
);
351 file_list_head
= next_file
;
355 if (i
== n_modules
) {
356 ERROR("File `%s' was listed in `%s', but not in the command line.",
358 unlisted_files
= true;
362 if (unlisted_files
) {
363 while (file_list_head
!= NULL
) {
364 tcov_file_list
*next_file
= file_list_head
->next
;
365 Free(file_list_head
->file_name
);
366 Free(file_list_head
);
367 file_list_head
= next_file
;
369 file_list_head
= NULL
;
371 return !unlisted_files
;
374 static boolean
is_valid_asn1_filename(const char* file_name
)
376 // only check the actual file name, not the whole path
377 const char* file_name_start
= strrchr(file_name
, '/');
378 if (0 == strchr(file_name_start
!= NULL
? file_name_start
: file_name
, '-' )) {
387 "usage: %s [-abcdEfgijlLMnOpqrRsStuwxXyY] [-K file] [-z file] [-V verb_level]\n"
388 " [-o dir] [-U none|type] [-P modulename.top_level_pdu_name] [-Q number] ...\n"
389 " [-T] module.ttcn [-A] module.asn ...\n"
391 " or %s --ttcn2json [-jf] ... [-T] module.ttcn [-A] module.asn ... [- schema.json]\n"
394 " -a: force XER in ASN.1 files\n"
395 " -b: disable BER encoder/decoder functions\n"
396 " -B: allow selected union field to be unbound (legacy behavior)\n"
397 " -c: write out checksums in case of error\n"
398 " -d: treat default fields as omit\n"
399 " -E: display only warnings for unrecognized encoding variants\n"
400 " -f: force overwriting of output files\n"
401 " -g: emulate GCC error/warning message format\n"
402 " -i: use only line numbers in error/warning messages\n"
403 " -j: disable JSON encoder/decoder functions\n"
404 " -K file: enable selective code coverage\n"
405 " -l: include source line info in C++ code\n"
406 " -L: add source line info for logging\n"
407 " -M: allow 'omit' in template value lists (legacy behavior)\n"
408 " -n: activate debugger (generates extra code for debugging)\n"
409 " -o dir: output files will be placed into dir\n"
410 " -p: parse only (no semantic check or code generation)\n"
411 " -P pduname: define top-level pdu\n"
412 " -q: suppress all messages (quiet mode)\n"
413 " -Qn: quit after n errors\n"
414 " -r: disable RAW encoder/decoder functions\n"
415 " -R: use function test runtime (TITAN_RUNTIME_2)\n"
416 " -s: parse and semantic check only (no code generation)\n"
417 " -S: suppress context information\n"
418 " -t: generate Test Port skeleton\n"
419 " -u: duplicate underscores in file names\n"
420 " -U none|type: select code splitting mode for the generated C++ code\n"
421 " -V verb_level: set verbosity level bitmask (decimal)\n"
422 " -w: suppress warnings\n"
423 " -x: disable TEXT encoder/decoder functions\n"
424 " -X: disable XER encoder/decoder functions\n"
425 " -y: disable subtype checking\n"
426 " -Y: enforce legacy behaviour for \"out\" function parameters (see refguide)\n"
427 " -z file: enable profiling and code coverage for the TTCN-3 files in the argument\n"
428 " -T file: force interpretation of file as TTCN-3 module\n"
429 " -A file: force interpretation of file as ASN.1 module\n"
430 " -v: show version\n"
431 " --ttcn2json: generate JSON schema from input modules\n"
432 "JSON schema generator options:\n"
433 " -j: only include types with JSON encoding\n"
434 " -f: only generate references to types with JSON encoding/decoding functions\n", argv0
, argv0
, argv0
);
437 #define SET_FLAG(x) if (x##flag) {\
438 ERROR("Flag -" #x " was specified more than once.");\
440 } else x##flag = true
443 extern int ttcn3_debug
;
444 extern int asn1_yydebug
;
445 extern int pattern_yydebug
;
446 extern int pattern_unidebug
;
447 extern int rawAST_debug
;
448 extern int coding_attrib_debug
;
450 int main(int argc
, char *argv
[])
454 asn1_yydebug
= !! getenv("DEBUG_ASN1");
455 ttcn3_debug
= !! getenv("DEBUG_TTCN");
456 pattern_unidebug
= pattern_yydebug
= !! getenv("DEBUG_PATTERN");
457 rawAST_debug
= !! getenv("DEBUG_RAW");
458 coding_attrib_debug
= !!getenv("DEBUG_ATRIB") || getenv("DEBUG_ATTRIB");
462 #if defined(__CYGWIN__) || defined(INTERIX)
465 debug_new_counter
.set_program_name(argv0
);
470 fputs("TTCN-3 and ASN.1 Compiler for the TTCN-3 Test Executor, version "
471 PRODUCT_NUMBER
"\n", stderr
);
477 Aflag
= false, Lflag
= false, Yflag
= false,
478 Pflag
= false, Tflag
= false, Vflag
= false, bflag
= false,
479 cflag
= false, fflag
= false, iflag
= false, lflag
= false,
480 oflag
= false, pflag
= false, qflag
= false, rflag
= false, sflag
= false,
481 tflag
= false, uflag
= false, vflag
= false, wflag
= false, xflag
= false,
482 dflag
= false, Xflag
= false, Rflag
= false, gflag
= false, aflag
= false,
483 s0flag
= false, Cflag
= false, yflag
= false, Uflag
= false, Qflag
= false,
484 Sflag
= false, Kflag
= false, jflag
= false, zflag
= false, Fflag
= false,
485 Mflag
= false, Eflag
= false, nflag
= false, Bflag
= false, errflag
= false,
486 print_usage
= false, ttcn2json
= false;
490 bool asn1_modules_present
= false;
492 bool ttcn3_modules_present
= false;
494 size_t n_modules
= 0;
495 module_struct
*module_list
= NULL
;
496 char* json_schema_name
= NULL
;
498 if (0 == strcmp(argv
[1], "--ttcn2json")) {
500 display_up_to_date
= TRUE
;
501 implicit_json_encoding
= TRUE
;
502 for (int i
= 2; i
< argc
; ++i
) {
503 // A dash (-) is used to separate the schema file name from the input files
504 if (0 == strcmp(argv
[i
], "-")) {
506 json_schema_name
= mcopystr(argv
[i
+ 1]);
508 ERROR("Expected JSON schema name (1 argument) after option `--ttcn2json' and `-'");
513 else if (0 == strcmp(argv
[i
], "-A")) {
516 ERROR("Option `-A' must be followed by an ASN.1 file name");
520 add_module(n_modules
, module_list
, argv
[i
], Module::MOD_ASN
);
521 asn1_modules_present
= true;
523 else if (0 == strcmp(argv
[i
], "-T")) {
526 ERROR("Option `-T' must be followed by a TTCN-3 file name");
530 add_module(n_modules
, module_list
, argv
[i
], Module::MOD_TTCN
);
532 else if (0 == strcmp(argv
[i
], "-j")) {
533 implicit_json_encoding
= FALSE
;
535 else if (0 == strcmp(argv
[i
], "-f")) {
536 json_refs_for_all_types
= FALSE
;
538 else if (0 == strcmp(argv
[i
], "-fj") || 0 == strcmp(argv
[i
], "-jf")) {
539 implicit_json_encoding
= FALSE
;
540 json_refs_for_all_types
= FALSE
;
542 else if (argv
[i
][0] == '-') {
543 ERROR("Invalid option `%s' after option `--ttcn2json'", argv
[i
]);
549 add_module(n_modules
, module_list
, argv
[i
], Module::MOD_UNKNOWN
);
553 if (!errflag
&& 0 == n_modules
) {
554 ERROR("No TTCN-3 or ASN.1 modules specified after option `--ttcn2json'");
559 if (!errflag
&& NULL
== json_schema_name
) {
560 // Create the schema name using the first TTCN-3 or ASN.1 file's name
561 const module_struct
& first
= module_list
[0];
562 if (0 == strncmp(first
.file_name
+ strlen(first
.file_name
) - 4, ".asn", 4)) {
563 json_schema_name
= mcopystrn(first
.file_name
, strlen(first
.file_name
) - 4);
564 json_schema_name
= mputstrn(json_schema_name
, ".json", 5);
566 else if (0 == strncmp(first
.file_name
+ strlen(first
.file_name
) - 5, ".ttcn", 5)) {
567 json_schema_name
= mcopystrn(first
.file_name
, strlen(first
.file_name
) - 5);
568 json_schema_name
= mputstrn(json_schema_name
, ".json", 5);
571 json_schema_name
= mprintf("%s.json", first
.file_name
);
578 int c
= getopt(argc
, argv
, "aA:bBcC:dEfFgijK:lLMno:pP:qQ:rRsStT:uU:vV:wxXyYz:0-");
587 add_module(n_modules
, module_list
, optarg
, Module::MOD_ASN
);
588 asn1_modules_present
= true;
592 expected_platform
= optarg
;
596 include_location_info
= TRUE
;
600 nof_top_level_pdus
++;
601 top_level_pdu
=(const char**)
602 Realloc(top_level_pdu
, nof_top_level_pdus
*sizeof(*top_level_pdu
));
603 top_level_pdu
[nof_top_level_pdus
-1] = optarg
;
607 add_module(n_modules
, module_list
, optarg
, Module::MOD_TTCN
);
609 ttcn3_modules_present
= true;
614 /* set verbosity level bitmask */
615 if (isdigit(optarg
[0])) {
616 verb_level
= atoi(optarg
);
617 // don't bother with overflow
620 ERROR("Option `-V' requires a decimal number as argument instead of "
634 default_as_optional
= TRUE
;
638 force_overwrite
= TRUE
;
646 output_only_linenum
= TRUE
;
650 tcov_file_name
= optarg
;
654 include_line_info
= TRUE
;
662 enable_set_bound_out_param
= TRUE
;
670 /* quiet; suppress all message */
679 use_runtime_2
= TRUE
;
683 semantic_check_only
= TRUE
;
687 suppress_context
= TRUE
;
691 attribute_validation_disabled
= TRUE
;
695 generate_skeleton
= TRUE
;
699 duplicate_underscores
= TRUE
;
703 if (!cgh
.set_split_mode(optarg
)) {
704 ERROR("Wrong code splitting option: '%s'. Valid values are: 'none', "
714 /* suppress warnings and "not supported" messages */
715 verb_level
&= ~(1|2);
719 text_disabled
= TRUE
;
727 json_disabled
= TRUE
;
731 check_subtype
= FALSE
;
735 profiler_file_name
= optarg
;
739 force_gen_seof
= TRUE
;
743 omit_in_value_list
= TRUE
;
747 warnings_for_bad_variants
= TRUE
;
751 debugger_active
= TRUE
;
755 legacy_unbound_union_fields
= TRUE
;
761 printf("Q: %s\n", optarg
);
764 max_errs
= strtol(optarg
, (char**)NULL
, 10);
766 || (long)(int)max_errs
!= max_errs
) { // does not fit into int
767 ERROR("Invalid value %s: %s", optarg
, strerror(errno
));
770 else if (max_errs
< 0) {
771 ERROR("Negative value %s not allowed", optarg
);
775 if (max_errs
== 0) max_errs
= 1;
778 Error_Context::set_max_errors(max_errs
);
782 if (!strcmp(argv
[optind
], "--ttcn2json")) {
783 ERROR("Option `--ttcn2json' is only allowed as the first option");
785 ERROR("Invalid option: `%s'", argv
[optind
]);
796 /* Checking incompatible options */
798 if (Aflag
|| Lflag
|| Pflag
|| Tflag
|| Vflag
|| Yflag
||
799 bflag
|| fflag
|| iflag
|| lflag
|| oflag
|| pflag
|| qflag
||
800 rflag
|| sflag
|| tflag
|| uflag
|| wflag
|| xflag
|| Xflag
|| Rflag
||
801 Uflag
|| yflag
|| Kflag
|| jflag
|| zflag
|| Fflag
|| Mflag
|| Eflag
||
809 ERROR("Options `-p' and `-s' are incompatible with each other.");
810 // totally confusing: exit immediately
814 if (Kflag
&& !Lflag
) {
815 ERROR("Source line information `-L' is necessary for code coverage `-K'.");
818 if (zflag
&& !Lflag
) {
819 ERROR("Source line information `-L' is necessary for profiling `-z'.");
822 if (nflag
&& !Lflag
) {
823 ERROR("Source line information `-L' is necessary for debugging `-n'.");
826 if (iflag
&& gflag
) {
827 WARNING("Option `-g' overrides `-i'.");
828 iflag
= false; // -g gives more information
830 if (oflag
&& get_path_status(output_dir
) != PS_DIRECTORY
) {
831 ERROR("The argument of -o switch (`%s') must be a directory.",
835 if (optind
== argc
&& n_modules
== 0) {
836 ERROR("No input TTCN-3 or ASN.1 module was given.");
843 if (print_usage
) usage();
844 Free(json_schema_name
);
849 fputs("TTCN-3 and ASN.1 Compiler for the TTCN-3 Test Executor\n"
850 "Product number: " PRODUCT_NUMBER
"\n"
851 "Build date: " __DATE__
" " __TIME__
"\n"
852 "Compiled with: " C_COMPILER_VERSION
"\n\n"
853 COPYRIGHT_STRING
"\n\n", stderr
);
855 print_license_info();
856 fputs("\nUsing ", stderr
);
857 fputs(openssl_version_str(), stderr
);
858 fputs("\n\n", stderr
);
867 int license_valid
= verify_license(&lstr
);
869 if (!license_valid
) {
876 /* the position of '-' switch in argv list */
877 int dash_position
= -1;
879 /* Add the remaining files until switch '-' to the module_list */
880 for(int i
= optind
; i
< argc
; i
++) {
881 if (strcmp(argv
[i
], "-"))
882 add_module(n_modules
, module_list
, argv
[i
], Module::MOD_UNKNOWN
);
889 if (dash_position
== -1) {
890 /** if '-' was not present in the command line code should be generated for
892 for (size_t i
= 0; i
< n_modules
; i
++) module_list
[i
].need_codegen
= true;
894 for (int i
= dash_position
+ 1; i
< argc
; i
++) {
895 char *absolute_path
= canonize_input_file(argv
[i
]);
896 if (absolute_path
== NULL
) continue;
898 for (size_t j
= 0; j
< n_modules
; j
++) {
899 module_struct
*module
= module_list
+ j
;
900 if (!strcmp(module
->absolute_path
, absolute_path
)) {
901 module
->need_codegen
= true;
903 // do not stop: the same file may be present on the list twice
904 // (as both ASN.1 and TTCN-3 module)
909 ERROR("File `%s' was not given before the `-' switch for selective "
910 "code generation.", argv
[i
]);
911 // go further (i.e. check all files after the `-')
918 STOPWATCH("Determining module types");
919 // check the readability of all files and
920 // determine the type of unknown modules
921 for (size_t i
= 0; i
< n_modules
; i
++) {
922 module_struct
*module
= module_list
+ i
;
923 FILE *fp
= fopen(module
->file_name
, "r");
925 if (module
->module_type
== Module::MOD_UNKNOWN
) {
926 // try the ASN.1 and TTCN-3 preparsers
927 boolean asn1_module
= is_asn1_module(module
->file_name
, fp
, NULL
);
928 boolean ttcn3_module
= is_ttcn3_module(module
->file_name
, fp
, NULL
);
930 if (!is_valid_asn1_filename (module
->file_name
)) {
931 ERROR("The file name (without suffix) shall be identical to the module name.\n"
932 "If the name of the ASN.1 module contains a hyphen, the corresponding "
933 "file name shall contain an underscore character instead.");
936 ERROR("File `%s' looks so strange that it can contain both an "
937 "ASN.1 and a TTCN-3 module. Use the command-line switch `-A' or "
938 "`-T' to set its type.", module
->file_name
);
941 for (size_t j
= 0; j
< n_modules
; j
++) {
942 module_struct
*module2
= module_list
+ j
;
943 if (module2
->module_type
== Module::MOD_ASN
&&
944 !strcmp(module
->absolute_path
, module2
->absolute_path
)) {
950 ERROR("Input file `%s' was given more than once.",
953 module
->module_type
= Module::MOD_ASN
;
954 asn1_modules_present
= true;
957 } else if (ttcn3_module
) {
959 for (size_t j
= 0; j
< n_modules
; j
++) {
960 module_struct
*module2
= module_list
+ j
;
961 if (module2
->module_type
== Module::MOD_TTCN
&&
962 !strcmp(module
->absolute_path
, module2
->absolute_path
)) {
968 ERROR("Input file `%s' was given more than once.",
971 module
->module_type
= Module::MOD_TTCN
;
973 ttcn3_modules_present
= true;
977 ERROR("Cannot recognize file `%s' as an ASN.1 or TTCN-3 module. "
978 "Use the command-line switch `-A' or `-T' to set its type.",
984 ERROR("Cannot open input file `%s' for reading: %s", module
->file_name
,
987 // do not invoke the real parsers on that file
988 module
->module_type
= Module::MOD_UNKNOWN
;
994 if (!semantic_check_only
) {
995 NOTIFY("On native win32 builds code generation is disabled.");
996 semantic_check_only
= TRUE
;
1000 /* Checking of required license features */
1001 if (asn1_modules_present
&& !check_feature(&lstr
, FEATURE_ASN1
)) {
1002 ERROR("The license key does not allow the parsing of "
1004 return EXIT_FAILURE
;
1006 if (ttcn3_modules_present
&& !check_feature(&lstr
, FEATURE_TTCN3
)) {
1007 ERROR("The license key does not allow the parsing of "
1009 return EXIT_FAILURE
;
1011 if (!parse_only
&& !semantic_check_only
&&
1012 !check_feature(&lstr
, FEATURE_CODEGEN
)) {
1013 WARNING("The license key does not allow the generation of "
1015 semantic_check_only
= TRUE
;
1017 if (generate_skeleton
&& !check_feature(&lstr
, FEATURE_TPGEN
)) {
1018 WARNING("The license key does not allow the generation of "
1019 "Test Port skeletons.");
1020 generate_skeleton
= FALSE
;
1022 has_raw_feature
= check_feature(&lstr
, FEATURE_RAW
);
1023 has_ber_feature
= check_feature(&lstr
, FEATURE_BER
);
1024 has_per_feature
= check_feature(&lstr
, FEATURE_PER
);
1025 has_text_feature
= check_feature(&lstr
, FEATURE_TEXT
);
1026 has_xer_feature
= check_feature(&lstr
, FEATURE_XER
);
1027 free_license(&lstr
);
1029 if (Kflag
&& !check_file_list(tcov_file_name
, module_list
, n_modules
, tcov_files
)) {
1030 ERROR("Error while processing `%s' provided for code coverage data "
1031 "generation.", tcov_file_name
);
1032 return EXIT_FAILURE
;
1035 tcov_file_list
*file_list_head
= NULL
;
1036 if(!check_file_list(profiler_file_name
, module_list
, n_modules
, file_list_head
)) {
1037 ERROR("Error while processing `%s' provided for profiling and code coverage.",
1038 profiler_file_name
);
1039 return EXIT_FAILURE
;
1041 init_profiler_data(file_list_head
);
1044 STOPWATCH("Parsing modules");
1047 if (asn1_modules_present
) asn1_init();
1048 modules
= new Common::Modules();
1050 for (size_t i
= 0; i
< n_modules
; i
++) {
1051 const module_struct
*module
= module_list
+ i
;
1052 switch (module
->module_type
) {
1053 case Module::MOD_ASN
:
1054 asn1_parse_file(module
->file_name
, module
->need_codegen
);
1056 case Module::MOD_TTCN
:
1057 ttcn3_parse_file(module
->file_name
, module
->need_codegen
);
1059 default: // MOD_UNKNOWN ?
1064 for (size_t i
= 0; i
< n_modules
; i
++) Free(module_list
[i
].absolute_path
);
1068 if (!parse_only
&& 0 == Error_Context::get_error_count()) {
1069 NOTIFY("Checking modules...");
1071 STOPWATCH("Semantic check");
1076 if (verb_level
> 7) modules
->dump();
1078 int ret_val
= EXIT_SUCCESS
;
1079 unsigned int error_count
= Error_Context::get_error_count();
1080 if (error_count
> 0) ret_val
= EXIT_FAILURE
;
1082 if (parse_only
|| semantic_check_only
) {
1083 // print detailed statistics
1084 Error_Context::print_error_statistics();
1086 if (error_count
== 0) {
1089 // Ignore SIGPIPE signals
1090 struct sigaction sig_act
;
1091 if (sigaction(SIGPIPE
, NULL
, &sig_act
))
1092 ERROR("System call sigaction() failed when getting signal "
1093 "handling information for %s.", "SIGINT");
1094 sig_act
.sa_handler
= SIG_IGN
;
1095 sig_act
.sa_flags
= 0;
1096 if (sigaction(SIGPIPE
, &sig_act
, NULL
))
1097 ERROR("System call sigaction() failed when disabling signal "
1101 std::stringstream stream
;
1102 stream
<< "compiler";
1103 std::set
<ModuleVersion
> versions
= modules
->getVersionsWithProductNumber();
1104 if (!versions
.empty()) {
1105 stream
<< "&products=";
1106 for (std::set
<ModuleVersion
>::iterator it
= versions
.begin(); it
!= versions
.end(); ++it
) {
1107 if (it
!= versions
.begin()) {
1110 stream
<< it
->toString();
1114 HttpSender
*sender
= new HttpSender
;
1115 UsageData::getInstance().sendDataThreaded(stream
.str(), sender
);
1118 NOTIFY("Generating JSON schema...");
1119 STOPWATCH("Generating JSON schema");
1120 // the Ttcn2Json constructor starts the process
1121 Ttcn::Ttcn2Json
t2j(modules
, json_schema_name
);
1123 NOTIFY("Generating code...");
1124 STOPWATCH("Generating code");
1125 modules
->generate_code(cgh
);
1126 report_nof_updated_files();
1129 NOTIFY("Error%s found in the input module%s. Code will not be generated.",
1130 error_count
> 1 ? "s" : "", n_modules
> 1 ? "s" : "");
1132 modules
->write_checksums();
1138 while (tcov_files
!= NULL
) {
1139 tcov_file_list
*next_file
= tcov_files
->next
;
1140 Free(tcov_files
->file_name
);
1142 tcov_files
= next_file
;
1147 Free(top_level_pdu
);
1148 if (asn1_modules_present
) asn1_free();
1150 Common::Node::chk_counter();
1151 Location::delete_source_file_names();
1152 Free(json_schema_name
);
1154 free_profiler_data();
1157 // dbgnew.hh already does it: check_mem_leak(argv[0]);