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