From 8d9b21dcfe6814c92c9f445a7c742b7bab4f86b8 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Aug 2015 12:54:45 +0100 Subject: ASN.1: Fix handling of CHOICE in ASN.1 compiler Fix the handling of CHOICE types in the ASN.1 compiler to make SEQUENCE and SET elements in a CHOICE be correctly rendered as skippable and conditional as appropriate. For example, in the following ASN.1: Foo ::= SEQUENCE { w1 INTEGER, w2 Bar, w3 OBJECT IDENTIFIER } Bar ::= CHOICE { x1 Seq1, x2 [0] IMPLICIT OCTET STRING, x3 Seq2, x4 SET OF INTEGER } Seq1 ::= SEQUENCE { y1 INTEGER, y2 INTEGER, y3 INTEGER } Seq2 ::= SEQUENCE { z1 BOOLEAN, z2 BOOLEAN, z3 BOOLEAN } the output in foo.c generated by: ./scripts/asn1_compiler foo.asn1 foo.c foo.h included: // Bar // Seq1 [ 4] = ASN1_OP_MATCH, [ 5] = _tag(UNIV, CONS, SEQ), ... [ 13] = ASN1_OP_COND_MATCH_OR_SKIP, // x2 [ 14] = _tagn(CONT, PRIM, 0), // Seq2 [ 15] = ASN1_OP_MATCH, [ 16] = _tag(UNIV, CONS, SEQ), ... [ 24] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // x4 [ 25] = _tag(UNIV, CONS, SET), ... [ 27] = ASN1_OP_COND_FAIL, as a result of the CHOICE - but this is wrong on lines 4 and 15 because both of these should be skippable (one and only one of the four can be picked) and the one on line 15 should also be conditional so that it is ignored if anything before it matches. After the patch, it looks like: // Bar // Seq1 [ 4] = ASN1_OP_MATCH_JUMP_OR_SKIP, // x1 [ 5] = _tag(UNIV, CONS, SEQ), ... [ 7] = ASN1_OP_COND_MATCH_OR_SKIP, // x2 [ 8] = _tagn(CONT, PRIM, 0), // Seq2 [ 9] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // x3 [ 10] = _tag(UNIV, CONS, SEQ), ... [ 12] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // x4 [ 13] = _tag(UNIV, CONS, SET), ... [ 15] = ASN1_OP_COND_FAIL, where all four options are skippable and the second, third and fourth are all conditional, as is the backstop at the end. This hasn't been a problem so far because in the ASN.1 specs we have are either using primitives or are using SET OF and SEQUENCE OF which are handled correctly. Whilst we're at it, also make sure that element labels get included in comments in the output for elements that have complex types. This cannot be tested with the code as it stands, but rather affects future code. Signed-off-by: David Howells Reviewed-By: David Woodhouse --- scripts/asn1_compiler.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'scripts/asn1_compiler.c') diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c index 7750e9c31483..e87359cd23c0 100644 --- a/scripts/asn1_compiler.c +++ b/scripts/asn1_compiler.c @@ -666,7 +666,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 @@ -879,6 +879,7 @@ static struct element *parse_type(struct token **_cursor, struct token *end, element->tag &= ~0x1f; element->tag |= strtoul(cursor->value, &p, 10); + element->flags |= ELEMENT_TAG_SPECIFIED; if (p - cursor->value != cursor->size) abort(); cursor++; @@ -1376,7 +1377,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; @@ -1435,15 +1436,17 @@ static void render_element(FILE *out, struct element *e, struct element *tag) break; } - if (e->name) + x = tag ?: e; + if (x->name) render_more(out, "\t\t// %*.*s", - (int)e->name->size, (int)e->name->size, - e->name->value); + (int)x->name->size, (int)x->name->size, + x->name->value); 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 && @@ -1539,7 +1542,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) -- cgit v1.2.1 From 3f3af97d8225a58ecdcde7217c030b17e5198226 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Aug 2015 12:54:46 +0100 Subject: ASN.1: Fix actions on CHOICE elements with IMPLICIT tags In an ASN.1 description where there is a CHOICE construct that contains elements with IMPLICIT tags that refer to constructed types, actions to be taken on those elements should be conditional on the corresponding element actually being matched. Currently, however, such actions are performed unconditionally in the middle of processing the CHOICE. For example, look at elements 'b' and 'e' here: A ::= SEQUENCE { CHOICE { b [0] IMPLICIT B ({ do_XXXXXXXXXXXX_b }), c [1] EXPLICIT C ({ do_XXXXXXXXXXXX_c }), d [2] EXPLICIT B ({ do_XXXXXXXXXXXX_d }), e [3] IMPLICIT C ({ do_XXXXXXXXXXXX_e }), f [4] IMPLICIT INTEGER ({ do_XXXXXXXXXXXX_f }) } } ({ do_XXXXXXXXXXXX_A }) B ::= SET OF OBJECT IDENTIFIER ({ do_XXXXXXXXXXXX_oid }) C ::= SET OF INTEGER ({ do_XXXXXXXXXXXX_int }) They each have an action (do_XXXXXXXXXXXX_b and do_XXXXXXXXXXXX_e) that should only be processed if that element is matched. The problem is that there's no easy place to hang the action off in the subclause (type B for element 'b' and type C for element 'e') because subclause opcode sequences can be shared. To fix this, introduce a conditional action opcode(ASN1_OP_MAYBE_ACT) that the decoder only processes if the preceding match was successful. This can be seen in an excerpt from the output of the fixed ASN.1 compiler for the above ASN.1 description: [ 13] = ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // e [ 14] = _tagn(CONT, CONS, 3), [ 15] = _jump_target(45), // --> C [ 16] = ASN1_OP_MAYBE_ACT, [ 17] = _action(ACT_do_XXXXXXXXXXXX_e), In this, if the op at [13] is matched (ie. element 'e' above) then the action at [16] will be performed. However, if the op at [13] doesn't match or is skipped because it is conditional and some previous op matched, then the action at [16] will be ignored. Note that to make this work in the decoder, the ASN1_OP_RETURN op must set the flag to indicate that a match happened. This is necessary because the _jump_target() seen above introduces a subclause (in this case an object of type 'C') which is likely to alter the flag. Setting the flag here is okay because to process a subclause, a match must have happened and caused a jump. This cannot be tested with the code as it stands, but rather affects future code. Signed-off-by: David Howells Reviewed-by: David Woodhouse --- scripts/asn1_compiler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts/asn1_compiler.c') diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c index e87359cd23c0..0515bced929a 100644 --- a/scripts/asn1_compiler.c +++ b/scripts/asn1_compiler.c @@ -1468,7 +1468,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: -- cgit v1.2.1 From 233ce79db4b23a174bcf30bde5d6ad913d5f46d3 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Aug 2015 12:54:46 +0100 Subject: ASN.1: Handle 'ANY OPTIONAL' in grammar An ANY object in an ASN.1 grammar that is marked OPTIONAL should be skipped if there is no more data to be had. This can be tested by editing X.509 certificates or PKCS#7 messages to remove the NULL from subobjects that look like the following: SEQUENCE { OBJECT(2a864886f70d01010b); NULL(); } This is an algorithm identifier plus an optional parameter. The modified DER can be passed to one of: keyctl padd asymmetric "" @s Tested-by: Marcel Holtmann Reviewed-by: David Woodhouse --- scripts/asn1_compiler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts/asn1_compiler.c') diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c index 0515bced929a..1c75e22b6385 100644 --- a/scripts/asn1_compiler.c +++ b/scripts/asn1_compiler.c @@ -1401,7 +1401,8 @@ 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, -- cgit v1.2.1 From ae44a2f6a03338cb9d2bd32864f686c732b7841f Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Aug 2015 14:07:01 +0100 Subject: ASN.1: Add an ASN.1 compiler option to dump the element tree Add an ASN.1 compiler option to dump the element tree to stdout. Signed-off-by: David Howells Reviewed-By: David Woodhouse --- scripts/asn1_compiler.c | 88 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 12 deletions(-) (limited to 'scripts/asn1_compiler.c') diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c index 1c75e22b6385..6e4ba992a51f 100644 --- a/scripts/asn1_compiler.c +++ b/scripts/asn1_compiler.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -311,9 +312,11 @@ struct token { 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) { @@ -518,7 +521,7 @@ 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 { @@ -534,6 +537,7 @@ static void tokenise(char *buffer, char *end) static void build_type_list(void); static void parse(void); +static void dump_elements(void); static void render(FILE *out, FILE *hdr); /* @@ -548,16 +552,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 \n", + fprintf(stderr, "Format: %s [-v] [-d] \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 +623,7 @@ int main(int argc, char **argv) tokenise(buffer, buffer + readlen); build_type_list(); parse(); + dump_elements(); out = fopen(outputname, "w"); if (!out) { @@ -756,7 +772,7 @@ 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]; @@ -801,7 +817,7 @@ static void parse(void) } 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; @@ -1192,6 +1208,54 @@ 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->value : "."; + int nsize = e->name ? e->name->size : 1; + const char *tname = t && t->name ? t->name->value : "."; + int tnsize = t && t->name ? t->name->size : 1; + 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, + tnsize, tnsize, tname, + nsize, nsize, 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); @@ -1293,7 +1357,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); @@ -1304,7 +1368,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); -- cgit v1.2.1 From c05cae9a58dca6dcbc6e66b228a9589c6b60880c Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 29 Jul 2015 21:14:00 +0100 Subject: ASN.1: Copy string names to tokens in ASN.1 compiler Copy string names to tokens in ASN.1 compiler rather than storing a pointer into the source text. This means we don't have to use "%*.*s" all over the place. Signed-off-by: David Howells Reviewed-by: David Woodhouse --- scripts/asn1_compiler.c | 155 +++++++++++++++++++++++------------------------- 1 file changed, 73 insertions(+), 82 deletions(-) (limited to 'scripts/asn1_compiler.c') diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c index 6e4ba992a51f..e000f44e37b8 100644 --- a/scripts/asn1_compiler.c +++ b/scripts/asn1_compiler.c @@ -294,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; @@ -306,7 +306,7 @@ struct token { enum token_type token_type : 8; unsigned char size; struct action *action; - const char *value; + char *content; struct type *type; }; @@ -328,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; @@ -352,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 @@ -411,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. @@ -426,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; } @@ -458,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; } @@ -466,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; } @@ -475,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; } @@ -491,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: @@ -527,10 +548,7 @@ static void tokenise(char *buffer, char *end) { 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 } @@ -709,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); } @@ -722,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); } @@ -776,10 +794,7 @@ static void build_type_list(void) #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 } @@ -809,9 +824,8 @@ 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); } @@ -878,34 +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); + element->tag |= strtoul(cursor->content, &p, 10); element->flags |= ELEMENT_TAG_SPECIFIED; - if (p - cursor->value != cursor->size) + 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++; @@ -1005,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; @@ -1056,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); } @@ -1075,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; @@ -1118,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++; @@ -1130,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: @@ -1150,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++; @@ -1193,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++; @@ -1212,10 +1215,8 @@ 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->value : "."; - int nsize = e->name ? e->name->size : 1; - const char *tname = t && t->name ? t->name->value : "."; - int tnsize = t && t->name ? t->name->size : 1; + 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) @@ -1231,7 +1232,7 @@ static void dump_element(const struct element *e, int level) 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", + 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' : '-', @@ -1240,8 +1241,8 @@ static void dump_element(const struct element *e, int level) "-tTqQcaro"[e->compound], level, "", tag, - tnsize, tnsize, tname, - nsize, nsize, name, + tname, + name, e->action ? e->action->name : ""); if (e->compound == TYPE_REF) dump_element(e->type->type->element, level + 3); @@ -1454,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 */ @@ -1468,9 +1467,7 @@ static void render_element(FILE *out, struct element *e, struct element *tag) 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; @@ -1503,9 +1500,7 @@ static void render_element(FILE *out, struct element *e, struct element *tag) x = tag ?: e; if (x->name) - render_more(out, "\t\t// %*.*s", - (int)x->name->size, (int)x->name->size, - x->name->value); + render_more(out, "\t\t// %s", x->name->content); render_more(out, "\n"); /* Render the tag */ @@ -1543,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; @@ -1571,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; -- cgit v1.2.1