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