asn1: Improve option handling; help msg

- Giving asn1_compile the name of an ASN.1 module w/o the ".asn1" stem
   will cause the compiler to add the ".asn1" stem, and it will cause
   the compiler to look for a ".opt" file as well.

 - The default C module name substring derivation from the .asn1 file
   name is improved.

 - There is now a --gen-name=NAME option for specifying the C module
   name substring.  This is useful for specifying that in a .opt file.

 - More options now have helpful usage messages.

This will allow simplification of lib/asn1/Makefile.am's invocations of
asn1_compile.

We may well end up requiring the automatic .opt file finding feature
when we eventualy add support for parsing multiple modules in a single
invocation for better support of IMPORTs.
This commit is contained in:
Nicolas Williams
2020-12-24 12:29:54 -06:00
parent 83d4c6ddb5
commit 24543c4a31

View File

@@ -60,8 +60,26 @@ seq_type(const char *p)
return 0; return 0;
} }
static const char *
my_basename(const char *fn)
{
const char *base, *p;
for (p = base = fn; *p; p++) {
#ifdef WIN32
if (*p == '/' || *p == '\\')
base = p + 1;
#else
if (*p == '/')
base = p + 1;
#endif
}
return base;
}
const char *fuzzer_string = ""; const char *fuzzer_string = "";
const char *enum_prefix; const char *enum_prefix;
const char *name;
int prefix_enum; int prefix_enum;
int fuzzer_flag; int fuzzer_flag;
int support_ber; int support_ber;
@@ -83,11 +101,18 @@ struct getargs args[] = {
{ "enum-prefix", 0, arg_string, &enum_prefix, { "enum-prefix", 0, arg_string, &enum_prefix,
"prefix for C enum labels for ENUMERATED types and INTEGER types with " "prefix for C enum labels for ENUMERATED types and INTEGER types with "
"enumerated values", "PREFIX" }, "enumerated values", "PREFIX" },
{ "encode-rfc1510-bit-string", 0, arg_flag, &rfc1510_bitstring, NULL, NULL }, { "encode-rfc1510-bit-string", 0, arg_flag, &rfc1510_bitstring,
{ "decode-dce-ber", 0, arg_flag, &support_ber, NULL, NULL }, "Use RFC1510 incorrect BIT STRING handling for all BIT STRING types "
{ "support-ber", 0, arg_flag, &support_ber, NULL, NULL }, "in the module", NULL },
{ "preserve-binary", 0, arg_strings, &preserve, NULL, NULL }, { "decode-dce-ber", 0, arg_flag, &support_ber,
{ "sequence", 0, arg_strings, &seq, NULL, NULL }, "Allow DCE-style BER on decode", NULL },
{ "support-ber", 0, arg_flag, &support_ber, "Allow BER on decode", NULL },
{ "preserve-binary", 0, arg_strings, &preserve,
"Names of types for which to generate _save fields, saving original "
"encoding, in containing structures (useful for signature "
"verification)", "TYPE-NAME" },
{ "sequence", 0, arg_strings, &seq,
"Generate add/remove functions for SEQUENCE OF types", "TYPE-NAME" },
{ "one-code-file", 0, arg_flag, &one_code_file, NULL, NULL }, { "one-code-file", 0, arg_flag, &one_code_file, NULL, NULL },
{ "gen-name", 0, arg_string, &name, { "gen-name", 0, arg_string, &name,
"Name of generated module", "NAME" }, "Name of generated module", "NAME" },
@@ -99,7 +124,9 @@ struct getargs args[] = {
"is useful for comparing output to earlier compiler versions.", "is useful for comparing output to earlier compiler versions.",
NULL }, NULL },
{ "parse-units", 0, arg_negative_flag, &parse_units_flag, NULL, NULL }, { "parse-units", 0, arg_negative_flag, &parse_units_flag, NULL, NULL },
{ "type-file", 0, arg_string, &type_file_string, NULL, NULL }, { "type-file", 0, arg_string, &type_file_string,
"Name of a C header file to generate includes of for base types",
"C-HEADER-FILE" },
{ "version", 0, arg_flag, &version_flag, NULL, NULL }, { "version", 0, arg_flag, &version_flag, NULL, NULL },
{ "help", 0, arg_flag, &help_flag, NULL, NULL } { "help", 0, arg_flag, &help_flag, NULL, NULL }
}; };
@@ -119,10 +146,12 @@ main(int argc, char **argv)
{ {
int ret; int ret;
const char *file; const char *file;
const char *name = NULL; FILE *opt = NULL;
int optidx = 0; int optidx = 0;
char **arg = NULL; char **arg = NULL;
int len = 0, i; size_t len = 0;
size_t sz = 0;
int i;
setprogname(argv[0]); setprogname(argv[0]);
if (getarg(args, num_args, argc, argv, &optidx)) if (getarg(args, num_args, argc, argv, &optidx))
@@ -134,17 +163,39 @@ main(int argc, char **argv)
exit(0); exit(0);
} }
if (argc == optidx) { if (argc == optidx) {
/* Compile the module on stdin */
file = "stdin"; file = "stdin";
name = "stdin"; name = "stdin";
yyin = stdin; yyin = stdin;
} else { } else {
/* Compile a named module */
file = argv[optidx]; file = argv[optidx];
/*
* If the .asn1 stem is not given, then assume it, and also assume
* --option-file was given if the .opt file exists
*/
if (strchr(file, '.') == NULL) {
char *s = NULL;
if (asprintf(&s, "%s.opt", file) == -1 || s == NULL)
err(1, "Out of memory");
if ((opt = fopen(s, "r")))
option_file = s;
else
free(s);
if (asprintf(&s, "%s.asn1", file) == -1 || s == NULL)
err(1, "Out of memory");
file = s;
}
yyin = fopen (file, "r"); yyin = fopen (file, "r");
if (yyin == NULL) if (yyin == NULL)
err (1, "open %s", file); err (1, "open %s", file);
if (argc == optidx + 1) { if (argc == optidx + 1) {
char *p; char *p;
name = estrdup(file);
/* C module name substring not given; derive from file name */
name = my_basename(estrdup(file));
p = strrchr(name, '.'); p = strrchr(name, '.');
if (p) if (p)
*p = '\0'; *p = '\0';
@@ -157,13 +208,10 @@ main(int argc, char **argv)
*/ */
if (option_file) { if (option_file) {
char buf[1024]; char buf[1024];
FILE *opt;
opt = fopen(option_file, "r"); if (opt == NULL &&
if (opt == NULL) { (opt = fopen(option_file, "r")) == NULL)
perror("open"); err(1, "Could not open given option file %s", option_file);
exit(1);
}
arg = calloc(2, sizeof(arg[0])); arg = calloc(2, sizeof(arg[0]));
if (arg == NULL) { if (arg == NULL) {
@@ -173,15 +221,19 @@ main(int argc, char **argv)
arg[0] = option_file; arg[0] = option_file;
arg[1] = NULL; arg[1] = NULL;
len = 1; len = 1;
sz = 2;
while (fgets(buf, sizeof(buf), opt) != NULL) { while (fgets(buf, sizeof(buf), opt) != NULL) {
buf[strcspn(buf, "\n\r")] = '\0'; buf[strcspn(buf, "\n\r")] = '\0';
arg = realloc(arg, (len + 2) * sizeof(arg[0])); if (len + 1 >= sz) {
arg = realloc(arg, (sz + (sz>>1) + 2) * sizeof(arg[0]));
if (arg == NULL) { if (arg == NULL) {
perror("malloc"); perror("malloc");
exit(1); exit(1);
} }
sz += (sz>>1) + 2;
}
arg[len] = strdup(buf); arg[len] = strdup(buf);
if (arg[len] == NULL) { if (arg[len] == NULL) {
perror("strdup"); perror("strdup");