function_test/Semantic_Analyser/xer/aa_optional_SE.ttcn removed
[deliverable/titan.core.git] / compiler2 / main.cc
CommitLineData
970ed795
EL
1///////////////////////////////////////////////////////////////////////////////
2// Copyright (c) 2000-2014 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
7///////////////////////////////////////////////////////////////////////////////
8/* Main program for the merged compiler */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <unistd.h>
14#include <ctype.h>
15#include <errno.h>
16#include <vector>
17#include <sstream>
18#if defined SOLARIS || defined SOLARIS8
19# include <sys/utsname.h>
20#endif
21
22#ifdef USAGE_STATS
23#include "../common/usage_stats.hh"
24#include <signal.h>
25#endif
26
27#include "../common/dbgnew.hh"
28#include "../common/path.h"
29#include "../common/version_internal.h"
30#include "../common/userinfo.h"
31#include "datatypes.h"
32#include "main.hh"
33
34#include "asn1/asn1_preparser.h"
35#include "asn1/asn1.hh"
36#include "ttcn3/ttcn3_preparser.h"
37#include "ttcn3/compiler.h"
38
39#include "AST.hh"
40#include "asn1/AST_asn1.hh"
41#include "ttcn3/AST_ttcn3.hh"
42
43#include "CodeGenHelper.hh"
44#include "Stopwatch.hh"
45
46#include "ttcn3/Ttcn2Json.hh"
47
48#ifdef LICENSE
49#include "../common/license.h"
50#endif
51
52using namespace Common;
53
54const char *output_dir = NULL;
55const char *tcov_file_name = NULL;
56tcov_file_list *tcov_files = NULL;
57expstring_t effective_module_lines = NULL;
58expstring_t effective_module_functions = NULL;
59
60size_t nof_top_level_pdus = 0;
61const char **top_level_pdu = NULL;
62
63boolean generate_skeleton = FALSE, force_overwrite = FALSE,
64 include_line_info = FALSE, include_location_info = FALSE,
65 duplicate_underscores = FALSE, parse_only = FALSE,
66 semantic_check_only = FALSE, output_only_linenum = FALSE,
67 default_as_optional = FALSE, enable_set_bound_out_param = FALSE,
68 use_runtime_2 = FALSE, gcc_compat = FALSE, asn1_xer = FALSE,
af710487 69 check_subtype = TRUE, suppress_context = FALSE, display_up_to_date = FALSE,
70 implicit_json_encoding = FALSE, json_refs_for_all_types = TRUE,
71 profiler_enabled = FALSE;
970ed795
EL
72
73// Default code splitting mode is set to 'no splitting'.
74CodeGenHelper::split_type code_splitting_mode = CodeGenHelper::SPLIT_NONE;
75
76#if defined SOLARIS || defined SOLARIS8
77/** Automatic detection of Solaris version based on uname() system call.
78 * Distinguishing is needed because some socket functions use socklen_t
79 * (which is an alias for unsigned int) as length arguments on Solaris 8.
80 * On Solaris 2.6 the argument type is simply int and no socklen_t or other
81 * alias exists.
82 * Note: It was discovered later that Solaris 7 (which is used rarely within
83 * Ericsson) already uses socklen_t thus the SOLARIS8 platform identifier is a
84 * bit misleading. */
85static const char *get_platform_string(void)
86{
87 struct utsname name;
88 int major, minor;
89 if (uname(&name) < 0) {
90 WARNING("System call uname() failed: %s", strerror(errno));
91 errno = 0;
92 return "SOLARIS";
93 }
94 if (sscanf(name.release, "%d.%d", &major, &minor) == 2 && major == 5) {
95 if (minor <= 6) return "SOLARIS";
96 else return "SOLARIS8";
97 } else {
98 ERROR("Invalid OS release: %s", name.release);
99 return "SOLARIS";
100 }
101}
102#elif defined LINUX
103#define get_platform_string() "LINUX"
104#elif defined FREEBSD
105#define get_platform_string() "FREEBSD"
106#elif defined WIN32
107#define get_platform_string() "WIN32"
108#elif defined INTERIX
109#define get_platform_string() "INTERIX"
110#else
111#error Platform was not set.
112#endif
113
114
115const char *expected_platform = get_platform_string();
116
117/// "The" AST.
118Modules *modules = NULL;
119
120// Features can be disabled in the license or by commandline switches
121static bool raw_disabled = false, ber_disabled = false, per_disabled = false,
122 text_disabled = false, xer_disabled = false, json_disabled = false;
123static bool attribute_validation_disabled = FALSE;
124#ifdef LICENSE
125static bool has_raw_feature = false, has_ber_feature = false,
126 has_per_feature = false, has_text_feature = false, has_xer_feature = false;
127#endif
128
129boolean enable_raw()
130{
131 if (raw_disabled) return FALSE;
132#ifdef LICENSE
133 if (!has_raw_feature) {
134 WARNING("The license key does not allow the generation of "
135 "RAW encoder/decoder functions.");
136 raw_disabled = true;
137 return FALSE;
138 }
139#endif
140 return TRUE;
141}
142
143boolean enable_ber()
144{
145 if (ber_disabled) return FALSE;
146#ifdef LICENSE
147 if (!has_ber_feature) {
148 WARNING("The license key does not allow the generation of "
149 "BER encoder/decoder functions.");
150 ber_disabled = true;
151 return FALSE;
152 }
153#endif
154 return TRUE;
155}
156
157boolean enable_per()
158{
159 if (per_disabled) return FALSE;
160#ifdef LICENSE
161 if (!has_per_feature) {
162 WARNING("The license key does not allow the generation of "
163 "PER encoder/decoder functions.");
164 per_disabled = true;
165 return FALSE;
166 }
167#endif
168 return TRUE;
169}
170
171boolean enable_text()
172{
173 if (text_disabled) return FALSE;
174#ifdef LICENSE
175 if (!has_text_feature) {
176 WARNING("The license key does not allow the generation of "
177 "TEXT encoder/decoder functions.");
178 text_disabled = true;
179 return FALSE;
180 }
181#endif
182 return TRUE;
183}
184
185boolean enable_xer()
186{
187 if (xer_disabled) return FALSE;
188#ifdef LICENSE
189 if (!has_xer_feature) {
190 WARNING("The license key does not allow the generation of "
191 "XER encoder/decoder functions.");
192 xer_disabled = true;
193 return FALSE;
194 }
195#endif
196 return TRUE;
197}
198
199boolean enable_json()
200{
201 return !json_disabled;
202}
203
204boolean disable_attribute_validation()
205{
206 if (attribute_validation_disabled) return TRUE;
207
208 return FALSE;
209}
210
211char *canonize_input_file(const char *path_name)
212{
213 switch (get_path_status(path_name)) {
214 case PS_NONEXISTENT:
215 ERROR("Input file `%s' does not exist.", path_name);
216 return NULL;
217 case PS_DIRECTORY:
218 ERROR("Argument `%s' is a directory.", path_name);
219 return NULL;
220 default:
221 break;
222 }
223 char *dir_name = get_dir_from_path(path_name);
224 char *abs_dir = get_absolute_dir(dir_name, NULL);
225 Free(dir_name);
226 char *file_name = get_file_from_path(path_name);
227 char *ret_val = compose_path_name(abs_dir, file_name);
228 Free(abs_dir);
229 Free(file_name);
230 return ret_val;
231}
232
233struct module_struct {
234 const char *file_name;
235 char *absolute_path;
236 Module::moduletype_t module_type;
237 bool need_codegen; /**< Code is generated for a module if
238 - the module appears on the command line after the dash, or
239 - there is no dash (code is generated for all modules) */
240};
241
242static void add_module(size_t& n_modules, module_struct*& module_list,
243 const char *file_name, Module::moduletype_t module_type)
244{
245 char *absolute_path = canonize_input_file(file_name);
246 if (absolute_path == NULL) return;
247 for (size_t i = 0; i < n_modules; i++) {
248 const module_struct *module = module_list + i;
249 if (module->module_type == module_type &&
250 !strcmp(module->absolute_path, absolute_path)) {
251 ERROR("Input file `%s' was given more than once.", file_name);
252 Free(absolute_path);
253 return;
254 }
255 }
256 module_list = (module_struct*)
257 Realloc(module_list, (n_modules + 1) * sizeof(module_struct));
258 module_struct *module = module_list + n_modules;
259 module->file_name = file_name;
260 module->absolute_path = absolute_path;
261 module->module_type = module_type;
262 module->need_codegen = false;
263 n_modules++;
264}
265
266const char *get_tcov_file_name(const char *file_name)
267{
268 tcov_file_list *tcov_file = tcov_files;
269 expstring_t file_name_pp = mputprintf(NULL, "%spp", file_name);
270 while (tcov_file != NULL) {
271 // This name can be a `.ttcnpp' too.
272 const char *real_file_name = static_cast<const char *>(tcov_file->file_name);
273 if (!strcmp(file_name, real_file_name) ||
274 !strcmp(static_cast<const char *>(file_name_pp), real_file_name)) {
275 Free(file_name_pp);
276 return real_file_name;
277 }
278 tcov_file = tcov_file->next;
279 }
280 Free(file_name_pp);
281 return NULL;
282}
283
284boolean in_tcov_files(const char *file_name)
285{
286 return get_tcov_file_name(file_name) ? TRUE : FALSE;
287}
288
289static bool check_file_list(const char *file_name, module_struct *module_list, size_t n_modules)
290{
291 FILE *fp = fopen(file_name, "r");
292 if (fp == NULL) {
293 ERROR("File `%s' does not exist.", file_name);
294 return false;
295 }
296#ifndef PATH_MAX
297#define PATH_MAX 1024
298#endif
299 char line[PATH_MAX];
300 bool unlisted_files = false;
301 while (fgets(line, sizeof(line), fp) != NULL) {
302 // Remove trailing '\n'.
303 size_t line_len = strlen(line) - 1;
304 if (line[line_len] == '\n')
305 line[line_len] = 0;
306 // Handle `.ttcnpp' files in input file.
307 if (line_len > 1) {
308 char last = line[line_len - 1];
309 char before_last = line[line_len - 2];
310 if (last == 'p' && before_last == 'p')
311 line_len -= 2;
312 }
313 if (line_len < 1)
314 continue;
315 size_t i = 0;
316 for (; i < n_modules; ++i) {
317 const module_struct *module = module_list + i;
318 if (!strncmp(module->file_name, line, line_len)) {
319 tcov_file_list *next_file = new tcov_file_list;
320 next_file->next = tcov_files;
321 // We'll need the `.ttcnpp' file name.
322 next_file->file_name = mcopystr(line);
323 tcov_files = next_file;
324 break;
325 }
326 }
327 if (i == n_modules) {
328 ERROR("File `%s' was listed in `%s', but not in the command line.",
329 line, file_name);
330 unlisted_files = true;
331 }
332 }
333 fclose(fp);
334 if (unlisted_files) {
335 while (tcov_files != NULL) {
336 tcov_file_list *next_file = tcov_files->next;
337 Free(tcov_files->file_name);
338 delete tcov_files;
339 tcov_files = next_file;
340 }
341 tcov_files = NULL;
342 }
343 return !unlisted_files;
344}
345
346static boolean is_valid_asn1_filename(const char* file_name)
347{
348 if (0 == strchr(file_name, '-' )) {
349 return TRUE;
350 }
351 return FALSE;
352}
353
354static void usage()
355{
356 fprintf(stderr, "\n"
357 "usage: %s [-abcdfgilLOpqrRsStuwxXjy] [-K file] [-V verb_level] [-o dir]\n"
358 " [-U none|type] [-P modulename.top_level_pdu_name] [-Q number] ...\n"
359 " [-T] module.ttcn [-A] module.asn ...\n"
360 " or %s -v\n"
af710487 361 " or %s --ttcn2json [-jf] ... [-T] module.ttcn [-A] module.asn ... [- schema.json]\n"
970ed795
EL
362 "\n"
363 "OPTIONS:\n"
364 " -a: force XER in ASN.1 files\n"
365 " -b: disable BER encoder/decoder functions\n"
366 " -c: write out checksums in case of error\n"
367 " -d: treat default fields as omit\n"
368 " -f: force overwriting of output files\n"
369 " -g: emulate GCC error/warning message format\n"
370 " -i: use only line numbers in error/warning messages\n"
af710487 371 " -j: disable JSON encoder/decoder functions\n"
970ed795
EL
372 " -l: include source line info in C++ code\n"
373 " -L: add source line info for logging\n"
374 " -K file: enable selective code coverage\n"
af710487 375 " -o dir: output files will be placed into dir\n"
970ed795 376 " -p: parse only (no semantic check or code generation)\n"
af710487 377 " -P pduname: define top-level pdu\n"
970ed795
EL
378 " -q: suppress all messages (quiet mode)\n"
379 " -Qn: quit after n errors\n"
380 " -r: disable RAW encoder/decoder functions\n"
381 " -R: use function test runtime (TITAN_RUNTIME_2)\n"
382 " -s: parse and semantic check only (no code generation)\n"
383 " -S: suppress context information\n"
384 " -t: generate Test Port skeleton\n"
385 " -u: duplicate underscores in file names\n"
386 " -U none|type: select code splitting mode for the generated C++ code\n"
af710487 387 " -V verb_level: set verbosity level bitmask (decimal)\n"
970ed795
EL
388 " -w: suppress warnings\n"
389 " -x: disable TEXT encoder/decoder functions\n"
390 " -X: disable XER encoder/decoder functions\n"
970ed795 391 " -y: disable subtype checking\n"
970ed795 392 " -Y: Enforces legacy behaviour of the \"out\" function parameters (see refguide)\n"
af710487 393 //" -z: enable profiling and code coverage for TTCN-3 files\n" - not open to the public yet
970ed795
EL
394 " -T file: force interpretation of file as TTCN-3 module\n"
395 " -A file: force interpretation of file as ASN.1 module\n"
396 " -v: show version\n"
af710487 397 " --ttcn2json: generate JSON schema from input modules\n"
398 "JSON schema generator options:\n"
399 " -j: only include types with JSON encoding\n"
400 " -f: only generate references to types with JSON encoding/decoding functions\n", argv0, argv0, argv0);
970ed795
EL
401}
402
403#define SET_FLAG(x) if (x##flag) {\
404 ERROR("Flag -" #x " was specified more than once.");\
405 errflag = true;\
406 } else x##flag = true
407
408
409extern int ttcn3_debug;
410extern int asn1_yydebug;
411extern int pattern_yydebug;
412extern int pattern_unidebug;
413extern int rawAST_debug;
414extern int coding_attrib_debug;
415
416int main(int argc, char *argv[])
417{
418 argv0 = argv[0];
419#ifndef NDEBUG
420 asn1_yydebug = !! getenv("DEBUG_ASN1");
421 ttcn3_debug = !! getenv("DEBUG_TTCN");
422 pattern_unidebug= pattern_yydebug = !! getenv("DEBUG_PATTERN");
423 rawAST_debug = !! getenv("DEBUG_RAW");
424 coding_attrib_debug = !!getenv("DEBUG_ATRIB") || getenv("DEBUG_ATTRIB");
425#endif
426
427#ifdef MEMORY_DEBUG
428#if defined(__CYGWIN__) || defined(INTERIX)
429 //nothing to do
430#else
431 debug_new_counter.set_program_name(argv0);
432#endif
433#endif
434
435 if (argc == 1) {
436 fputs("TTCN-3 and ASN.1 Compiler for the TTCN-3 Test Executor, version "
437 PRODUCT_NUMBER "\n", stderr);
438 usage();
439 return EXIT_FAILURE;
440 }
441
442 bool
443 Aflag = false, Lflag = false, Yflag = false,
444 Pflag = false, Tflag = false, Vflag = false, bflag = false,
445 cflag = false, fflag = false, iflag = false, lflag = false,
446 oflag = false, pflag = false, qflag = false, rflag = false, sflag = false,
447 tflag = false, uflag = false, vflag = false, wflag = false, xflag = false,
448 dflag = false, Xflag = false, Rflag = false, gflag = false, aflag = false,
449 s0flag = false, Cflag = false, yflag = false, Uflag = false, Qflag = false,
af710487 450 Sflag = false, Kflag = false, jflag = false, zflag = false,
970ed795
EL
451 errflag = false, print_usage = false, ttcn2json = false;
452
453 CodeGenHelper cgh;
454
455 bool asn1_modules_present = false;
456#ifdef LICENSE
457 bool ttcn3_modules_present = false;
458#endif
459 size_t n_modules = 0;
460 module_struct *module_list = NULL;
461 char* json_schema_name = NULL;
462
463 if (0 == strcmp(argv[1], "--ttcn2json")) {
464 ttcn2json = true;
465 display_up_to_date = TRUE;
af710487 466 implicit_json_encoding = TRUE;
970ed795
EL
467 for (int i = 2; i < argc; ++i) {
468 // A dash (-) is used to separate the schema file name from the input files
469 if (0 == strcmp(argv[i], "-")) {
470 if (i == argc - 2) {
471 json_schema_name = mcopystr(argv[i + 1]);
472 } else {
473 ERROR("Expected JSON schema name (1 argument) after option `--ttcn2json' and `-'");
474 errflag = true;
475 }
476 break;
477 }
478 else if (0 == strcmp(argv[i], "-A")) {
479 ++i;
480 if (i == argc) {
481 ERROR("Option `-A' must be followed by an ASN.1 file name");
482 errflag = true;
483 break;
484 }
485 add_module(n_modules, module_list, argv[i], Module::MOD_ASN);
486 asn1_modules_present = true;
487 }
488 else if (0 == strcmp(argv[i], "-T")) {
489 ++i;
490 if (i == argc) {
491 ERROR("Option `-T' must be followed by a TTCN-3 file name");
492 errflag = true;
493 break;
494 }
495 add_module(n_modules, module_list, argv[i], Module::MOD_TTCN);
496 }
af710487 497 else if (0 == strcmp(argv[i], "-j")) {
498 implicit_json_encoding = FALSE;
499 }
500 else if (0 == strcmp(argv[i], "-f")) {
501 json_refs_for_all_types = FALSE;
502 }
503 else if (0 == strcmp(argv[i], "-fj") || 0 == strcmp(argv[i], "-jf")) {
504 implicit_json_encoding = FALSE;
505 json_refs_for_all_types = FALSE;
506 }
970ed795
EL
507 else if (argv[i][0] == '-') {
508 ERROR("Invalid option `%s' after option `--ttcn2json'", argv[i]);
509 print_usage = true;
510 errflag = true;
511 break;
512 }
513 else {
514 add_module(n_modules, module_list, argv[i], Module::MOD_UNKNOWN);
515 }
516 }
517
518 if (!errflag && 0 == n_modules) {
519 ERROR("No TTCN-3 or ASN.1 modules specified after option `--ttcn2json'");
520 errflag = true;
521 print_usage = true;
522 }
523
524 if (!errflag && NULL == json_schema_name) {
525 // Create the schema name using the first TTCN-3 or ASN.1 file's name
526 const module_struct& first = module_list[0];
527 if (0 == strncmp(first.file_name + strlen(first.file_name) - 4, ".asn", 4)) {
528 json_schema_name = mcopystrn(first.file_name, strlen(first.file_name) - 4);
529 json_schema_name = mputstrn(json_schema_name, ".json", 5);
530 }
531 else if (0 == strncmp(first.file_name + strlen(first.file_name) - 5, ".ttcn", 5)) {
532 json_schema_name = mcopystrn(first.file_name, strlen(first.file_name) - 5);
533 json_schema_name = mputstrn(json_schema_name, ".json", 5);
534 }
535 else {
536 json_schema_name = mprintf("%s.json", first.file_name);
537 }
538 }
539 }
540
541 if (!ttcn2json) {
542 for ( ; ; ) {
af710487 543 int c = getopt(argc, argv, "aA:C:K:LP:T:V:bcdfgilo:YpqQ:rRs0StuU:vwxXjyz-");
970ed795
EL
544 if (c == -1) break;
545 switch (c) {
546 case 'a':
547 SET_FLAG(a);
548 asn1_xer = TRUE;
549 break;
550 case 'A':
551 Aflag = true;
552 add_module(n_modules, module_list, optarg, Module::MOD_ASN);
553 asn1_modules_present = true;
554 break;
555 case 'C':
556 SET_FLAG(C);
557 expected_platform = optarg;
558 break;
559 case 'L':
560 SET_FLAG(L);
561 include_location_info = TRUE;
562 break;
563 case 'P':
564 Pflag = true;
565 nof_top_level_pdus++;
566 top_level_pdu=(const char**)
567 Realloc(top_level_pdu, nof_top_level_pdus*sizeof(*top_level_pdu));
568 top_level_pdu[nof_top_level_pdus-1] = optarg;
569 break;
570 case 'T':
571 Tflag = true;
572 add_module(n_modules, module_list, optarg, Module::MOD_TTCN);
573 #ifdef LICENSE
574 ttcn3_modules_present = true;
575 #endif
576 break;
577 case 'V':
578 SET_FLAG(V);
579 /* set verbosity level bitmask */
580 if (isdigit(optarg[0])) {
581 verb_level = atoi(optarg);
582 // don't bother with overflow
583 errno = 0;
584 } else {
585 ERROR("Option `-V' requires a decimal number as argument instead of "
586 "`%s'.", optarg);
587 errflag = true;
588 }
589 break;
590 case 'b':
591 SET_FLAG(b);
592 ber_disabled = TRUE;
593 break;
594 case 'c':
595 SET_FLAG(c);
596 break;
597 case 'd':
598 SET_FLAG(d);
599 default_as_optional = TRUE;
600 break;
601 case 'f':
602 SET_FLAG(f);
603 force_overwrite = TRUE;
604 break;
605 case 'g':
606 SET_FLAG(g);
607 gcc_compat = TRUE;
608 break;
609 case 'i':
610 SET_FLAG(i);
611 output_only_linenum = TRUE;
612 break;
613 case 'K':
614 SET_FLAG(K);
615 tcov_file_name = optarg;
616 break;
617 case 'l':
618 SET_FLAG(l);
619 include_line_info = TRUE;
620 break;
621 case 'o':
622 SET_FLAG(o);
623 output_dir = optarg;
624 break;
625 case 'Y':
626 SET_FLAG(Y);
627 enable_set_bound_out_param = TRUE;
628 break;
629 case 'p':
630 SET_FLAG(p);
631 parse_only = TRUE;
632 break;
633 case 'q':
634 SET_FLAG(q);
635 /* quiet; suppress all message */
636 verb_level = 0;
637 break;
638 case 'r':
639 SET_FLAG(r);
640 raw_disabled = TRUE;
641 break;
642 case 'R':
643 SET_FLAG(R);
644 use_runtime_2 = TRUE;
645 break;
646 case 's':
647 SET_FLAG(s);
648 semantic_check_only = TRUE;
649 break;
650 case 'S':
651 SET_FLAG(S);
652 suppress_context = TRUE;
653 break;
654 case '0':
655 SET_FLAG(s0);
656 attribute_validation_disabled = TRUE;
657 break;
658 case 't':
659 SET_FLAG(t);
660 generate_skeleton = TRUE;
661 break;
662 case 'u':
663 SET_FLAG(u);
664 duplicate_underscores = TRUE;
665 break;
666 case 'U':
667 SET_FLAG(U);
668 if (!cgh.set_split_mode(optarg)) {
669 ERROR("Wrong code splitting option: '%s'. Valid values are: 'none', "
670 "'type'.", optarg);
671 errflag = true;
672 }
673 break;
674 case 'v':
675 SET_FLAG(v);
676 break;
677 case 'w':
678 SET_FLAG(w);
679 /* suppress warnings and "not supported" messages */
680 verb_level &= ~(1|2);
681 break;
682 case 'x':
683 SET_FLAG(x);
684 text_disabled = TRUE;
685 break;
686 case 'X':
687 SET_FLAG(X);
688 xer_disabled = TRUE;
689 break;
690 case 'j':
691 SET_FLAG(j);
692 json_disabled = TRUE;
693 break;
694 case 'y':
695 SET_FLAG(y);
696 check_subtype = FALSE;
697 break;
af710487 698 case 'z':
699 SET_FLAG(z);
700 profiler_enabled = TRUE;
701 break;
970ed795
EL
702
703 case 'Q': {
704 long max_errs;
705 SET_FLAG(Q);
706 printf("Q: %s\n", optarg);
707
708 errno = 0;
709 max_errs = strtol(optarg, (char**)NULL, 10);
710 if (errno != 0
711 || (long)(int)max_errs != max_errs) { // does not fit into int
712 ERROR("Invalid value %s: %s", optarg, strerror(errno));
713 errflag = true;
714 }
715 else if (max_errs < 0) {
716 ERROR("Negative value %s not allowed", optarg);
717 errflag = true;
718 }
719 else { // all good
720 if (max_errs == 0) max_errs = 1;
721 }
722
723 Error_Context::set_max_errors(max_errs);
724 break; }
725
726 case '-':
727 if (!strcmp(argv[optind], "--ttcn2json")) {
af710487 728 ERROR("Option `--ttcn2json' is only allowed as the first option");
970ed795
EL
729 } else {
730 ERROR("Invalid option: `%s'", argv[optind]);
731 }
732 // no break
733
734 default:
735 errflag = true;
736 print_usage = true;
737 break;
738 }
739 }
740
741 /* Checking incompatible options */
742 if (vflag) {
743 if (Aflag || Lflag || Pflag || Tflag || Vflag || Yflag ||
744 bflag || fflag || iflag || lflag || oflag || pflag || qflag ||
745 rflag || sflag || tflag || uflag || wflag || xflag || Xflag || Rflag ||
af710487 746 Uflag || yflag || Kflag || jflag || zflag) {
970ed795
EL
747 errflag = true;
748 print_usage = true;
749 }
750 } else {
751 if (pflag) {
752 if (sflag) {
753 ERROR("Options `-p' and `-s' are incompatible with each other.");
754 // totally confusing: exit immediately
755 errflag = true;
756 }
757 }
758 if (Kflag && !Lflag) {
759 ERROR("Source line information `-L' is necessary for code coverage `-K'.");
760 errflag = true;
761 }
af710487 762 if (zflag && !Lflag) {
763 ERROR("Source line information `-L' is necessary for profiling `-z'.");
764 errflag = true;
765 }
970ed795
EL
766 if (iflag && gflag) {
767 WARNING("Option `-g' overrides `-i'.");
768 iflag = false; // -g gives more information
769 }
770 if (oflag && get_path_status(output_dir) != PS_DIRECTORY) {
771 ERROR("The argument of -o switch (`%s') must be a directory.",
772 output_dir);
773 errflag = true;
774 }
775 if (optind == argc && n_modules == 0) {
776 ERROR("No input TTCN-3 or ASN.1 module was given.");
777 errflag = true;
778 }
779 }
780 } // if (!ttcn2json)
781
782 if (errflag) {
783 if (print_usage) usage();
784 Free(json_schema_name);
785 return EXIT_FAILURE;
786 }
787
788 if (vflag) {
789 fputs("TTCN-3 and ASN.1 Compiler for the TTCN-3 Test Executor\n"
790 "Product number: " PRODUCT_NUMBER "\n"
791 "Build date: " __DATE__ " " __TIME__ "\n"
792 "Compiled with: " C_COMPILER_VERSION "\n\n"
793 COPYRIGHT_STRING "\n\n", stderr);
794#ifdef LICENSE
795 print_license_info();
796 fputs("\nUsing ", stderr);
797 fputs(openssl_version_str(), stderr);
798 fputs("\n\n", stderr);
799#endif
800 return EXIT_SUCCESS;
801 }
802
803#ifdef LICENSE
804 init_openssl();
805 license_struct lstr;
806 load_license(&lstr);
807 int license_valid = verify_license(&lstr);
808 free_openssl();
809 if (!license_valid) {
810 free_license(&lstr);
811 exit(EXIT_FAILURE);
812 }
813#endif
814
815 if (!ttcn2json) {
816 /* the position of '-' switch in argv list */
817 int dash_position = -1;
818
819 /* Add the remaining files until switch '-' to the module_list */
820 for(int i = optind; i < argc; i++) {
821 if (strcmp(argv[i], "-"))
822 add_module(n_modules, module_list, argv[i], Module::MOD_UNKNOWN);
823 else {
824 dash_position = i;
825 break;
826 }
827 }
828
829 if (dash_position == -1) {
830 /** if '-' was not present in the command line code should be generated for
831 * all modules */
832 for (size_t i = 0; i < n_modules; i++) module_list[i].need_codegen = true;
833 } else {
834 for (int i = dash_position + 1; i < argc; i++) {
835 char *absolute_path = canonize_input_file(argv[i]);
836 if (absolute_path == NULL) continue;
837 bool found = false;
838 for (size_t j = 0; j < n_modules; j++) {
839 module_struct *module = module_list + j;
840 if (!strcmp(module->absolute_path, absolute_path)) {
841 module->need_codegen = true;
842 found = true;
843 // do not stop: the same file may be present on the list twice
844 // (as both ASN.1 and TTCN-3 module)
845 }
846 }
847 Free(absolute_path);
848 if (!found) {
849 ERROR("File `%s' was not given before the `-' switch for selective "
850 "code generation.", argv[i]);
851 // go further (i.e. check all files after the `-')
852 }
853 }
854 }
855 } // if (!ttcn2json)
856
857 {
858 STOPWATCH("Determining module types");
859 // check the readability of all files and
860 // determine the type of unknown modules
861 for (size_t i = 0; i < n_modules; i++) {
862 module_struct *module = module_list + i;
863 FILE *fp = fopen(module->file_name, "r");
864 if (fp != NULL) {
865 if (module->module_type == Module::MOD_UNKNOWN) {
866 // try the ASN.1 and TTCN-3 preparsers
867 boolean asn1_module = is_asn1_module(module->file_name, fp, NULL);
868 boolean ttcn3_module = is_ttcn3_module(module->file_name, fp, NULL);
869 if (asn1_module) {
870 if (!is_valid_asn1_filename (module->file_name)) {
871 ERROR("The file name (without suffix) shall be identical to the module name.\n"
872 "If the name of the ASN.1 module contains a hyphen, the corresponding "
873 "file name shall contain an underscore character instead.");
874 }
875 if (ttcn3_module) {
876 ERROR("File `%s' looks so strange that it can contain both an "
877 "ASN.1 and a TTCN-3 module. Use the command-line switch `-A' or "
878 "`-T' to set its type.", module->file_name);
879 } else {
880 bool found = false;
881 for (size_t j = 0; j < n_modules; j++) {
882 module_struct *module2 = module_list + j;
883 if (module2->module_type == Module::MOD_ASN &&
884 !strcmp(module->absolute_path, module2->absolute_path)) {
885 found = true;
886 break;
887 }
888 }
889 if (found) {
890 ERROR("Input file `%s' was given more than once.",
891 module->file_name);
892 } else {
893 module->module_type = Module::MOD_ASN;
894 asn1_modules_present = true;
895 }
896 }
897 } else if (ttcn3_module) {
898 bool found = false;
899 for (size_t j = 0; j < n_modules; j++) {
900 module_struct *module2 = module_list + j;
901 if (module2->module_type == Module::MOD_TTCN &&
902 !strcmp(module->absolute_path, module2->absolute_path)) {
903 found = true;
904 break;
905 }
906 }
907 if (found) {
908 ERROR("Input file `%s' was given more than once.",
909 module->file_name);
910 } else {
911 module->module_type = Module::MOD_TTCN;
912#ifdef LICENSE
913 ttcn3_modules_present = true;
914#endif
915 }
916 } else {
917 ERROR("Cannot recognize file `%s' as an ASN.1 or TTCN-3 module. "
918 "Use the command-line switch `-A' or `-T' to set its type.",
919 module->file_name);
920 }
921 }
922 fclose(fp);
923 } else {
924 ERROR("Cannot open input file `%s' for reading: %s", module->file_name,
925 strerror(errno));
926 errno = 0;
927 // do not invoke the real parsers on that file
928 module->module_type = Module::MOD_UNKNOWN;
929 }
930 }
931 }
932
933#if defined(MINGW)
934 if (!semantic_check_only) {
935 NOTIFY("On native win32 builds code generation is disabled.");
936 semantic_check_only = TRUE;
937 }
938#endif
939#ifdef LICENSE
940 /* Checking of required license features */
941 if (asn1_modules_present && !check_feature(&lstr, FEATURE_ASN1)) {
942 ERROR("The license key does not allow the parsing of "
943 "ASN.1 modules.");
944 return EXIT_FAILURE;
945 }
946 if (ttcn3_modules_present && !check_feature(&lstr, FEATURE_TTCN3)) {
947 ERROR("The license key does not allow the parsing of "
948 "TTCN-3 modules.");
949 return EXIT_FAILURE;
950 }
951 if (!parse_only && !semantic_check_only &&
952 !check_feature(&lstr, FEATURE_CODEGEN)) {
953 WARNING("The license key does not allow the generation of "
954 "C++ code.");
955 semantic_check_only = TRUE;
956 }
957 if (generate_skeleton && !check_feature(&lstr, FEATURE_TPGEN)) {
958 WARNING("The license key does not allow the generation of "
959 "Test Port skeletons.");
960 generate_skeleton = FALSE;
961 }
962 has_raw_feature = check_feature(&lstr, FEATURE_RAW);
963 has_ber_feature = check_feature(&lstr, FEATURE_BER);
964 has_per_feature = check_feature(&lstr, FEATURE_PER);
965 has_text_feature = check_feature(&lstr, FEATURE_TEXT);
966 has_xer_feature = check_feature(&lstr, FEATURE_XER);
967 free_license(&lstr);
968#endif
969 if (Kflag && !check_file_list(tcov_file_name, module_list, n_modules)) {
970 ERROR("Error while processing `%s' provided for code coverage data "
971 "generation.", tcov_file_name);
972 return EXIT_FAILURE;
973 }
974 {
975 STOPWATCH("Parsing modules");
976
977 // asn1_yydebug=1;
978 if (asn1_modules_present) asn1_init();
979 modules = new Common::Modules();
980
981 for (size_t i = 0; i < n_modules; i++) {
982 const module_struct *module = module_list + i;
983 switch (module->module_type) {
984 case Module::MOD_ASN:
985 asn1_parse_file(module->file_name, module->need_codegen);
986 break;
987 case Module::MOD_TTCN:
988 ttcn3_parse_file(module->file_name, module->need_codegen);
989 break;
990 default: // MOD_UNKNOWN ?
991 break;
992 }
993 }
994
995 for (size_t i = 0; i < n_modules; i++) Free(module_list[i].absolute_path);
996 Free(module_list);
997 }
998
999 if (!parse_only && 0 == Error_Context::get_error_count()) {
1000 NOTIFY("Checking modules...");
1001 {
1002 STOPWATCH("Semantic check");
1003 modules->chk();
1004 }
1005 }
1006
1007 if (verb_level > 7) modules->dump();
1008
1009 int ret_val = EXIT_SUCCESS;
1010 unsigned int error_count = Error_Context::get_error_count();
1011 if (error_count > 0) ret_val = EXIT_FAILURE;
1012
1013 if (parse_only || semantic_check_only) {
1014 // print detailed statistics
1015 Error_Context::print_error_statistics();
1016 } else {
1017 if (error_count == 0) {
1018#ifdef USAGE_STATS
1019 {
1020 // Ignore SIGPIPE signals
1021 struct sigaction sig_act;
1022 if (sigaction(SIGPIPE, NULL, &sig_act))
1023 ERROR("System call sigaction() failed when getting signal "
1024 "handling information for %s.", "SIGINT");
1025 sig_act.sa_handler = SIG_IGN;
1026 sig_act.sa_flags = 0;
1027 if (sigaction(SIGPIPE, &sig_act, NULL))
1028 ERROR("System call sigaction() failed when disabling signal "
1029 "%s.", "SIGINT");
1030 }
1031
1032 std::stringstream stream;
1033 stream << "compiler";
1034 std::set<ModuleVersion> versions = modules->getVersionsWithProductNumber();
1035 if (!versions.empty()) {
1036 stream << "&products=";
1037 for (std::set<ModuleVersion>::iterator it = versions.begin(); it != versions.end(); ++it) {
1038 if (it != versions.begin()) {
1039 stream << ",";
1040 }
1041 stream << it->toString();
1042 }
1043 }
1044
1045 HttpSender *sender = new HttpSender;
1046 UsageData::getInstance().sendDataThreaded(stream.str(), sender);
1047#endif
1048 if (ttcn2json) {
1049 NOTIFY("Generating JSON schema...");
1050 STOPWATCH("Generating JSON schema");
1051 // the Ttcn2Json constructor starts the process
1052 Ttcn::Ttcn2Json t2j(modules, json_schema_name);
1053 } else {
1054 NOTIFY("Generating code...");
1055 STOPWATCH("Generating code");
1056 modules->generate_code(cgh);
1057 report_nof_updated_files();
1058 }
1059 } else {
1060 NOTIFY("Error%s found in the input module%s. Code will not be generated.",
1061 error_count > 1 ? "s" : "", n_modules > 1 ? "s" : "");
1062 if (cflag) {
1063 modules->write_checksums();
1064 }
1065 }
1066 }
1067
1068 if (Kflag) {
1069 while (tcov_files != NULL) {
1070 tcov_file_list *next_file = tcov_files->next;
1071 Free(tcov_files->file_name);
1072 delete tcov_files;
1073 tcov_files = next_file;
1074 }
1075 tcov_files = NULL;
1076 }
1077 delete modules;
1078 Free(top_level_pdu);
1079 if (asn1_modules_present) asn1_free();
1080 Type::free_pools();
1081 Common::Node::chk_counter();
1082 Location::delete_source_file_names();
1083 Free(json_schema_name);
1084
1085 // dbgnew.hh already does it: check_mem_leak(argv[0]);
1086
1087 return ret_val;
1088}
This page took 0.064337 seconds and 5 git commands to generate.