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