Merge pull request #26 from BotondBaranyi/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,
7329404e 97 warnings_for_bad_variants = FALSE, debugger_active = 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,
7329404e
BB
482 Mflag = false, Eflag = false, nflag = false, errflag = false,
483 print_usage = false, 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 ( ; ; ) {
7329404e 575 int c = getopt(argc, argv, "aA:bcC:dEfFgijK:lLMno: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;
7329404e
BB
746 case 'n':
747 SET_FLAG(n);
748 debugger_active = TRUE;
749 break;
970ed795
EL
750
751 case 'Q': {
752 long max_errs;
753 SET_FLAG(Q);
754 printf("Q: %s\n", optarg);
755
756 errno = 0;
757 max_errs = strtol(optarg, (char**)NULL, 10);
758 if (errno != 0
759 || (long)(int)max_errs != max_errs) { // does not fit into int
760 ERROR("Invalid value %s: %s", optarg, strerror(errno));
761 errflag = true;
762 }
763 else if (max_errs < 0) {
764 ERROR("Negative value %s not allowed", optarg);
765 errflag = true;
766 }
767 else { // all good
768 if (max_errs == 0) max_errs = 1;
769 }
770
771 Error_Context::set_max_errors(max_errs);
772 break; }
a38c6d4c 773
774 case '-':
970ed795 775 if (!strcmp(argv[optind], "--ttcn2json")) {
af710487 776 ERROR("Option `--ttcn2json' is only allowed as the first option");
970ed795
EL
777 } else {
778 ERROR("Invalid option: `%s'", argv[optind]);
779 }
780 // no break
781
782 default:
783 errflag = true;
784 print_usage = true;
785 break;
786 }
787 }
788
789 /* Checking incompatible options */
790 if (vflag) {
791 if (Aflag || Lflag || Pflag || Tflag || Vflag || Yflag ||
792 bflag || fflag || iflag || lflag || oflag || pflag || qflag ||
793 rflag || sflag || tflag || uflag || wflag || xflag || Xflag || Rflag ||
7329404e
BB
794 Uflag || yflag || Kflag || jflag || zflag || Fflag || Mflag || Eflag ||
795 nflag) {
970ed795
EL
796 errflag = true;
797 print_usage = true;
798 }
799 } else {
800 if (pflag) {
801 if (sflag) {
802 ERROR("Options `-p' and `-s' are incompatible with each other.");
803 // totally confusing: exit immediately
804 errflag = true;
805 }
806 }
807 if (Kflag && !Lflag) {
808 ERROR("Source line information `-L' is necessary for code coverage `-K'.");
809 errflag = true;
810 }
af710487 811 if (zflag && !Lflag) {
812 ERROR("Source line information `-L' is necessary for profiling `-z'.");
813 errflag = true;
814 }
7329404e
BB
815 if (nflag && !Lflag) {
816 ERROR("Source line information `-L' is necessary for debugging `-n'.");
817 errflag = true;
818 }
970ed795
EL
819 if (iflag && gflag) {
820 WARNING("Option `-g' overrides `-i'.");
821 iflag = false; // -g gives more information
822 }
823 if (oflag && get_path_status(output_dir) != PS_DIRECTORY) {
824 ERROR("The argument of -o switch (`%s') must be a directory.",
825 output_dir);
826 errflag = true;
827 }
828 if (optind == argc && n_modules == 0) {
829 ERROR("No input TTCN-3 or ASN.1 module was given.");
830 errflag = true;
831 }
832 }
833 } // if (!ttcn2json)
834
835 if (errflag) {
836 if (print_usage) usage();
837 Free(json_schema_name);
838 return EXIT_FAILURE;
839 }
840
841 if (vflag) {
842 fputs("TTCN-3 and ASN.1 Compiler for the TTCN-3 Test Executor\n"
843 "Product number: " PRODUCT_NUMBER "\n"
844 "Build date: " __DATE__ " " __TIME__ "\n"
845 "Compiled with: " C_COMPILER_VERSION "\n\n"
846 COPYRIGHT_STRING "\n\n", stderr);
847#ifdef LICENSE
848 print_license_info();
849 fputs("\nUsing ", stderr);
850 fputs(openssl_version_str(), stderr);
851 fputs("\n\n", stderr);
852#endif
853 return EXIT_SUCCESS;
854 }
855
856#ifdef LICENSE
857 init_openssl();
858 license_struct lstr;
859 load_license(&lstr);
860 int license_valid = verify_license(&lstr);
861 free_openssl();
862 if (!license_valid) {
863 free_license(&lstr);
864 exit(EXIT_FAILURE);
865 }
866#endif
867
868 if (!ttcn2json) {
869 /* the position of '-' switch in argv list */
870 int dash_position = -1;
871
872 /* Add the remaining files until switch '-' to the module_list */
873 for(int i = optind; i < argc; i++) {
874 if (strcmp(argv[i], "-"))
875 add_module(n_modules, module_list, argv[i], Module::MOD_UNKNOWN);
876 else {
877 dash_position = i;
878 break;
879 }
880 }
881
882 if (dash_position == -1) {
883 /** if '-' was not present in the command line code should be generated for
884 * all modules */
885 for (size_t i = 0; i < n_modules; i++) module_list[i].need_codegen = true;
886 } else {
887 for (int i = dash_position + 1; i < argc; i++) {
888 char *absolute_path = canonize_input_file(argv[i]);
889 if (absolute_path == NULL) continue;
890 bool found = false;
891 for (size_t j = 0; j < n_modules; j++) {
892 module_struct *module = module_list + j;
893 if (!strcmp(module->absolute_path, absolute_path)) {
894 module->need_codegen = true;
895 found = true;
896 // do not stop: the same file may be present on the list twice
897 // (as both ASN.1 and TTCN-3 module)
898 }
899 }
900 Free(absolute_path);
901 if (!found) {
902 ERROR("File `%s' was not given before the `-' switch for selective "
903 "code generation.", argv[i]);
904 // go further (i.e. check all files after the `-')
905 }
906 }
907 }
908 } // if (!ttcn2json)
909
910 {
911 STOPWATCH("Determining module types");
912 // check the readability of all files and
913 // determine the type of unknown modules
914 for (size_t i = 0; i < n_modules; i++) {
915 module_struct *module = module_list + i;
916 FILE *fp = fopen(module->file_name, "r");
917 if (fp != NULL) {
918 if (module->module_type == Module::MOD_UNKNOWN) {
919 // try the ASN.1 and TTCN-3 preparsers
920 boolean asn1_module = is_asn1_module(module->file_name, fp, NULL);
921 boolean ttcn3_module = is_ttcn3_module(module->file_name, fp, NULL);
922 if (asn1_module) {
923 if (!is_valid_asn1_filename (module->file_name)) {
924 ERROR("The file name (without suffix) shall be identical to the module name.\n"
925 "If the name of the ASN.1 module contains a hyphen, the corresponding "
926 "file name shall contain an underscore character instead.");
927 }
928 if (ttcn3_module) {
929 ERROR("File `%s' looks so strange that it can contain both an "
930 "ASN.1 and a TTCN-3 module. Use the command-line switch `-A' or "
931 "`-T' to set its type.", module->file_name);
932 } else {
933 bool found = false;
934 for (size_t j = 0; j < n_modules; j++) {
935 module_struct *module2 = module_list + j;
936 if (module2->module_type == Module::MOD_ASN &&
937 !strcmp(module->absolute_path, module2->absolute_path)) {
938 found = true;
939 break;
940 }
941 }
942 if (found) {
943 ERROR("Input file `%s' was given more than once.",
944 module->file_name);
945 } else {
946 module->module_type = Module::MOD_ASN;
947 asn1_modules_present = true;
948 }
949 }
950 } else if (ttcn3_module) {
951 bool found = false;
952 for (size_t j = 0; j < n_modules; j++) {
953 module_struct *module2 = module_list + j;
954 if (module2->module_type == Module::MOD_TTCN &&
955 !strcmp(module->absolute_path, module2->absolute_path)) {
956 found = true;
957 break;
958 }
959 }
960 if (found) {
961 ERROR("Input file `%s' was given more than once.",
962 module->file_name);
963 } else {
964 module->module_type = Module::MOD_TTCN;
965#ifdef LICENSE
966 ttcn3_modules_present = true;
967#endif
968 }
969 } else {
970 ERROR("Cannot recognize file `%s' as an ASN.1 or TTCN-3 module. "
971 "Use the command-line switch `-A' or `-T' to set its type.",
972 module->file_name);
973 }
974 }
975 fclose(fp);
976 } else {
977 ERROR("Cannot open input file `%s' for reading: %s", module->file_name,
978 strerror(errno));
979 errno = 0;
980 // do not invoke the real parsers on that file
981 module->module_type = Module::MOD_UNKNOWN;
982 }
983 }
984 }
985
986#if defined(MINGW)
987 if (!semantic_check_only) {
988 NOTIFY("On native win32 builds code generation is disabled.");
989 semantic_check_only = TRUE;
990 }
991#endif
992#ifdef LICENSE
993 /* Checking of required license features */
994 if (asn1_modules_present && !check_feature(&lstr, FEATURE_ASN1)) {
995 ERROR("The license key does not allow the parsing of "
996 "ASN.1 modules.");
997 return EXIT_FAILURE;
998 }
999 if (ttcn3_modules_present && !check_feature(&lstr, FEATURE_TTCN3)) {
1000 ERROR("The license key does not allow the parsing of "
1001 "TTCN-3 modules.");
1002 return EXIT_FAILURE;
1003 }
1004 if (!parse_only && !semantic_check_only &&
1005 !check_feature(&lstr, FEATURE_CODEGEN)) {
1006 WARNING("The license key does not allow the generation of "
1007 "C++ code.");
1008 semantic_check_only = TRUE;
1009 }
1010 if (generate_skeleton && !check_feature(&lstr, FEATURE_TPGEN)) {
1011 WARNING("The license key does not allow the generation of "
1012 "Test Port skeletons.");
1013 generate_skeleton = FALSE;
1014 }
1015 has_raw_feature = check_feature(&lstr, FEATURE_RAW);
1016 has_ber_feature = check_feature(&lstr, FEATURE_BER);
1017 has_per_feature = check_feature(&lstr, FEATURE_PER);
1018 has_text_feature = check_feature(&lstr, FEATURE_TEXT);
1019 has_xer_feature = check_feature(&lstr, FEATURE_XER);
1020 free_license(&lstr);
1021#endif
a38c6d4c 1022 if (Kflag && !check_file_list(tcov_file_name, module_list, n_modules, tcov_files)) {
970ed795
EL
1023 ERROR("Error while processing `%s' provided for code coverage data "
1024 "generation.", tcov_file_name);
1025 return EXIT_FAILURE;
1026 }
a38c6d4c 1027 if (zflag) {
1028 tcov_file_list *file_list_head = NULL;
1029 if(!check_file_list(profiler_file_name, module_list, n_modules, file_list_head)) {
1030 ERROR("Error while processing `%s' provided for profiling and code coverage.",
1031 profiler_file_name);
1032 return EXIT_FAILURE;
1033 }
1034 init_profiler_data(file_list_head);
1035 }
970ed795
EL
1036 {
1037 STOPWATCH("Parsing modules");
1038
1039 // asn1_yydebug=1;
1040 if (asn1_modules_present) asn1_init();
1041 modules = new Common::Modules();
1042
1043 for (size_t i = 0; i < n_modules; i++) {
1044 const module_struct *module = module_list + i;
1045 switch (module->module_type) {
1046 case Module::MOD_ASN:
1047 asn1_parse_file(module->file_name, module->need_codegen);
1048 break;
1049 case Module::MOD_TTCN:
1050 ttcn3_parse_file(module->file_name, module->need_codegen);
1051 break;
1052 default: // MOD_UNKNOWN ?
1053 break;
1054 }
1055 }
1056
1057 for (size_t i = 0; i < n_modules; i++) Free(module_list[i].absolute_path);
1058 Free(module_list);
1059 }
1060
1061 if (!parse_only && 0 == Error_Context::get_error_count()) {
1062 NOTIFY("Checking modules...");
1063 {
1064 STOPWATCH("Semantic check");
1065 modules->chk();
1066 }
1067 }
1068
1069 if (verb_level > 7) modules->dump();
1070
1071 int ret_val = EXIT_SUCCESS;
1072 unsigned int error_count = Error_Context::get_error_count();
1073 if (error_count > 0) ret_val = EXIT_FAILURE;
1074
1075 if (parse_only || semantic_check_only) {
1076 // print detailed statistics
1077 Error_Context::print_error_statistics();
1078 } else {
1079 if (error_count == 0) {
1080#ifdef USAGE_STATS
1081 {
1082 // Ignore SIGPIPE signals
1083 struct sigaction sig_act;
1084 if (sigaction(SIGPIPE, NULL, &sig_act))
1085 ERROR("System call sigaction() failed when getting signal "
1086 "handling information for %s.", "SIGINT");
1087 sig_act.sa_handler = SIG_IGN;
1088 sig_act.sa_flags = 0;
1089 if (sigaction(SIGPIPE, &sig_act, NULL))
1090 ERROR("System call sigaction() failed when disabling signal "
1091 "%s.", "SIGINT");
1092 }
1093
1094 std::stringstream stream;
1095 stream << "compiler";
1096 std::set<ModuleVersion> versions = modules->getVersionsWithProductNumber();
1097 if (!versions.empty()) {
1098 stream << "&products=";
1099 for (std::set<ModuleVersion>::iterator it = versions.begin(); it != versions.end(); ++it) {
1100 if (it != versions.begin()) {
1101 stream << ",";
1102 }
1103 stream << it->toString();
1104 }
1105 }
1106
1107 HttpSender *sender = new HttpSender;
1108 UsageData::getInstance().sendDataThreaded(stream.str(), sender);
1109#endif
1110 if (ttcn2json) {
1111 NOTIFY("Generating JSON schema...");
1112 STOPWATCH("Generating JSON schema");
1113 // the Ttcn2Json constructor starts the process
1114 Ttcn::Ttcn2Json t2j(modules, json_schema_name);
1115 } else {
1116 NOTIFY("Generating code...");
1117 STOPWATCH("Generating code");
1118 modules->generate_code(cgh);
1119 report_nof_updated_files();
1120 }
1121 } else {
1122 NOTIFY("Error%s found in the input module%s. Code will not be generated.",
1123 error_count > 1 ? "s" : "", n_modules > 1 ? "s" : "");
1124 if (cflag) {
1125 modules->write_checksums();
1126 }
1127 }
1128 }
1129
1130 if (Kflag) {
1131 while (tcov_files != NULL) {
1132 tcov_file_list *next_file = tcov_files->next;
1133 Free(tcov_files->file_name);
a38c6d4c 1134 Free(tcov_files);
970ed795
EL
1135 tcov_files = next_file;
1136 }
1137 tcov_files = NULL;
1138 }
1139 delete modules;
1140 Free(top_level_pdu);
1141 if (asn1_modules_present) asn1_free();
1142 Type::free_pools();
1143 Common::Node::chk_counter();
1144 Location::delete_source_file_names();
1145 Free(json_schema_name);
a38c6d4c 1146 if (zflag) {
1147 free_profiler_data();
1148 }
970ed795
EL
1149
1150 // dbgnew.hh already does it: check_mem_leak(argv[0]);
1151
1152 return ret_val;
1153}
This page took 0.095261 seconds and 5 git commands to generate.