blob: cde798fff2a99193b103bd907e5d31da342a2549 [file] [log] [blame]
Lev Walkinfa409762017-03-26 06:37:38 -07001/*
2 * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info> and contributors.
3 * All rights reserved.
Lev Walkin12984672004-09-24 21:00:15 +00004 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
Lev Walkin12984672004-09-24 21:00:15 +000026 */
Lev Walkinf15320b2004-06-03 03:38:44 +000027/*
28 * This is the program that connects the libasn1* libraries together.
29 * It uses them in turn to parse, fix and then compile or print the ASN.1 tree.
30 */
Lev Walkinb47d1ad2019-01-21 14:54:50 -080031#include "asn1_common.h"
Lev Walkinf15320b2004-06-03 03:38:44 +000032
Lev Walkin41a1da62016-01-23 08:50:28 -080033#undef COPYRIGHT
Lev Walkinfa409762017-03-26 06:37:38 -070034#define COPYRIGHT "Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info> and contributors.\n"
Lev Walkinfb872bd2006-03-18 06:53:11 +000035
Lev Walkin41a1da62016-01-23 08:50:28 -080036#include <asn1parser.h> /* Parse the ASN.1 file and build a tree */
37#include <asn1fix.h> /* Fix the ASN.1 tree */
38#include <asn1print.h> /* Print the ASN.1 tree */
39#include <asn1compiler.h> /* Compile the ASN.1 tree */
Lev Walkinc0e03b92017-08-22 01:48:23 -070040#include <asn1fix_export.h>
Lev Walkinf15320b2004-06-03 03:38:44 +000041
Lev Walkin41a1da62016-01-23 08:50:28 -080042#include <asn1c_compat.h> /* Portable basename(3) and dirname(3) */
Lev Walkin79f54952004-08-13 16:58:19 +000043
Lev Walkin41a1da62016-01-23 08:50:28 -080044#ifdef _WIN32
Lev Walkin46499872006-03-06 13:05:34 +000045#include <io.h>
46#include <direct.h>
47#else
48#include <dirent.h>
49#endif
50
Lev Walkin41a1da62016-01-23 08:50:28 -080051static void usage(const char *av0); /* Print the Usage screen and exit */
Lev Walkin46499872006-03-06 13:05:34 +000052static int importStandardModules(asn1p_t *asn, const char *skeletons_dir);
Lev Walkincbf218f2004-08-20 13:24:38 +000053
Lev Walkinf15320b2004-06-03 03:38:44 +000054int
55main(int ac, char **av) {
Lev Walkin41a1da62016-01-23 08:50:28 -080056 enum asn1p_flags asn1_parser_flags = A1P_NOFLAGS;
57 enum asn1f_flags asn1_fixer_flags = A1F_NOFLAGS;
Lev Walkind1c28aa2017-11-11 18:04:26 -080058 enum asn1c_flags asn1_compiler_flags =
59 A1C_NO_C99 | A1C_GEN_OER | A1C_GEN_PER | A1C_GEN_EXAMPLE;
Lev Walkin41a1da62016-01-23 08:50:28 -080060 enum asn1print_flags asn1_printer_flags = APF_NOFLAGS;
61 int print_arg__print_out = 0; /* Don't compile, just print parsed */
62 int print_arg__fix_n_print = 0; /* Fix and print */
63 int warnings_as_errors = 0; /* Treat warnings as errors */
64 char *skeletons_dir = NULL; /* Directory with supplementary stuff */
Lev Walkin4645db02017-11-18 11:32:07 -080065 char *destdir = NULL; /* Destination for generated files */
Lev Walkin4215c512017-11-19 19:01:26 -080066 char **debug_type_names = 0; /* Debug stuff */
67 size_t debug_type_names_count = 0;
Lev Walkin41a1da62016-01-23 08:50:28 -080068 asn1p_t *asn = 0; /* An ASN.1 parsed tree */
69 int ret; /* Return value from misc functions */
70 int ch; /* Command line character */
71 int i; /* Index in some loops */
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +080072 int exit_code = 0; /* Exit code */
Lev Walkinf15320b2004-06-03 03:38:44 +000073
Lev Walkin41a1da62016-01-23 08:50:28 -080074 /*
75 * Process command-line options.
76 */
Lev Walkin4215c512017-11-19 19:01:26 -080077 while((ch = getopt(ac, av, "D:d:EFf:g:hn:LPp:RS:vW:X")) != -1) switch(ch) {
78 case 'D':
79 if(optarg && *optarg) {
80 size_t optarg_len = strlen(optarg);
81 free(destdir);
82 destdir = calloc(1, optarg_len + 2); /* + "/\0" */
83 assert(destdir);
84 strcpy(destdir, optarg);
85 if(destdir[optarg_len - 1] != '/') {
86 destdir[optarg_len] = '/';
87 }
88 } else {
89 free(destdir);
90 destdir = NULL;
91 }
92 break;
93 case 'd':
94 if(strncmp(optarg, "ebug-type-naming=", 17) == 0) {
95 char **p = realloc(debug_type_names,
96 (debug_type_names_count + 2) * sizeof(*p));
97 assert(p);
98 debug_type_names = p;
99 debug_type_names[debug_type_names_count++] =
100 strdup(optarg + 17);
101 debug_type_names[debug_type_names_count] = NULL;
102 break;
Lev Walkin840fb8e2017-11-19 23:39:59 -0800103 } else if(strcmp(optarg, "ebug-output-origin-lines") == 0) {
104 asn1_compiler_flags |= A1C_DEBUG_OUTPUT_ORIGIN_LINES;
105 break;
Lev Walkin4215c512017-11-19 19:01:26 -0800106 }
107 usage(av[0]);
Lev Walkin41a1da62016-01-23 08:50:28 -0800108 case 'E':
109 print_arg__print_out = 1;
110 break;
111 case 'F':
112 print_arg__fix_n_print = 1;
113 break;
114 case 'f':
115 if(strcmp(optarg, "all-defs-global") == 0) {
116 asn1_compiler_flags |= A1C_ALL_DEFS_GLOBAL;
117 } else if(strcmp(optarg, "bless-SIZE") == 0) {
118 asn1_fixer_flags |= A1F_EXTENDED_SizeConstraint;
119 } else if(strcmp(optarg, "compound-names") == 0) {
120 asn1_compiler_flags |= A1C_COMPOUND_NAMES;
121 } else if(strcmp(optarg, "indirect-choice") == 0) {
122 asn1_compiler_flags |= A1C_INDIRECT_CHOICE;
123 } else if(strncmp(optarg, "known-extern-type=", 18) == 0) {
124 char *known_type = optarg + 18;
125 ret = asn1f_make_known_external_type(known_type);
126 assert(ret == 0 || errno == EEXIST);
127 } else if(strcmp(optarg, "native-types") == 0) {
128 fprintf(stderr, "-f%s: Deprecated option\n", optarg);
129 asn1_compiler_flags &= ~A1C_USE_WIDE_TYPES;
130 } else if(strcmp(optarg, "wide-types") == 0) {
131 asn1_compiler_flags |= A1C_USE_WIDE_TYPES;
132 } else if(strcmp(optarg, "line-refs") == 0) {
133 asn1_compiler_flags |= A1C_LINE_REFS;
134 } else if(strcmp(optarg, "no-constraints") == 0) {
135 asn1_compiler_flags |= A1C_NO_CONSTRAINTS;
136 } else if(strcmp(optarg, "no-include-deps") == 0) {
137 asn1_compiler_flags |= A1C_NO_INCLUDE_DEPS;
138 } else if(strcmp(optarg, "includes-quoted") == 0) {
139 asn1_compiler_flags |= A1C_INCLUDES_QUOTED;
140 } else if(strcmp(optarg, "unnamed-unions") == 0) {
141 asn1_compiler_flags |= A1C_UNNAMED_UNIONS;
142 } else if(strcmp(optarg, "skeletons-copy") == 0) {
143 fprintf(stderr, "-f%s: Deprecated option\n", optarg);
144 asn1_compiler_flags &= ~A1C_LINK_SKELETONS;
145 } else if(strcmp(optarg, "link-skeletons") == 0) {
146 asn1_compiler_flags |= A1C_LINK_SKELETONS;
147 } else {
148 fprintf(stderr, "-f%s: Invalid argument\n", optarg);
149 exit(EX_USAGE);
150 }
151 break;
152 case 'g':
153 if(strcmp(optarg, "en-PER") == 0) {
154 asn1_compiler_flags |= A1C_GEN_PER;
Lev Walkinba68c912017-07-06 07:52:39 -0700155 } else if(strcmp(optarg, "en-OER") == 0) {
156 asn1_compiler_flags |= A1C_GEN_OER;
Lev Walkind1c28aa2017-11-11 18:04:26 -0800157 } else if(strcmp(optarg, "en-example") == 0) {
158 asn1_compiler_flags |= A1C_GEN_EXAMPLE;
Jon Ringle3aa33c02017-11-14 11:16:03 -0500159 } else if(strcmp(optarg, "en-autotools") == 0) {
160 asn1_compiler_flags |= A1C_GEN_AUTOTOOLS_EXAMPLE;
Lev Walkin41a1da62016-01-23 08:50:28 -0800161 } else {
162 fprintf(stderr, "-g%s: Invalid argument\n", optarg);
163 exit(EX_USAGE);
164 }
165 break;
166 case 'h':
167 usage(av[0]);
Lev Walkind1c28aa2017-11-11 18:04:26 -0800168 case 'n':
169 if(strcmp(optarg, "o-gen-PER") == 0) {
170 asn1_compiler_flags &= ~A1C_GEN_PER;
171 } else if(strcmp(optarg, "o-gen-OER") == 0) {
172 asn1_compiler_flags &= ~A1C_GEN_OER;
173 } else if(strcmp(optarg, "o-gen-example") == 0) {
174 asn1_compiler_flags &= ~A1C_GEN_EXAMPLE;
Jon Ringle3aa33c02017-11-14 11:16:03 -0500175 } else if(strcmp(optarg, "o-gen-autotools") == 0) {
176 asn1_compiler_flags &= ~A1C_GEN_AUTOTOOLS_EXAMPLE;
Lev Walkind1c28aa2017-11-11 18:04:26 -0800177 } else {
178 fprintf(stderr, "-n%s: Invalid argument\n", optarg);
179 exit(EX_USAGE);
180 }
181 break;
Lev Walkin41a1da62016-01-23 08:50:28 -0800182 case 'P':
183 asn1_compiler_flags |= A1C_PRINT_COMPILED;
184 asn1_compiler_flags &= ~A1C_NO_C99;
185 break;
186 case 'p':
187 if(strncmp(optarg, "du=", 3) == 0) {
188 char *pduname = optarg + 3;
189 if(strcmp(pduname, "all") == 0) {
190 asn1_compiler_flags |= A1C_PDU_ALL;
191 } else if(strcmp(pduname, "auto") == 0) {
192 asn1_compiler_flags |= A1C_PDU_AUTO;
193 } else if(pduname[0] >= 'A' && pduname[0] <= 'Z') {
194 asn1c__add_pdu_type(pduname);
195 asn1_compiler_flags |= A1C_PDU_TYPE;
196 } else {
197 fprintf(stderr, "-pdu=%s: expected -pdu={all|auto|Type}\n",
198 pduname);
199 exit(EX_USAGE);
200 }
201 } else if(strcmp(optarg, "rint-class-matrix") == 0) {
202 asn1_printer_flags |= APF_PRINT_CLASS_MATRIX;
203 } else if(strcmp(optarg, "rint-constraints") == 0) {
204 asn1_printer_flags |= APF_PRINT_CONSTRAINTS;
205 } else if(strcmp(optarg, "rint-lines") == 0) {
206 asn1_printer_flags |= APF_LINE_COMMENTS;
207 } else {
208 fprintf(stderr, "-p%s: Invalid argument\n", optarg);
209 exit(EX_USAGE);
210 }
211 break;
212 case 'R':
213 asn1_compiler_flags |= A1C_OMIT_SUPPORT_CODE;
214 break;
215 case 'S':
216 skeletons_dir = optarg;
217 break;
218 case 'v':
219 fprintf(stderr, "ASN.1 Compiler, v" VERSION "\n" COPYRIGHT);
220 exit(0);
221 break;
222 case 'W':
223 if(strcmp(optarg, "error") == 0) {
224 warnings_as_errors = 1;
225 break;
226 } else if(strcmp(optarg, "debug-lexer") == 0) {
Lev Walkin0c686452017-09-07 22:59:36 -0700227 asn1_parser_flags |= A1P_DEBUG_LEXER;
228 break;
229 } else if(strcmp(optarg, "debug-parser") == 0) {
230 asn1_parser_flags |= A1P_DEBUG_PARSER;
Lev Walkin41a1da62016-01-23 08:50:28 -0800231 break;
232 } else if(strcmp(optarg, "debug-fixer") == 0) {
233 asn1_fixer_flags |= A1F_DEBUG;
234 break;
235 } else if(strcmp(optarg, "debug-compiler") == 0) {
236 asn1_compiler_flags |= A1C_DEBUG;
237 break;
238 } else {
239 fprintf(stderr, "-W%s: Invalid argument\n", optarg);
240 exit(EX_USAGE);
241 }
242 break;
243 case 'X':
244 print_arg__print_out = 1; /* Implicit -E */
245 print_arg__fix_n_print = 1; /* Implicit -F */
246 asn1_printer_flags |= APF_PRINT_XML_DTD;
247 break;
248 default:
249 usage(av[0]);
250 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000251
Lev Walkin41a1da62016-01-23 08:50:28 -0800252 /*
253 * Validate the options combination.
254 */
Lev Walkin6f50a3f2017-07-26 18:46:55 -0700255 if(print_arg__print_out) {
256 if((asn1_printer_flags & APF_PRINT_CONSTRAINTS)
257 && !print_arg__fix_n_print) {
258 fprintf(stderr,
259 "Error: -print-constraints argument requires -E -F\n");
260 exit(EX_USAGE);
261 }
262 } else {
Lev Walkin41a1da62016-01-23 08:50:28 -0800263 if(print_arg__fix_n_print) {
264 fprintf(stderr, "Error: -F requires -E\n");
265 exit(EX_USAGE);
266 }
267 if(asn1_printer_flags) {
268 fprintf(stderr, "Error: -print-... arguments require -E\n");
269 exit(EX_USAGE);
270 }
271 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000272
Lev Walkin41a1da62016-01-23 08:50:28 -0800273 /*
274 * Ensure that there are some input files present.
275 */
276 if(ac > optind) {
277 ac -= optind;
278 av += optind;
279 } else {
Jon Ringle6431b1c2017-11-15 01:22:02 -0500280 const char *bin_name = a1c_basename(av[0], NULL);
Lev Walkin41a1da62016-01-23 08:50:28 -0800281 fprintf(stderr,
282 "%s: No input files specified. "
283 "Try '%s -h' for more information\n",
284 bin_name, bin_name);
285 exit(1);
286 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000287
Lev Walkin41a1da62016-01-23 08:50:28 -0800288 /*
289 * Make sure the skeleton directory is out there.
290 */
291 if(skeletons_dir == NULL) {
292 struct stat sb;
293 skeletons_dir = DATADIR;
294 if((av[-optind][0] == '.' || av[-optind][1] == '/')
295 && stat(skeletons_dir, &sb)) {
296 /*
297 * The default skeletons directory does not exist,
298 * compute it from my file name:
299 * ./asn1c/asn1c -> ./skeletons
300 */
Lev Walkina4f8e942017-10-08 19:28:20 -0700301 const char *skel_dir;
Lev Walkin41a1da62016-01-23 08:50:28 -0800302 size_t len;
Lev Walkin46499872006-03-06 13:05:34 +0000303
Lev Walkina4f8e942017-10-08 19:28:20 -0700304 skel_dir = a1c_dirname(av[-optind]);
Lev Walkin46499872006-03-06 13:05:34 +0000305
Lev Walkina4f8e942017-10-08 19:28:20 -0700306 len = strlen(skel_dir) + sizeof("/../skeletons");
Lev Walkin41a1da62016-01-23 08:50:28 -0800307 skeletons_dir = malloc(len);
308 assert(skeletons_dir);
Lev Walkina4f8e942017-10-08 19:28:20 -0700309 snprintf(skeletons_dir, len, "%s/../skeletons", skel_dir);
Lev Walkin41a1da62016-01-23 08:50:28 -0800310 if(stat(skeletons_dir, &sb)) {
311 fprintf(stderr,
312 "WARNING: skeletons are neither in "
313 "\"%s\" nor in \"%s\"!\n",
314 DATADIR, skeletons_dir);
315 if(warnings_as_errors) exit(EX_OSFILE);
316 }
317 }
318 }
Lev Walkin46499872006-03-06 13:05:34 +0000319
Lev Walkin41a1da62016-01-23 08:50:28 -0800320 /*
321 * Iterate over input files and parse each.
322 * All syntax trees from all files will be bundled together.
323 */
324 for(i = 0; i < ac; i++) {
325 asn1p_t *new_asn;
Lev Walkinf15320b2004-06-03 03:38:44 +0000326
Lev Walkin41a1da62016-01-23 08:50:28 -0800327 new_asn = asn1p_parse_file(av[i], asn1_parser_flags);
328 if(new_asn == NULL) {
329 fprintf(stderr, "Cannot parse \"%s\"\n", av[i]);
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800330 exit_code = EX_DATAERR;
331 goto cleanup;
Lev Walkin41a1da62016-01-23 08:50:28 -0800332 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000333
Lev Walkin41a1da62016-01-23 08:50:28 -0800334 /*
335 * Bundle the parsed tree with existing one.
336 */
337 if(asn) {
338 asn1p_module_t *mod;
339 while((mod = TQ_REMOVE(&(new_asn->modules), mod_next)))
340 TQ_ADD(&(asn->modules), mod, mod_next);
341 asn1p_delete(new_asn);
342 } else {
343 asn = new_asn;
344 }
345 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000346
Lev Walkin41a1da62016-01-23 08:50:28 -0800347 /* These are mostly notes for the human readers */
348 assert(asn);
349 assert(skeletons_dir);
Lev Walkin46499872006-03-06 13:05:34 +0000350
Lev Walkin41a1da62016-01-23 08:50:28 -0800351 /*
352 * Dump the parsed ASN.1 tree if -E specified and -F is NOT given.
353 */
354 if(print_arg__print_out && !print_arg__fix_n_print) {
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800355 if(asn1print(asn, asn1_printer_flags)) {
356 exit_code = EX_SOFTWARE;
357 goto cleanup;
358 }
Lev Walkin41a1da62016-01-23 08:50:28 -0800359 return 0;
360 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000361
Lev Walkin41a1da62016-01-23 08:50:28 -0800362 /*
363 * Read in the files from skeletons/standard-modules
364 */
365 if(importStandardModules(asn, skeletons_dir)) {
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800366 if(warnings_as_errors) {
367 exit_code = EX_DATAERR;
368 goto cleanup;
369 }
Lev Walkinc0e03b92017-08-22 01:48:23 -0700370 } else {
371 asn1f_use_standard_namespaces(asn);
Lev Walkin41a1da62016-01-23 08:50:28 -0800372 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000373
Lev Walkin41a1da62016-01-23 08:50:28 -0800374 /*
375 * Process the ASN.1 specification: perform semantic checks,
376 * expand references, etc, etc.
377 * This function will emit necessary warnings and error messages.
378 */
379 ret = asn1f_process(asn, asn1_fixer_flags,
380 NULL /* default fprintf(stderr) */);
381 switch(ret) {
Lev Walkin48e82d12017-10-19 03:06:35 -0700382 case 0:
Lev Walkin41a1da62016-01-23 08:50:28 -0800383 break; /* All clear */
Lev Walkin48e82d12017-10-19 03:06:35 -0700384 case 1:
385 if(!warnings_as_errors) {
386 break;
387 }
388 /* Fall through */
Lev Walkin41a1da62016-01-23 08:50:28 -0800389 case -1:
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800390 exit_code = EX_DATAERR; /* Fatal failure */
391 goto cleanup;
Lev Walkin41a1da62016-01-23 08:50:28 -0800392 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000393
Lev Walkin41a1da62016-01-23 08:50:28 -0800394 /*
395 * Dump the parsed ASN.1 tree if -E specified and -F is given.
396 */
397 if(print_arg__print_out && print_arg__fix_n_print) {
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800398 if(asn1print(asn, asn1_printer_flags)) {
399 exit_code = EX_SOFTWARE;
400 goto cleanup;
401 }
Lev Walkin41a1da62016-01-23 08:50:28 -0800402 return 0;
403 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000404
Lev Walkin41a1da62016-01-23 08:50:28 -0800405 /*
Lev Walkin4215c512017-11-19 19:01:26 -0800406 * -debug-type-naming=Type
407 */
408 if(debug_type_names) {
409 asn1c_debug_type_naming(asn, asn1_compiler_flags, debug_type_names);
410 return 0;
411 }
412
413 /*
Lev Walkin41a1da62016-01-23 08:50:28 -0800414 * Compile the ASN.1 tree into a set of source files
415 * of another language.
416 */
Lev Walkin4645db02017-11-18 11:32:07 -0800417 if(asn1_compile(asn, skeletons_dir, destdir ? destdir : "",
418 asn1_compiler_flags, ac + optind, optind, av - optind)) {
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800419 exit_code = EX_SOFTWARE;
Lev Walkin41a1da62016-01-23 08:50:28 -0800420 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000421
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800422cleanup:
Bi-Ruei, Chiub9adfc52016-11-09 00:17:25 +0800423 asn1p_delete(asn);
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800424 asn1p_lex_destroy();
425 if (exit_code) exit(exit_code);
Bi-Ruei, Chiub9adfc52016-11-09 00:17:25 +0800426
Lev Walkin41a1da62016-01-23 08:50:28 -0800427 return 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000428}
429
430/*
Lev Walkin46499872006-03-06 13:05:34 +0000431 * Parse and import *.asn1 from skeletons/standard-modules
432 */
433static int
434importStandardModules(asn1p_t *asn, const char *skeletons_dir) {
Lev Walkin41a1da62016-01-23 08:50:28 -0800435 asn1p_t *new_asn;
436 asn1p_module_t *mod;
437 const char *filename;
438 char *fullname;
439 char *target_dir;
440 int target_dir_len;
441 int len;
442#ifdef _WIN32
443 intptr_t dir;
444 struct _finddata_t c_file;
445 char *pattern;
Lev Walkin46499872006-03-06 13:05:34 +0000446#else
Lev Walkin41a1da62016-01-23 08:50:28 -0800447 struct dirent *dp;
448 DIR *dir;
Lev Walkin46499872006-03-06 13:05:34 +0000449#endif
Lev Walkin41a1da62016-01-23 08:50:28 -0800450 int ret = 0;
Lev Walkin46499872006-03-06 13:05:34 +0000451
Lev Walkin41a1da62016-01-23 08:50:28 -0800452 /* Notes for the human reader */
453 assert(asn);
454 assert(skeletons_dir);
Lev Walkin46499872006-03-06 13:05:34 +0000455
Lev Walkin41a1da62016-01-23 08:50:28 -0800456 /*
457 * Figure out the standard-modules directory.
458 */
459 target_dir_len = strlen(skeletons_dir) + sizeof("/standard-modules") - 1;
460 target_dir = malloc(target_dir_len + 1);
461 assert(target_dir);
462 snprintf(target_dir, target_dir_len + 1, "%s/standard-modules",
463 skeletons_dir);
Lev Walkin46499872006-03-06 13:05:34 +0000464
Lev Walkin41a1da62016-01-23 08:50:28 -0800465#ifdef _WIN32
466 len = target_dir_len + sizeof("/*.asn1");
467 pattern = malloc(len);
468 assert(pattern);
469 snprintf(pattern, len, "%s/*.asn1", target_dir);
470 dir = _findfirst(pattern, &c_file);
471 if(dir == -1L) {
Lev Walkin46499872006-03-06 13:05:34 +0000472#else
Lev Walkin41a1da62016-01-23 08:50:28 -0800473 dir = opendir(target_dir);
474 if(!dir) {
Lev Walkin46499872006-03-06 13:05:34 +0000475#endif
Lev Walkin41a1da62016-01-23 08:50:28 -0800476 fprintf(stderr, "WARNING: Cannot find standard modules in %s\n",
477 target_dir);
478 return -1;
479 }
Lev Walkin46499872006-03-06 13:05:34 +0000480
Lev Walkin41a1da62016-01-23 08:50:28 -0800481#ifdef _WIN32
482 do {
483 filename = c_file.name;
Lev Walkin46499872006-03-06 13:05:34 +0000484#else
Lev Walkin41a1da62016-01-23 08:50:28 -0800485 while((dp = readdir(dir))) {
486 filename = dp->d_name;
Lev Walkin20a7bf42006-03-17 00:20:52 +0000487#endif
Lev Walkin41a1da62016-01-23 08:50:28 -0800488 len = strlen(filename);
489 if(len <= 5 || strcmp(filename + len - 5, ".asn1")) continue;
490 len = target_dir_len + 1 + len + 1;
491 fullname = malloc(len);
492 if(!fullname) continue; /* Just skip it, no big deal */
493 snprintf(fullname, len, "%s/%s", target_dir, filename);
494 filename = fullname;
Lev Walkin46499872006-03-06 13:05:34 +0000495
Lev Walkin41a1da62016-01-23 08:50:28 -0800496 new_asn = asn1p_parse_file(filename, A1P_NOFLAGS);
497 if(new_asn == NULL) {
498 fprintf(stderr, "WARNING: Cannot parse standard module \"%s\"\n",
499 filename);
500 ret = -1;
501 continue;
502 }
Lev Walkin46499872006-03-06 13:05:34 +0000503
Lev Walkin41a1da62016-01-23 08:50:28 -0800504 /* Import these modules and mark them as "standard" */
505 while((mod = TQ_REMOVE(&(new_asn->modules), mod_next))) {
506 mod->_tags |= MT_STANDARD_MODULE;
507 TQ_ADD(&(asn->modules), mod, mod_next);
508 }
509 asn1p_delete(new_asn);
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800510 asn1p_lex_destroy();
Lev Walkin46499872006-03-06 13:05:34 +0000511
Lev Walkin41a1da62016-01-23 08:50:28 -0800512#ifdef _WIN32
513 } while(_findnext(dir, &c_file) == 0);
514 _findclose(dir);
Lev Walkin46499872006-03-06 13:05:34 +0000515#else
Lev Walkin41a1da62016-01-23 08:50:28 -0800516 free(fullname);
517 } /* while(readdir()) */
518 closedir(dir);
Lev Walkin46499872006-03-06 13:05:34 +0000519#endif
520
Bi-Ruei, Chiu4661dae2016-11-09 00:59:41 +0800521#ifdef _WIN32
522 free(pattern);
523#endif
524 free(target_dir);
525
Lev Walkin41a1da62016-01-23 08:50:28 -0800526 return ret;
Lev Walkin46499872006-03-06 13:05:34 +0000527}
528
529/*
Lev Walkinf15320b2004-06-03 03:38:44 +0000530 * Print the usage screen and exit(EX_USAGE).
531 */
Lev Walkin48e82d12017-10-19 03:06:35 -0700532static void __attribute__((noreturn))
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000533usage(const char *av0) {
Lev Walkin41a1da62016-01-23 08:50:28 -0800534 /* clang-format off */
Lev Walkinf15320b2004-06-03 03:38:44 +0000535 fprintf(stderr,
Lev Walkincbf218f2004-08-20 13:24:38 +0000536"ASN.1 Compiler, v" VERSION "\n" COPYRIGHT
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000537"Usage: %s [options] file ...\n"
538"Options:\n"
Lev Walkincbf218f2004-08-20 13:24:38 +0000539" -E Run only the ASN.1 parser and print out the tree\n"
540" -F During -E operation, also perform tree fixing\n"
541"\n"
542" -P Concatenate and print the compiled text\n"
543" -R Restrict output (tables only, no support code)\n"
544" -S <dir> Directory with support (skeleton?) files\n"
545" (Default is \"%s\")\n"
Jon Ringle6431b1c2017-11-15 01:22:02 -0500546" -D <dir> Destination directory for generated files (default current dir)\n"
Lev Walkinf7484512004-10-13 09:13:56 +0000547" -X Generate and print the XML DTD\n"
Lev Walkincbf218f2004-08-20 13:24:38 +0000548"\n"
549
Lev Walkincbf218f2004-08-20 13:24:38 +0000550" -Werror Treat warnings as errors; abort if any warning\n"
551" -Wdebug-lexer Enable verbose debugging output from lexer\n"
Lev Walkin0c686452017-09-07 22:59:36 -0700552" -Wdebug-parser Enable verbose debugging output from parser\n"
Lev Walkincbf218f2004-08-20 13:24:38 +0000553" -Wdebug-fixer --//-- semantics processor\n"
554" -Wdebug-compiler --//-- compiler\n"
555"\n"
556
557" -fbless-SIZE Allow SIZE() constraint for INTEGER etc (non-std.)\n"
Lev Walkin21d00002005-03-04 08:48:53 +0000558" -fcompound-names Disambiguate C's struct NAME's inside top-level types\n"
Lev Walkin72a0f5a2005-07-24 08:28:39 +0000559" -findirect-choice Compile members of CHOICE as indirect pointers\n"
Lev Walkin34944f22010-10-07 08:25:37 +0000560" -fincludes-quoted Generate #includes in \"double\" instead of <angle> quotes\n"
Lev Walkin7c655122005-06-05 09:42:42 +0000561" -fknown-extern-type=<name> Pretend the specified type is known\n"
Lev Walkin4062b012013-10-11 14:29:38 -0700562" -fline-refs Include ASN.1 module's line numbers in comments\n"
Lev Walkind1c28aa2017-11-11 18:04:26 -0800563" -fno-constraints Do not generate the constraint checking code\n"
564" -fno-include-deps Do not generate the courtesy #includes for dependencies\n"
Lev Walkincbf218f2004-08-20 13:24:38 +0000565" -funnamed-unions Enable unnamed unions in structures\n"
Lev Walkin2a744a72013-03-27 01:56:23 -0700566" -fwide-types Use INTEGER_t instead of \"long\" by default, etc.\n"
Lev Walkin59b176e2005-11-26 11:25:14 +0000567"\n"
568
Lev Walkind1c28aa2017-11-11 18:04:26 -0800569" -no-gen-OER Do not generate the OER (X.696) support code\n"
570" -no-gen-PER Do not generate the PER (X.691) support code\n"
571" -no-gen-example Do not generate the ASN.1 format converter example\n"
Jon Ringle3aa33c02017-11-14 11:16:03 -0500572" -gen-autotools Generate example top-level configure.ac and Makefile.am\n"
Lev Walkin66adab42006-09-23 02:52:12 +0000573" -pdu={all|auto|Type} Generate PDU table (discover PDUs automatically)\n"
Lev Walkincbf218f2004-08-20 13:24:38 +0000574"\n"
575
Lev Walkind370e9f2006-03-16 10:03:35 +0000576" -print-class-matrix Print out the collected object class matrix (debug)\n"
Lev Walkindafd95d2006-03-18 06:13:57 +0000577" -print-constraints Explain subtype constraints (debug)\n"
Lev Walkincbf218f2004-08-20 13:24:38 +0000578" -print-lines Generate \"-- #line\" comments in -E output\n"
579
Lev Walkinab4bb292004-08-18 04:52:48 +0000580 ,
Jon Ringle6431b1c2017-11-15 01:22:02 -0500581 a1c_basename(av0, NULL), DATADIR);
Lev Walkin41a1da62016-01-23 08:50:28 -0800582 /* clang-format on */
583 exit(EX_USAGE);
Lev Walkinf15320b2004-06-03 03:38:44 +0000584}