diff options
Diffstat (limited to 'scripts/asn1_compiler.c')
-rw-r--r-- | scripts/asn1_compiler.c | 248 |
1 files changed, 154 insertions, 94 deletions
diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c index 7750e9c..e000f44 100644 --- a/scripts/asn1_compiler.c +++ b/scripts/asn1_compiler.c @@ -13,6 +13,7 @@ #include <stdio.h> #include <stdlib.h> #include <stdint.h> +#include <stdbool.h> #include <string.h> #include <ctype.h> #include <unistd.h> @@ -293,8 +294,8 @@ static const char *const directives[NR__DIRECTIVES] = { struct action { struct action *next; + char *name; unsigned char index; - char name[]; }; static struct action *action_list; @@ -305,15 +306,17 @@ struct token { enum token_type token_type : 8; unsigned char size; struct action *action; - const char *value; + char *content; struct type *type; }; static struct token *token_list; static unsigned nr_tokens; -static _Bool verbose; +static bool verbose_opt; +static bool debug_opt; -#define debug(fmt, ...) do { if (verbose) printf(fmt, ## __VA_ARGS__); } while (0) +#define verbose(fmt, ...) do { if (verbose_opt) printf(fmt, ## __VA_ARGS__); } while (0) +#define debug(fmt, ...) do { if (debug_opt) printf(fmt, ## __VA_ARGS__); } while (0) static int directive_compare(const void *_key, const void *_pdir) { @@ -325,11 +328,9 @@ static int directive_compare(const void *_key, const void *_pdir) dlen = strlen(dir); clen = (dlen < token->size) ? dlen : token->size; - //debug("cmp(%*.*s,%s) = ", - // (int)token->size, (int)token->size, token->value, - // dir); + //debug("cmp(%s,%s) = ", token->content, dir); - val = memcmp(token->value, dir, clen); + val = memcmp(token->content, dir, clen); if (val != 0) { //debug("%d [cmp]\n", val); return val; @@ -349,7 +350,7 @@ static int directive_compare(const void *_key, const void *_pdir) static void tokenise(char *buffer, char *end) { struct token *tokens; - char *line, *nl, *p, *q; + char *line, *nl, *start, *p, *q; unsigned tix, lineno; /* Assume we're going to have half as many tokens as we have @@ -408,11 +409,11 @@ static void tokenise(char *buffer, char *end) break; tokens[tix].line = lineno; - tokens[tix].value = p; + start = p; /* Handle string tokens */ if (isalpha(*p)) { - const char **dir; + const char **dir, *start = p; /* Can be a directive, type name or element * name. Find the end of the name. @@ -423,10 +424,18 @@ static void tokenise(char *buffer, char *end) tokens[tix].size = q - p; p = q; + tokens[tix].content = malloc(tokens[tix].size + 1); + if (!tokens[tix].content) { + perror(NULL); + exit(1); + } + memcpy(tokens[tix].content, start, tokens[tix].size); + tokens[tix].content[tokens[tix].size] = 0; + /* If it begins with a lowercase letter then * it's an element name */ - if (islower(tokens[tix].value[0])) { + if (islower(tokens[tix].content[0])) { tokens[tix++].token_type = TOKEN_ELEMENT_NAME; continue; } @@ -455,6 +464,13 @@ static void tokenise(char *buffer, char *end) q++; tokens[tix].size = q - p; p = q; + tokens[tix].content = malloc(tokens[tix].size + 1); + if (!tokens[tix].content) { + perror(NULL); + exit(1); + } + memcpy(tokens[tix].content, start, tokens[tix].size); + tokens[tix].content[tokens[tix].size] = 0; tokens[tix++].token_type = TOKEN_NUMBER; continue; } @@ -463,6 +479,7 @@ static void tokenise(char *buffer, char *end) if (memcmp(p, "::=", 3) == 0) { p += 3; tokens[tix].size = 3; + tokens[tix].content = "::="; tokens[tix++].token_type = TOKEN_ASSIGNMENT; continue; } @@ -472,12 +489,14 @@ static void tokenise(char *buffer, char *end) if (memcmp(p, "({", 2) == 0) { p += 2; tokens[tix].size = 2; + tokens[tix].content = "({"; tokens[tix++].token_type = TOKEN_OPEN_ACTION; continue; } if (memcmp(p, "})", 2) == 0) { p += 2; tokens[tix].size = 2; + tokens[tix].content = "})"; tokens[tix++].token_type = TOKEN_CLOSE_ACTION; continue; } @@ -488,22 +507,27 @@ static void tokenise(char *buffer, char *end) switch (*p) { case '{': p += 1; + tokens[tix].content = "{"; tokens[tix++].token_type = TOKEN_OPEN_CURLY; continue; case '}': p += 1; + tokens[tix].content = "}"; tokens[tix++].token_type = TOKEN_CLOSE_CURLY; continue; case '[': p += 1; + tokens[tix].content = "["; tokens[tix++].token_type = TOKEN_OPEN_SQUARE; continue; case ']': p += 1; + tokens[tix].content = "]"; tokens[tix++].token_type = TOKEN_CLOSE_SQUARE; continue; case ',': p += 1; + tokens[tix].content = ","; tokens[tix++].token_type = TOKEN_COMMA; continue; default: @@ -518,22 +542,20 @@ static void tokenise(char *buffer, char *end) } nr_tokens = tix; - debug("Extracted %u tokens\n", nr_tokens); + verbose("Extracted %u tokens\n", nr_tokens); #if 0 { int n; for (n = 0; n < nr_tokens; n++) - debug("Token %3u: '%*.*s'\n", - n, - (int)token_list[n].size, (int)token_list[n].size, - token_list[n].value); + debug("Token %3u: '%s'\n", n, token_list[n].content); } #endif } static void build_type_list(void); static void parse(void); +static void dump_elements(void); static void render(FILE *out, FILE *hdr); /* @@ -548,16 +570,27 @@ int main(int argc, char **argv) char *kbuild_verbose; int fd; + kbuild_verbose = getenv("KBUILD_VERBOSE"); + if (kbuild_verbose) + verbose_opt = atoi(kbuild_verbose); + + while (argc > 4) { + if (strcmp(argv[1], "-v") == 0) + verbose_opt = true; + else if (strcmp(argv[1], "-d") == 0) + debug_opt = true; + else + break; + memmove(&argv[1], &argv[2], (argc - 2) * sizeof(char *)); + argc--; + } + if (argc != 4) { - fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n", + fprintf(stderr, "Format: %s [-v] [-d] <grammar-file> <c-file> <hdr-file>\n", argv[0]); exit(2); } - kbuild_verbose = getenv("KBUILD_VERBOSE"); - if (kbuild_verbose) - verbose = atoi(kbuild_verbose); - filename = argv[1]; outputname = argv[2]; headername = argv[3]; @@ -608,6 +641,7 @@ int main(int argc, char **argv) tokenise(buffer, buffer + readlen); build_type_list(); parse(); + dump_elements(); out = fopen(outputname, "w"); if (!out) { @@ -666,7 +700,7 @@ struct element { unsigned flags; #define ELEMENT_IMPLICIT 0x0001 #define ELEMENT_EXPLICIT 0x0002 -#define ELEMENT_MARKED 0x0004 +#define ELEMENT_TAG_SPECIFIED 0x0004 #define ELEMENT_RENDERED 0x0008 #define ELEMENT_SKIPPABLE 0x0010 #define ELEMENT_CONDITIONAL 0x0020 @@ -693,7 +727,7 @@ static int type_index_compare(const void *_a, const void *_b) if ((*a)->name->size != (*b)->name->size) return (*a)->name->size - (*b)->name->size; else - return memcmp((*a)->name->value, (*b)->name->value, + return memcmp((*a)->name->content, (*b)->name->content, (*a)->name->size); } @@ -706,7 +740,7 @@ static int type_finder(const void *_key, const void *_ti) if (token->size != type->name->size) return token->size - type->name->size; else - return memcmp(token->value, type->name->value, + return memcmp(token->content, type->name->content, token->size); } @@ -756,14 +790,11 @@ static void build_type_list(void) qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); - debug("Extracted %u types\n", nr_types); + verbose("Extracted %u types\n", nr_types); #if 0 for (n = 0; n < nr_types; n++) { struct type *type = type_index[n]; - debug("- %*.*s\n", - (int)type->name->size, - (int)type->name->size, - type->name->value); + debug("- %*.*s\n", type->name->content); } #endif } @@ -793,15 +824,14 @@ static void parse(void) type->element->type_def = type; if (cursor != type[1].name) { - fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n", - filename, cursor->line, - (int)cursor->size, (int)cursor->size, cursor->value); + fprintf(stderr, "%s:%d: Parse error at token '%s'\n", + filename, cursor->line, cursor->content); exit(1); } } while (type++, !(type->flags & TYPE_STOP_MARKER)); - debug("Extracted %u actions\n", nr_actions); + verbose("Extracted %u actions\n", nr_actions); } static struct element *element_list; @@ -862,33 +892,31 @@ static struct element *parse_type(struct token **_cursor, struct token *end, cursor++; break; default: - fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n", - filename, cursor->line, - (int)cursor->size, (int)cursor->size, cursor->value); + fprintf(stderr, "%s:%d: Unrecognised tag class token '%s'\n", + filename, cursor->line, cursor->content); exit(1); } if (cursor >= end) goto overrun_error; if (cursor->token_type != TOKEN_NUMBER) { - fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n", - filename, cursor->line, - (int)cursor->size, (int)cursor->size, cursor->value); + fprintf(stderr, "%s:%d: Missing tag number '%s'\n", + filename, cursor->line, cursor->content); exit(1); } element->tag &= ~0x1f; - element->tag |= strtoul(cursor->value, &p, 10); - if (p - cursor->value != cursor->size) + element->tag |= strtoul(cursor->content, &p, 10); + element->flags |= ELEMENT_TAG_SPECIFIED; + if (p - cursor->content != cursor->size) abort(); cursor++; if (cursor >= end) goto overrun_error; if (cursor->token_type != TOKEN_CLOSE_SQUARE) { - fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n", - filename, cursor->line, - (int)cursor->size, (int)cursor->size, cursor->value); + fprintf(stderr, "%s:%d: Missing closing square bracket '%s'\n", + filename, cursor->line, cursor->content); exit(1); } cursor++; @@ -988,9 +1016,8 @@ static struct element *parse_type(struct token **_cursor, struct token *end, ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]), type_finder); if (!ref) { - fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n", - filename, cursor->line, - (int)cursor->size, (int)cursor->size, cursor->value); + fprintf(stderr, "%s:%d: Type '%s' undefined\n", + filename, cursor->line, cursor->content); exit(1); } cursor->type = *ref; @@ -1039,9 +1066,8 @@ static struct element *parse_type(struct token **_cursor, struct token *end, break; default: - fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n", - filename, cursor->line, - (int)cursor->size, (int)cursor->size, cursor->value); + fprintf(stderr, "%s:%d: Token '%s' does not introduce a type\n", + filename, cursor->line, cursor->content); exit(1); } @@ -1058,20 +1084,18 @@ static struct element *parse_type(struct token **_cursor, struct token *end, if (cursor >= end) goto overrun_error; if (cursor->token_type != TOKEN_ELEMENT_NAME) { - fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n", - filename, cursor->line, - (int)cursor->size, (int)cursor->size, cursor->value); + fprintf(stderr, "%s:%d: Token '%s' is not an action function name\n", + filename, cursor->line, cursor->content); exit(1); } - action = malloc(sizeof(struct action) + cursor->size + 1); + action = malloc(sizeof(struct action)); if (!action) { perror(NULL); exit(1); } action->index = 0; - memcpy(action->name, cursor->value, cursor->size); - action->name[cursor->size] = 0; + action->name = cursor->content; for (ppaction = &action_list; *ppaction; @@ -1101,9 +1125,8 @@ static struct element *parse_type(struct token **_cursor, struct token *end, if (cursor >= end) goto overrun_error; if (cursor->token_type != TOKEN_CLOSE_ACTION) { - fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n", - filename, cursor->line, - (int)cursor->size, (int)cursor->size, cursor->value); + fprintf(stderr, "%s:%d: Missing close action, got '%s'\n", + filename, cursor->line, cursor->content); exit(1); } cursor++; @@ -1113,9 +1136,8 @@ static struct element *parse_type(struct token **_cursor, struct token *end, return top; parse_error: - fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n", - filename, cursor->line, - (int)cursor->size, (int)cursor->size, cursor->value); + fprintf(stderr, "%s:%d: Unexpected token '%s'\n", + filename, cursor->line, cursor->content); exit(1); overrun_error: @@ -1133,9 +1155,8 @@ static struct element *parse_compound(struct token **_cursor, struct token *end, struct token *cursor = *_cursor, *name; if (cursor->token_type != TOKEN_OPEN_CURLY) { - fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n", - filename, cursor->line, - (int)cursor->size, (int)cursor->size, cursor->value); + fprintf(stderr, "%s:%d: Expected compound to start with brace not '%s'\n", + filename, cursor->line, cursor->content); exit(1); } cursor++; @@ -1176,9 +1197,8 @@ static struct element *parse_compound(struct token **_cursor, struct token *end, children->flags &= ~ELEMENT_CONDITIONAL; if (cursor->token_type != TOKEN_CLOSE_CURLY) { - fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n", - filename, cursor->line, - (int)cursor->size, (int)cursor->size, cursor->value); + fprintf(stderr, "%s:%d: Expected compound closure, got '%s'\n", + filename, cursor->line, cursor->content); exit(1); } cursor++; @@ -1191,6 +1211,52 @@ overrun_error: exit(1); } +static void dump_element(const struct element *e, int level) +{ + const struct element *c; + const struct type *t = e->type_def; + const char *name = e->name ? e->name->content : "."; + const char *tname = t && t->name ? t->name->content : "."; + char tag[32]; + + if (e->class == 0 && e->method == 0 && e->tag == 0) + strcpy(tag, "<...>"); + else if (e->class == ASN1_UNIV) + sprintf(tag, "%s %s %s", + asn1_classes[e->class], + asn1_methods[e->method], + asn1_universal_tags[e->tag]); + else + sprintf(tag, "%s %s %u", + asn1_classes[e->class], + asn1_methods[e->method], + e->tag); + + printf("%c%c%c%c%c %c %*s[*] \e[33m%s\e[m %s %s \e[35m%s\e[m\n", + e->flags & ELEMENT_IMPLICIT ? 'I' : '-', + e->flags & ELEMENT_EXPLICIT ? 'E' : '-', + e->flags & ELEMENT_TAG_SPECIFIED ? 'T' : '-', + e->flags & ELEMENT_SKIPPABLE ? 'S' : '-', + e->flags & ELEMENT_CONDITIONAL ? 'C' : '-', + "-tTqQcaro"[e->compound], + level, "", + tag, + tname, + name, + e->action ? e->action->name : ""); + if (e->compound == TYPE_REF) + dump_element(e->type->type->element, level + 3); + else + for (c = e->children; c; c = c->next) + dump_element(c, level + 3); +} + +static void dump_elements(void) +{ + if (debug_opt) + dump_element(type_list[0].element, 0); +} + static void render_element(FILE *out, struct element *e, struct element *tag); static void render_out_of_line_list(FILE *out); @@ -1292,7 +1358,7 @@ static void render(FILE *out, FILE *hdr) } /* We do two passes - the first one calculates all the offsets */ - debug("Pass 1\n"); + verbose("Pass 1\n"); nr_entries = 0; root = &type_list[0]; render_element(NULL, root->element, NULL); @@ -1303,7 +1369,7 @@ static void render(FILE *out, FILE *hdr) e->flags &= ~ELEMENT_RENDERED; /* And then we actually render */ - debug("Pass 2\n"); + verbose("Pass 2\n"); fprintf(out, "\n"); fprintf(out, "static const unsigned char %s_machine[] = {\n", grammar_name); @@ -1376,7 +1442,7 @@ static void render_out_of_line_list(FILE *out) */ static void render_element(FILE *out, struct element *e, struct element *tag) { - struct element *ec; + struct element *ec, *x; const char *cond, *act; int entry, skippable = 0, outofline = 0; @@ -1389,9 +1455,7 @@ static void render_element(FILE *out, struct element *e, struct element *tag) outofline = 1; if (e->type_def && out) { - render_more(out, "\t// %*.*s\n", - (int)e->type_def->name->size, (int)e->type_def->name->size, - e->type_def->name->value); + render_more(out, "\t// %s\n", e->type_def->name->content); } /* Render the operation */ @@ -1400,11 +1464,10 @@ static void render_element(FILE *out, struct element *e, struct element *tag) act = e->action ? "_ACT" : ""; switch (e->compound) { case ANY: - render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act); + render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,", + cond, act, skippable ? "_OR_SKIP" : ""); if (e->name) - render_more(out, "\t\t// %*.*s", - (int)e->name->size, (int)e->name->size, - e->name->value); + render_more(out, "\t\t// %s", e->name->content); render_more(out, "\n"); goto dont_render_tag; @@ -1435,15 +1498,15 @@ static void render_element(FILE *out, struct element *e, struct element *tag) break; } - if (e->name) - render_more(out, "\t\t// %*.*s", - (int)e->name->size, (int)e->name->size, - e->name->value); + x = tag ?: e; + if (x->name) + render_more(out, "\t\t// %s", x->name->content); render_more(out, "\n"); /* Render the tag */ - if (!tag) + if (!tag || !(tag->flags & ELEMENT_TAG_SPECIFIED)) tag = e; + if (tag->class == ASN1_UNIV && tag->tag != 14 && tag->tag != 15 && @@ -1465,7 +1528,8 @@ dont_render_tag: case TYPE_REF: render_element(out, e->type->type->element, tag); if (e->action) - render_opcode(out, "ASN1_OP_ACT,\n"); + render_opcode(out, "ASN1_OP_%sACT,\n", + skippable ? "MAYBE_" : ""); break; case SEQUENCE: @@ -1474,10 +1538,8 @@ dont_render_tag: * skipability */ render_opcode(out, "_jump_target(%u),", e->entry_index); if (e->type_def && e->type_def->name) - render_more(out, "\t\t// --> %*.*s", - (int)e->type_def->name->size, - (int)e->type_def->name->size, - e->type_def->name->value); + render_more(out, "\t\t// --> %s", + e->type_def->name->content); render_more(out, "\n"); if (!(e->flags & ELEMENT_RENDERED)) { e->flags |= ELEMENT_RENDERED; @@ -1502,10 +1564,8 @@ dont_render_tag: * skipability */ render_opcode(out, "_jump_target(%u),", e->entry_index); if (e->type_def && e->type_def->name) - render_more(out, "\t\t// --> %*.*s", - (int)e->type_def->name->size, - (int)e->type_def->name->size, - e->type_def->name->value); + render_more(out, "\t\t// --> %s", + e->type_def->name->content); render_more(out, "\n"); if (!(e->flags & ELEMENT_RENDERED)) { e->flags |= ELEMENT_RENDERED; @@ -1539,7 +1599,7 @@ dont_render_tag: case CHOICE: for (ec = e->children; ec; ec = ec->next) - render_element(out, ec, NULL); + render_element(out, ec, ec); if (!skippable) render_opcode(out, "ASN1_OP_COND_FAIL,\n"); if (e->action) |