0001
0002
0003
0004
0005
0006
0007
0008 #include <stdarg.h>
0009 #include <stdio.h>
0010 #include <stdlib.h>
0011 #include <stdint.h>
0012 #include <stdbool.h>
0013 #include <string.h>
0014 #include <ctype.h>
0015 #include <unistd.h>
0016 #include <fcntl.h>
0017 #include <sys/stat.h>
0018 #include <linux/asn1_ber_bytecode.h>
0019
0020 enum token_type {
0021 DIRECTIVE_ABSENT,
0022 DIRECTIVE_ALL,
0023 DIRECTIVE_ANY,
0024 DIRECTIVE_APPLICATION,
0025 DIRECTIVE_AUTOMATIC,
0026 DIRECTIVE_BEGIN,
0027 DIRECTIVE_BIT,
0028 DIRECTIVE_BMPString,
0029 DIRECTIVE_BOOLEAN,
0030 DIRECTIVE_BY,
0031 DIRECTIVE_CHARACTER,
0032 DIRECTIVE_CHOICE,
0033 DIRECTIVE_CLASS,
0034 DIRECTIVE_COMPONENT,
0035 DIRECTIVE_COMPONENTS,
0036 DIRECTIVE_CONSTRAINED,
0037 DIRECTIVE_CONTAINING,
0038 DIRECTIVE_DEFAULT,
0039 DIRECTIVE_DEFINED,
0040 DIRECTIVE_DEFINITIONS,
0041 DIRECTIVE_EMBEDDED,
0042 DIRECTIVE_ENCODED,
0043 DIRECTIVE_ENCODING_CONTROL,
0044 DIRECTIVE_END,
0045 DIRECTIVE_ENUMERATED,
0046 DIRECTIVE_EXCEPT,
0047 DIRECTIVE_EXPLICIT,
0048 DIRECTIVE_EXPORTS,
0049 DIRECTIVE_EXTENSIBILITY,
0050 DIRECTIVE_EXTERNAL,
0051 DIRECTIVE_FALSE,
0052 DIRECTIVE_FROM,
0053 DIRECTIVE_GeneralString,
0054 DIRECTIVE_GeneralizedTime,
0055 DIRECTIVE_GraphicString,
0056 DIRECTIVE_IA5String,
0057 DIRECTIVE_IDENTIFIER,
0058 DIRECTIVE_IMPLICIT,
0059 DIRECTIVE_IMPLIED,
0060 DIRECTIVE_IMPORTS,
0061 DIRECTIVE_INCLUDES,
0062 DIRECTIVE_INSTANCE,
0063 DIRECTIVE_INSTRUCTIONS,
0064 DIRECTIVE_INTEGER,
0065 DIRECTIVE_INTERSECTION,
0066 DIRECTIVE_ISO646String,
0067 DIRECTIVE_MAX,
0068 DIRECTIVE_MIN,
0069 DIRECTIVE_MINUS_INFINITY,
0070 DIRECTIVE_NULL,
0071 DIRECTIVE_NumericString,
0072 DIRECTIVE_OBJECT,
0073 DIRECTIVE_OCTET,
0074 DIRECTIVE_OF,
0075 DIRECTIVE_OPTIONAL,
0076 DIRECTIVE_ObjectDescriptor,
0077 DIRECTIVE_PATTERN,
0078 DIRECTIVE_PDV,
0079 DIRECTIVE_PLUS_INFINITY,
0080 DIRECTIVE_PRESENT,
0081 DIRECTIVE_PRIVATE,
0082 DIRECTIVE_PrintableString,
0083 DIRECTIVE_REAL,
0084 DIRECTIVE_RELATIVE_OID,
0085 DIRECTIVE_SEQUENCE,
0086 DIRECTIVE_SET,
0087 DIRECTIVE_SIZE,
0088 DIRECTIVE_STRING,
0089 DIRECTIVE_SYNTAX,
0090 DIRECTIVE_T61String,
0091 DIRECTIVE_TAGS,
0092 DIRECTIVE_TRUE,
0093 DIRECTIVE_TeletexString,
0094 DIRECTIVE_UNION,
0095 DIRECTIVE_UNIQUE,
0096 DIRECTIVE_UNIVERSAL,
0097 DIRECTIVE_UTCTime,
0098 DIRECTIVE_UTF8String,
0099 DIRECTIVE_UniversalString,
0100 DIRECTIVE_VideotexString,
0101 DIRECTIVE_VisibleString,
0102 DIRECTIVE_WITH,
0103 NR__DIRECTIVES,
0104 TOKEN_ASSIGNMENT = NR__DIRECTIVES,
0105 TOKEN_OPEN_CURLY,
0106 TOKEN_CLOSE_CURLY,
0107 TOKEN_OPEN_SQUARE,
0108 TOKEN_CLOSE_SQUARE,
0109 TOKEN_OPEN_ACTION,
0110 TOKEN_CLOSE_ACTION,
0111 TOKEN_COMMA,
0112 TOKEN_NUMBER,
0113 TOKEN_TYPE_NAME,
0114 TOKEN_ELEMENT_NAME,
0115 NR__TOKENS
0116 };
0117
0118 static const unsigned char token_to_tag[NR__TOKENS] = {
0119
0120 [DIRECTIVE_BOOLEAN] = ASN1_BOOL,
0121 [DIRECTIVE_INTEGER] = ASN1_INT,
0122 [DIRECTIVE_BIT] = ASN1_BTS,
0123 [DIRECTIVE_OCTET] = ASN1_OTS,
0124 [DIRECTIVE_NULL] = ASN1_NULL,
0125 [DIRECTIVE_OBJECT] = ASN1_OID,
0126 [DIRECTIVE_ObjectDescriptor] = ASN1_ODE,
0127 [DIRECTIVE_EXTERNAL] = ASN1_EXT,
0128 [DIRECTIVE_REAL] = ASN1_REAL,
0129 [DIRECTIVE_ENUMERATED] = ASN1_ENUM,
0130 [DIRECTIVE_EMBEDDED] = 0,
0131 [DIRECTIVE_UTF8String] = ASN1_UTF8STR,
0132 [DIRECTIVE_RELATIVE_OID] = ASN1_RELOID,
0133
0134
0135 [DIRECTIVE_SEQUENCE] = ASN1_SEQ,
0136 [DIRECTIVE_SET] = ASN1_SET,
0137 [DIRECTIVE_NumericString] = ASN1_NUMSTR,
0138 [DIRECTIVE_PrintableString] = ASN1_PRNSTR,
0139 [DIRECTIVE_T61String] = ASN1_TEXSTR,
0140 [DIRECTIVE_TeletexString] = ASN1_TEXSTR,
0141 [DIRECTIVE_VideotexString] = ASN1_VIDSTR,
0142 [DIRECTIVE_IA5String] = ASN1_IA5STR,
0143 [DIRECTIVE_UTCTime] = ASN1_UNITIM,
0144 [DIRECTIVE_GeneralizedTime] = ASN1_GENTIM,
0145 [DIRECTIVE_GraphicString] = ASN1_GRASTR,
0146 [DIRECTIVE_VisibleString] = ASN1_VISSTR,
0147 [DIRECTIVE_GeneralString] = ASN1_GENSTR,
0148 [DIRECTIVE_UniversalString] = ASN1_UNITIM,
0149 [DIRECTIVE_CHARACTER] = ASN1_CHRSTR,
0150 [DIRECTIVE_BMPString] = ASN1_BMPSTR,
0151 };
0152
0153 static const char asn1_classes[4][5] = {
0154 [ASN1_UNIV] = "UNIV",
0155 [ASN1_APPL] = "APPL",
0156 [ASN1_CONT] = "CONT",
0157 [ASN1_PRIV] = "PRIV"
0158 };
0159
0160 static const char asn1_methods[2][5] = {
0161 [ASN1_UNIV] = "PRIM",
0162 [ASN1_APPL] = "CONS"
0163 };
0164
0165 static const char *const asn1_universal_tags[32] = {
0166 "EOC",
0167 "BOOL",
0168 "INT",
0169 "BTS",
0170 "OTS",
0171 "NULL",
0172 "OID",
0173 "ODE",
0174 "EXT",
0175 "REAL",
0176 "ENUM",
0177 "EPDV",
0178 "UTF8STR",
0179 "RELOID",
0180 NULL,
0181 NULL,
0182 "SEQ",
0183 "SET",
0184 "NUMSTR",
0185 "PRNSTR",
0186 "TEXSTR",
0187 "VIDSTR",
0188 "IA5STR",
0189 "UNITIM",
0190 "GENTIM",
0191 "GRASTR",
0192 "VISSTR",
0193 "GENSTR",
0194 "UNISTR",
0195 "CHRSTR",
0196 "BMPSTR",
0197 NULL
0198 };
0199
0200 static const char *filename;
0201 static const char *grammar_name;
0202 static const char *outputname;
0203 static const char *headername;
0204
0205 static const char *const directives[NR__DIRECTIVES] = {
0206 #define _(X) [DIRECTIVE_##X] = #X
0207 _(ABSENT),
0208 _(ALL),
0209 _(ANY),
0210 _(APPLICATION),
0211 _(AUTOMATIC),
0212 _(BEGIN),
0213 _(BIT),
0214 _(BMPString),
0215 _(BOOLEAN),
0216 _(BY),
0217 _(CHARACTER),
0218 _(CHOICE),
0219 _(CLASS),
0220 _(COMPONENT),
0221 _(COMPONENTS),
0222 _(CONSTRAINED),
0223 _(CONTAINING),
0224 _(DEFAULT),
0225 _(DEFINED),
0226 _(DEFINITIONS),
0227 _(EMBEDDED),
0228 _(ENCODED),
0229 [DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL",
0230 _(END),
0231 _(ENUMERATED),
0232 _(EXCEPT),
0233 _(EXPLICIT),
0234 _(EXPORTS),
0235 _(EXTENSIBILITY),
0236 _(EXTERNAL),
0237 _(FALSE),
0238 _(FROM),
0239 _(GeneralString),
0240 _(GeneralizedTime),
0241 _(GraphicString),
0242 _(IA5String),
0243 _(IDENTIFIER),
0244 _(IMPLICIT),
0245 _(IMPLIED),
0246 _(IMPORTS),
0247 _(INCLUDES),
0248 _(INSTANCE),
0249 _(INSTRUCTIONS),
0250 _(INTEGER),
0251 _(INTERSECTION),
0252 _(ISO646String),
0253 _(MAX),
0254 _(MIN),
0255 [DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY",
0256 [DIRECTIVE_NULL] = "NULL",
0257 _(NumericString),
0258 _(OBJECT),
0259 _(OCTET),
0260 _(OF),
0261 _(OPTIONAL),
0262 _(ObjectDescriptor),
0263 _(PATTERN),
0264 _(PDV),
0265 [DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY",
0266 _(PRESENT),
0267 _(PRIVATE),
0268 _(PrintableString),
0269 _(REAL),
0270 [DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID",
0271 _(SEQUENCE),
0272 _(SET),
0273 _(SIZE),
0274 _(STRING),
0275 _(SYNTAX),
0276 _(T61String),
0277 _(TAGS),
0278 _(TRUE),
0279 _(TeletexString),
0280 _(UNION),
0281 _(UNIQUE),
0282 _(UNIVERSAL),
0283 _(UTCTime),
0284 _(UTF8String),
0285 _(UniversalString),
0286 _(VideotexString),
0287 _(VisibleString),
0288 _(WITH)
0289 };
0290
0291 struct action {
0292 struct action *next;
0293 char *name;
0294 unsigned char index;
0295 };
0296
0297 static struct action *action_list;
0298 static unsigned nr_actions;
0299
0300 struct token {
0301 unsigned short line;
0302 enum token_type token_type : 8;
0303 unsigned char size;
0304 struct action *action;
0305 char *content;
0306 struct type *type;
0307 };
0308
0309 static struct token *token_list;
0310 static unsigned nr_tokens;
0311 static bool verbose_opt;
0312 static bool debug_opt;
0313
0314 #define verbose(fmt, ...) do { if (verbose_opt) printf(fmt, ## __VA_ARGS__); } while (0)
0315 #define debug(fmt, ...) do { if (debug_opt) printf(fmt, ## __VA_ARGS__); } while (0)
0316
0317 static int directive_compare(const void *_key, const void *_pdir)
0318 {
0319 const struct token *token = _key;
0320 const char *const *pdir = _pdir, *dir = *pdir;
0321 size_t dlen, clen;
0322 int val;
0323
0324 dlen = strlen(dir);
0325 clen = (dlen < token->size) ? dlen : token->size;
0326
0327
0328
0329 val = memcmp(token->content, dir, clen);
0330 if (val != 0) {
0331
0332 return val;
0333 }
0334
0335 if (dlen == token->size) {
0336
0337 return 0;
0338 }
0339
0340 return dlen - token->size;
0341 }
0342
0343
0344
0345
0346 static void tokenise(char *buffer, char *end)
0347 {
0348 struct token *tokens;
0349 char *line, *nl, *start, *p, *q;
0350 unsigned tix, lineno;
0351
0352
0353
0354
0355 token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token));
0356 if (!tokens) {
0357 perror(NULL);
0358 exit(1);
0359 }
0360 tix = 0;
0361
0362 lineno = 0;
0363 while (buffer < end) {
0364
0365 lineno++;
0366 line = buffer;
0367 nl = memchr(line, '\n', end - buffer);
0368 if (!nl) {
0369 buffer = nl = end;
0370 } else {
0371 buffer = nl + 1;
0372 *nl = '\0';
0373 }
0374
0375
0376 p = line;
0377 next_comment:
0378 while ((p = memchr(p, '-', nl - p))) {
0379 if (p[1] == '-') {
0380
0381 q = p + 2;
0382 while ((q = memchr(q, '-', nl - q))) {
0383 if (q[1] == '-') {
0384
0385 q += 2;
0386 memmove(p, q, nl - q);
0387 goto next_comment;
0388 }
0389 q++;
0390 }
0391 *p = '\0';
0392 nl = p;
0393 break;
0394 } else {
0395 p++;
0396 }
0397 }
0398
0399 p = line;
0400 while (p < nl) {
0401
0402 while (p < nl && isspace(*p))
0403 *(p++) = 0;
0404 if (p >= nl)
0405 break;
0406
0407 tokens[tix].line = lineno;
0408 start = p;
0409
0410
0411 if (isalpha(*p)) {
0412 const char **dir;
0413
0414
0415
0416
0417 q = p + 1;
0418 while (q < nl && (isalnum(*q) || *q == '-' || *q == '_'))
0419 q++;
0420 tokens[tix].size = q - p;
0421 p = q;
0422
0423 tokens[tix].content = malloc(tokens[tix].size + 1);
0424 if (!tokens[tix].content) {
0425 perror(NULL);
0426 exit(1);
0427 }
0428 memcpy(tokens[tix].content, start, tokens[tix].size);
0429 tokens[tix].content[tokens[tix].size] = 0;
0430
0431
0432
0433
0434 if (islower(tokens[tix].content[0])) {
0435 tokens[tix++].token_type = TOKEN_ELEMENT_NAME;
0436 continue;
0437 }
0438
0439
0440
0441
0442 dir = bsearch(&tokens[tix], directives,
0443 sizeof(directives) / sizeof(directives[1]),
0444 sizeof(directives[1]),
0445 directive_compare);
0446 if (dir) {
0447 tokens[tix++].token_type = dir - directives;
0448 continue;
0449 }
0450
0451 tokens[tix++].token_type = TOKEN_TYPE_NAME;
0452 continue;
0453 }
0454
0455
0456 if (isdigit(*p)) {
0457
0458 q = p + 1;
0459 while (q < nl && (isdigit(*q)))
0460 q++;
0461 tokens[tix].size = q - p;
0462 p = q;
0463 tokens[tix].content = malloc(tokens[tix].size + 1);
0464 if (!tokens[tix].content) {
0465 perror(NULL);
0466 exit(1);
0467 }
0468 memcpy(tokens[tix].content, start, tokens[tix].size);
0469 tokens[tix].content[tokens[tix].size] = 0;
0470 tokens[tix++].token_type = TOKEN_NUMBER;
0471 continue;
0472 }
0473
0474 if (nl - p >= 3) {
0475 if (memcmp(p, "::=", 3) == 0) {
0476 p += 3;
0477 tokens[tix].size = 3;
0478 tokens[tix].content = "::=";
0479 tokens[tix++].token_type = TOKEN_ASSIGNMENT;
0480 continue;
0481 }
0482 }
0483
0484 if (nl - p >= 2) {
0485 if (memcmp(p, "({", 2) == 0) {
0486 p += 2;
0487 tokens[tix].size = 2;
0488 tokens[tix].content = "({";
0489 tokens[tix++].token_type = TOKEN_OPEN_ACTION;
0490 continue;
0491 }
0492 if (memcmp(p, "})", 2) == 0) {
0493 p += 2;
0494 tokens[tix].size = 2;
0495 tokens[tix].content = "})";
0496 tokens[tix++].token_type = TOKEN_CLOSE_ACTION;
0497 continue;
0498 }
0499 }
0500
0501 if (nl - p >= 1) {
0502 tokens[tix].size = 1;
0503 switch (*p) {
0504 case '{':
0505 p += 1;
0506 tokens[tix].content = "{";
0507 tokens[tix++].token_type = TOKEN_OPEN_CURLY;
0508 continue;
0509 case '}':
0510 p += 1;
0511 tokens[tix].content = "}";
0512 tokens[tix++].token_type = TOKEN_CLOSE_CURLY;
0513 continue;
0514 case '[':
0515 p += 1;
0516 tokens[tix].content = "[";
0517 tokens[tix++].token_type = TOKEN_OPEN_SQUARE;
0518 continue;
0519 case ']':
0520 p += 1;
0521 tokens[tix].content = "]";
0522 tokens[tix++].token_type = TOKEN_CLOSE_SQUARE;
0523 continue;
0524 case ',':
0525 p += 1;
0526 tokens[tix].content = ",";
0527 tokens[tix++].token_type = TOKEN_COMMA;
0528 continue;
0529 default:
0530 break;
0531 }
0532 }
0533
0534 fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n",
0535 filename, lineno, *p);
0536 exit(1);
0537 }
0538 }
0539
0540 nr_tokens = tix;
0541 verbose("Extracted %u tokens\n", nr_tokens);
0542
0543 #if 0
0544 {
0545 int n;
0546 for (n = 0; n < nr_tokens; n++)
0547 debug("Token %3u: '%s'\n", n, token_list[n].content);
0548 }
0549 #endif
0550 }
0551
0552 static void build_type_list(void);
0553 static void parse(void);
0554 static void dump_elements(void);
0555 static void render(FILE *out, FILE *hdr);
0556
0557
0558
0559
0560 int main(int argc, char **argv)
0561 {
0562 struct stat st;
0563 ssize_t readlen;
0564 FILE *out, *hdr;
0565 char *buffer, *p;
0566 char *kbuild_verbose;
0567 int fd;
0568
0569 kbuild_verbose = getenv("KBUILD_VERBOSE");
0570 if (kbuild_verbose)
0571 verbose_opt = atoi(kbuild_verbose);
0572
0573 while (argc > 4) {
0574 if (strcmp(argv[1], "-v") == 0)
0575 verbose_opt = true;
0576 else if (strcmp(argv[1], "-d") == 0)
0577 debug_opt = true;
0578 else
0579 break;
0580 memmove(&argv[1], &argv[2], (argc - 2) * sizeof(char *));
0581 argc--;
0582 }
0583
0584 if (argc != 4) {
0585 fprintf(stderr, "Format: %s [-v] [-d] <grammar-file> <c-file> <hdr-file>\n",
0586 argv[0]);
0587 exit(2);
0588 }
0589
0590 filename = argv[1];
0591 outputname = argv[2];
0592 headername = argv[3];
0593
0594 fd = open(filename, O_RDONLY);
0595 if (fd < 0) {
0596 perror(filename);
0597 exit(1);
0598 }
0599
0600 if (fstat(fd, &st) < 0) {
0601 perror(filename);
0602 exit(1);
0603 }
0604
0605 if (!(buffer = malloc(st.st_size + 1))) {
0606 perror(NULL);
0607 exit(1);
0608 }
0609
0610 if ((readlen = read(fd, buffer, st.st_size)) < 0) {
0611 perror(filename);
0612 exit(1);
0613 }
0614
0615 if (close(fd) < 0) {
0616 perror(filename);
0617 exit(1);
0618 }
0619
0620 if (readlen != st.st_size) {
0621 fprintf(stderr, "%s: Short read\n", filename);
0622 exit(1);
0623 }
0624
0625 p = strrchr(argv[1], '/');
0626 p = p ? p + 1 : argv[1];
0627 grammar_name = strdup(p);
0628 if (!p) {
0629 perror(NULL);
0630 exit(1);
0631 }
0632 p = strchr(grammar_name, '.');
0633 if (p)
0634 *p = '\0';
0635
0636 buffer[readlen] = 0;
0637 tokenise(buffer, buffer + readlen);
0638 build_type_list();
0639 parse();
0640 dump_elements();
0641
0642 out = fopen(outputname, "w");
0643 if (!out) {
0644 perror(outputname);
0645 exit(1);
0646 }
0647
0648 hdr = fopen(headername, "w");
0649 if (!hdr) {
0650 perror(headername);
0651 exit(1);
0652 }
0653
0654 render(out, hdr);
0655
0656 if (fclose(out) < 0) {
0657 perror(outputname);
0658 exit(1);
0659 }
0660
0661 if (fclose(hdr) < 0) {
0662 perror(headername);
0663 exit(1);
0664 }
0665
0666 return 0;
0667 }
0668
0669 enum compound {
0670 NOT_COMPOUND,
0671 SET,
0672 SET_OF,
0673 SEQUENCE,
0674 SEQUENCE_OF,
0675 CHOICE,
0676 ANY,
0677 TYPE_REF,
0678 TAG_OVERRIDE
0679 };
0680
0681 struct element {
0682 struct type *type_def;
0683 struct token *name;
0684 struct token *type;
0685 struct action *action;
0686 struct element *children;
0687 struct element *next;
0688 struct element *render_next;
0689 struct element *list_next;
0690 uint8_t n_elements;
0691 enum compound compound : 8;
0692 enum asn1_class class : 8;
0693 enum asn1_method method : 8;
0694 uint8_t tag;
0695 unsigned entry_index;
0696 unsigned flags;
0697 #define ELEMENT_IMPLICIT 0x0001
0698 #define ELEMENT_EXPLICIT 0x0002
0699 #define ELEMENT_TAG_SPECIFIED 0x0004
0700 #define ELEMENT_RENDERED 0x0008
0701 #define ELEMENT_SKIPPABLE 0x0010
0702 #define ELEMENT_CONDITIONAL 0x0020
0703 };
0704
0705 struct type {
0706 struct token *name;
0707 struct token *def;
0708 struct element *element;
0709 unsigned ref_count;
0710 unsigned flags;
0711 #define TYPE_STOP_MARKER 0x0001
0712 #define TYPE_BEGIN 0x0002
0713 };
0714
0715 static struct type *type_list;
0716 static struct type **type_index;
0717 static unsigned nr_types;
0718
0719 static int type_index_compare(const void *_a, const void *_b)
0720 {
0721 const struct type *const *a = _a, *const *b = _b;
0722
0723 if ((*a)->name->size != (*b)->name->size)
0724 return (*a)->name->size - (*b)->name->size;
0725 else
0726 return memcmp((*a)->name->content, (*b)->name->content,
0727 (*a)->name->size);
0728 }
0729
0730 static int type_finder(const void *_key, const void *_ti)
0731 {
0732 const struct token *token = _key;
0733 const struct type *const *ti = _ti;
0734 const struct type *type = *ti;
0735
0736 if (token->size != type->name->size)
0737 return token->size - type->name->size;
0738 else
0739 return memcmp(token->content, type->name->content,
0740 token->size);
0741 }
0742
0743
0744
0745
0746 static void build_type_list(void)
0747 {
0748 struct type *types;
0749 unsigned nr, t, n;
0750
0751 nr = 0;
0752 for (n = 0; n < nr_tokens - 1; n++)
0753 if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
0754 token_list[n + 1].token_type == TOKEN_ASSIGNMENT)
0755 nr++;
0756
0757 if (nr == 0) {
0758 fprintf(stderr, "%s: No defined types\n", filename);
0759 exit(1);
0760 }
0761
0762 nr_types = nr;
0763 types = type_list = calloc(nr + 1, sizeof(type_list[0]));
0764 if (!type_list) {
0765 perror(NULL);
0766 exit(1);
0767 }
0768 type_index = calloc(nr, sizeof(type_index[0]));
0769 if (!type_index) {
0770 perror(NULL);
0771 exit(1);
0772 }
0773
0774 t = 0;
0775 types[t].flags |= TYPE_BEGIN;
0776 for (n = 0; n < nr_tokens - 1; n++) {
0777 if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
0778 token_list[n + 1].token_type == TOKEN_ASSIGNMENT) {
0779 types[t].name = &token_list[n];
0780 type_index[t] = &types[t];
0781 t++;
0782 }
0783 }
0784 types[t].name = &token_list[n + 1];
0785 types[t].flags |= TYPE_STOP_MARKER;
0786
0787 qsort(type_index, nr, sizeof(type_index[0]), type_index_compare);
0788
0789 verbose("Extracted %u types\n", nr_types);
0790 #if 0
0791 for (n = 0; n < nr_types; n++) {
0792 struct type *type = type_index[n];
0793 debug("- %*.*s\n", type->name->content);
0794 }
0795 #endif
0796 }
0797
0798 static struct element *parse_type(struct token **_cursor, struct token *stop,
0799 struct token *name);
0800
0801
0802
0803
0804 static void parse(void)
0805 {
0806 struct token *cursor;
0807 struct type *type;
0808
0809
0810 type = type_list;
0811 do {
0812 cursor = type->name;
0813
0814 if (cursor[0].token_type != TOKEN_TYPE_NAME ||
0815 cursor[1].token_type != TOKEN_ASSIGNMENT)
0816 abort();
0817 cursor += 2;
0818
0819 type->element = parse_type(&cursor, type[1].name, NULL);
0820 type->element->type_def = type;
0821
0822 if (cursor != type[1].name) {
0823 fprintf(stderr, "%s:%d: Parse error at token '%s'\n",
0824 filename, cursor->line, cursor->content);
0825 exit(1);
0826 }
0827
0828 } while (type++, !(type->flags & TYPE_STOP_MARKER));
0829
0830 verbose("Extracted %u actions\n", nr_actions);
0831 }
0832
0833 static struct element *element_list;
0834
0835 static struct element *alloc_elem(struct token *type)
0836 {
0837 struct element *e = calloc(1, sizeof(*e));
0838 if (!e) {
0839 perror(NULL);
0840 exit(1);
0841 }
0842 e->list_next = element_list;
0843 element_list = e;
0844 return e;
0845 }
0846
0847 static struct element *parse_compound(struct token **_cursor, struct token *end,
0848 int alternates);
0849
0850
0851
0852
0853 static struct element *parse_type(struct token **_cursor, struct token *end,
0854 struct token *name)
0855 {
0856 struct element *top, *element;
0857 struct action *action, **ppaction;
0858 struct token *cursor = *_cursor;
0859 struct type **ref;
0860 char *p;
0861 int labelled = 0, implicit = 0;
0862
0863 top = element = alloc_elem(cursor);
0864 element->class = ASN1_UNIV;
0865 element->method = ASN1_PRIM;
0866 element->tag = token_to_tag[cursor->token_type];
0867 element->name = name;
0868
0869
0870 if (cursor->token_type == TOKEN_OPEN_SQUARE) {
0871 cursor++;
0872 if (cursor >= end)
0873 goto overrun_error;
0874 switch (cursor->token_type) {
0875 case DIRECTIVE_UNIVERSAL:
0876 element->class = ASN1_UNIV;
0877 cursor++;
0878 break;
0879 case DIRECTIVE_APPLICATION:
0880 element->class = ASN1_APPL;
0881 cursor++;
0882 break;
0883 case TOKEN_NUMBER:
0884 element->class = ASN1_CONT;
0885 break;
0886 case DIRECTIVE_PRIVATE:
0887 element->class = ASN1_PRIV;
0888 cursor++;
0889 break;
0890 default:
0891 fprintf(stderr, "%s:%d: Unrecognised tag class token '%s'\n",
0892 filename, cursor->line, cursor->content);
0893 exit(1);
0894 }
0895
0896 if (cursor >= end)
0897 goto overrun_error;
0898 if (cursor->token_type != TOKEN_NUMBER) {
0899 fprintf(stderr, "%s:%d: Missing tag number '%s'\n",
0900 filename, cursor->line, cursor->content);
0901 exit(1);
0902 }
0903
0904 element->tag &= ~0x1f;
0905 element->tag |= strtoul(cursor->content, &p, 10);
0906 element->flags |= ELEMENT_TAG_SPECIFIED;
0907 if (p - cursor->content != cursor->size)
0908 abort();
0909 cursor++;
0910
0911 if (cursor >= end)
0912 goto overrun_error;
0913 if (cursor->token_type != TOKEN_CLOSE_SQUARE) {
0914 fprintf(stderr, "%s:%d: Missing closing square bracket '%s'\n",
0915 filename, cursor->line, cursor->content);
0916 exit(1);
0917 }
0918 cursor++;
0919 if (cursor >= end)
0920 goto overrun_error;
0921 labelled = 1;
0922 }
0923
0924
0925 if (cursor->token_type == DIRECTIVE_IMPLICIT) {
0926 element->flags |= ELEMENT_IMPLICIT;
0927 implicit = 1;
0928 cursor++;
0929 if (cursor >= end)
0930 goto overrun_error;
0931 } else if (cursor->token_type == DIRECTIVE_EXPLICIT) {
0932 element->flags |= ELEMENT_EXPLICIT;
0933 cursor++;
0934 if (cursor >= end)
0935 goto overrun_error;
0936 }
0937
0938 if (labelled) {
0939 if (!implicit)
0940 element->method |= ASN1_CONS;
0941 element->compound = implicit ? TAG_OVERRIDE : SEQUENCE;
0942 element->children = alloc_elem(cursor);
0943 element = element->children;
0944 element->class = ASN1_UNIV;
0945 element->method = ASN1_PRIM;
0946 element->tag = token_to_tag[cursor->token_type];
0947 element->name = name;
0948 }
0949
0950
0951 element->type = cursor;
0952 switch (cursor->token_type) {
0953 case DIRECTIVE_ANY:
0954 element->compound = ANY;
0955 cursor++;
0956 break;
0957
0958 case DIRECTIVE_NULL:
0959 case DIRECTIVE_BOOLEAN:
0960 case DIRECTIVE_ENUMERATED:
0961 case DIRECTIVE_INTEGER:
0962 element->compound = NOT_COMPOUND;
0963 cursor++;
0964 break;
0965
0966 case DIRECTIVE_EXTERNAL:
0967 element->method = ASN1_CONS;
0968
0969 case DIRECTIVE_BMPString:
0970 case DIRECTIVE_GeneralString:
0971 case DIRECTIVE_GraphicString:
0972 case DIRECTIVE_IA5String:
0973 case DIRECTIVE_ISO646String:
0974 case DIRECTIVE_NumericString:
0975 case DIRECTIVE_PrintableString:
0976 case DIRECTIVE_T61String:
0977 case DIRECTIVE_TeletexString:
0978 case DIRECTIVE_UniversalString:
0979 case DIRECTIVE_UTF8String:
0980 case DIRECTIVE_VideotexString:
0981 case DIRECTIVE_VisibleString:
0982 case DIRECTIVE_ObjectDescriptor:
0983 case DIRECTIVE_GeneralizedTime:
0984 case DIRECTIVE_UTCTime:
0985 element->compound = NOT_COMPOUND;
0986 cursor++;
0987 break;
0988
0989 case DIRECTIVE_BIT:
0990 case DIRECTIVE_OCTET:
0991 element->compound = NOT_COMPOUND;
0992 cursor++;
0993 if (cursor >= end)
0994 goto overrun_error;
0995 if (cursor->token_type != DIRECTIVE_STRING)
0996 goto parse_error;
0997 cursor++;
0998 break;
0999
1000 case DIRECTIVE_OBJECT:
1001 element->compound = NOT_COMPOUND;
1002 cursor++;
1003 if (cursor >= end)
1004 goto overrun_error;
1005 if (cursor->token_type != DIRECTIVE_IDENTIFIER)
1006 goto parse_error;
1007 cursor++;
1008 break;
1009
1010 case TOKEN_TYPE_NAME:
1011 element->compound = TYPE_REF;
1012 ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]),
1013 type_finder);
1014 if (!ref) {
1015 fprintf(stderr, "%s:%d: Type '%s' undefined\n",
1016 filename, cursor->line, cursor->content);
1017 exit(1);
1018 }
1019 cursor->type = *ref;
1020 (*ref)->ref_count++;
1021 cursor++;
1022 break;
1023
1024 case DIRECTIVE_CHOICE:
1025 element->compound = CHOICE;
1026 cursor++;
1027 element->children = parse_compound(&cursor, end, 1);
1028 break;
1029
1030 case DIRECTIVE_SEQUENCE:
1031 element->compound = SEQUENCE;
1032 element->method = ASN1_CONS;
1033 cursor++;
1034 if (cursor >= end)
1035 goto overrun_error;
1036 if (cursor->token_type == DIRECTIVE_OF) {
1037 element->compound = SEQUENCE_OF;
1038 cursor++;
1039 if (cursor >= end)
1040 goto overrun_error;
1041 element->children = parse_type(&cursor, end, NULL);
1042 } else {
1043 element->children = parse_compound(&cursor, end, 0);
1044 }
1045 break;
1046
1047 case DIRECTIVE_SET:
1048 element->compound = SET;
1049 element->method = ASN1_CONS;
1050 cursor++;
1051 if (cursor >= end)
1052 goto overrun_error;
1053 if (cursor->token_type == DIRECTIVE_OF) {
1054 element->compound = SET_OF;
1055 cursor++;
1056 if (cursor >= end)
1057 goto parse_error;
1058 element->children = parse_type(&cursor, end, NULL);
1059 } else {
1060 element->children = parse_compound(&cursor, end, 1);
1061 }
1062 break;
1063
1064 default:
1065 fprintf(stderr, "%s:%d: Token '%s' does not introduce a type\n",
1066 filename, cursor->line, cursor->content);
1067 exit(1);
1068 }
1069
1070
1071 if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL ||
1072 cursor->token_type == DIRECTIVE_DEFAULT)
1073 ) {
1074 cursor++;
1075 top->flags |= ELEMENT_SKIPPABLE;
1076 }
1077
1078 if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) {
1079 cursor++;
1080 if (cursor >= end)
1081 goto overrun_error;
1082 if (cursor->token_type != TOKEN_ELEMENT_NAME) {
1083 fprintf(stderr, "%s:%d: Token '%s' is not an action function name\n",
1084 filename, cursor->line, cursor->content);
1085 exit(1);
1086 }
1087
1088 action = malloc(sizeof(struct action));
1089 if (!action) {
1090 perror(NULL);
1091 exit(1);
1092 }
1093 action->index = 0;
1094 action->name = cursor->content;
1095
1096 for (ppaction = &action_list;
1097 *ppaction;
1098 ppaction = &(*ppaction)->next
1099 ) {
1100 int cmp = strcmp(action->name, (*ppaction)->name);
1101 if (cmp == 0) {
1102 free(action);
1103 action = *ppaction;
1104 goto found;
1105 }
1106 if (cmp < 0) {
1107 action->next = *ppaction;
1108 *ppaction = action;
1109 nr_actions++;
1110 goto found;
1111 }
1112 }
1113 action->next = NULL;
1114 *ppaction = action;
1115 nr_actions++;
1116 found:
1117
1118 element->action = action;
1119 cursor->action = action;
1120 cursor++;
1121 if (cursor >= end)
1122 goto overrun_error;
1123 if (cursor->token_type != TOKEN_CLOSE_ACTION) {
1124 fprintf(stderr, "%s:%d: Missing close action, got '%s'\n",
1125 filename, cursor->line, cursor->content);
1126 exit(1);
1127 }
1128 cursor++;
1129 }
1130
1131 *_cursor = cursor;
1132 return top;
1133
1134 parse_error:
1135 fprintf(stderr, "%s:%d: Unexpected token '%s'\n",
1136 filename, cursor->line, cursor->content);
1137 exit(1);
1138
1139 overrun_error:
1140 fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
1141 exit(1);
1142 }
1143
1144
1145
1146
1147 static struct element *parse_compound(struct token **_cursor, struct token *end,
1148 int alternates)
1149 {
1150 struct element *children, **child_p = &children, *element;
1151 struct token *cursor = *_cursor, *name;
1152
1153 if (cursor->token_type != TOKEN_OPEN_CURLY) {
1154 fprintf(stderr, "%s:%d: Expected compound to start with brace not '%s'\n",
1155 filename, cursor->line, cursor->content);
1156 exit(1);
1157 }
1158 cursor++;
1159 if (cursor >= end)
1160 goto overrun_error;
1161
1162 if (cursor->token_type == TOKEN_OPEN_CURLY) {
1163 fprintf(stderr, "%s:%d: Empty compound\n",
1164 filename, cursor->line);
1165 exit(1);
1166 }
1167
1168 for (;;) {
1169 name = NULL;
1170 if (cursor->token_type == TOKEN_ELEMENT_NAME) {
1171 name = cursor;
1172 cursor++;
1173 if (cursor >= end)
1174 goto overrun_error;
1175 }
1176
1177 element = parse_type(&cursor, end, name);
1178 if (alternates)
1179 element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL;
1180
1181 *child_p = element;
1182 child_p = &element->next;
1183
1184 if (cursor >= end)
1185 goto overrun_error;
1186 if (cursor->token_type != TOKEN_COMMA)
1187 break;
1188 cursor++;
1189 if (cursor >= end)
1190 goto overrun_error;
1191 }
1192
1193 children->flags &= ~ELEMENT_CONDITIONAL;
1194
1195 if (cursor->token_type != TOKEN_CLOSE_CURLY) {
1196 fprintf(stderr, "%s:%d: Expected compound closure, got '%s'\n",
1197 filename, cursor->line, cursor->content);
1198 exit(1);
1199 }
1200 cursor++;
1201
1202 *_cursor = cursor;
1203 return children;
1204
1205 overrun_error:
1206 fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
1207 exit(1);
1208 }
1209
1210 static void dump_element(const struct element *e, int level)
1211 {
1212 const struct element *c;
1213 const struct type *t = e->type_def;
1214 const char *name = e->name ? e->name->content : ".";
1215 const char *tname = t && t->name ? t->name->content : ".";
1216 char tag[32];
1217
1218 if (e->class == 0 && e->method == 0 && e->tag == 0)
1219 strcpy(tag, "<...>");
1220 else if (e->class == ASN1_UNIV)
1221 sprintf(tag, "%s %s %s",
1222 asn1_classes[e->class],
1223 asn1_methods[e->method],
1224 asn1_universal_tags[e->tag]);
1225 else
1226 sprintf(tag, "%s %s %u",
1227 asn1_classes[e->class],
1228 asn1_methods[e->method],
1229 e->tag);
1230
1231 printf("%c%c%c%c%c %c %*s[*] \e[33m%s\e[m %s %s \e[35m%s\e[m\n",
1232 e->flags & ELEMENT_IMPLICIT ? 'I' : '-',
1233 e->flags & ELEMENT_EXPLICIT ? 'E' : '-',
1234 e->flags & ELEMENT_TAG_SPECIFIED ? 'T' : '-',
1235 e->flags & ELEMENT_SKIPPABLE ? 'S' : '-',
1236 e->flags & ELEMENT_CONDITIONAL ? 'C' : '-',
1237 "-tTqQcaro"[e->compound],
1238 level, "",
1239 tag,
1240 tname,
1241 name,
1242 e->action ? e->action->name : "");
1243 if (e->compound == TYPE_REF)
1244 dump_element(e->type->type->element, level + 3);
1245 else
1246 for (c = e->children; c; c = c->next)
1247 dump_element(c, level + 3);
1248 }
1249
1250 static void dump_elements(void)
1251 {
1252 if (debug_opt)
1253 dump_element(type_list[0].element, 0);
1254 }
1255
1256 static void render_element(FILE *out, struct element *e, struct element *tag);
1257 static void render_out_of_line_list(FILE *out);
1258
1259 static int nr_entries;
1260 static int render_depth = 1;
1261 static struct element *render_list, **render_list_p = &render_list;
1262
1263 __attribute__((format(printf, 2, 3)))
1264 static void render_opcode(FILE *out, const char *fmt, ...)
1265 {
1266 va_list va;
1267
1268 if (out) {
1269 fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, "");
1270 va_start(va, fmt);
1271 vfprintf(out, fmt, va);
1272 va_end(va);
1273 }
1274 nr_entries++;
1275 }
1276
1277 __attribute__((format(printf, 2, 3)))
1278 static void render_more(FILE *out, const char *fmt, ...)
1279 {
1280 va_list va;
1281
1282 if (out) {
1283 va_start(va, fmt);
1284 vfprintf(out, fmt, va);
1285 va_end(va);
1286 }
1287 }
1288
1289
1290
1291
1292 static void render(FILE *out, FILE *hdr)
1293 {
1294 struct element *e;
1295 struct action *action;
1296 struct type *root;
1297 int index;
1298
1299 fprintf(hdr, "/*\n");
1300 fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n");
1301 fprintf(hdr, " *\n");
1302 fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name);
1303 fprintf(hdr, " */\n");
1304 fprintf(hdr, "#include <linux/asn1_decoder.h>\n");
1305 fprintf(hdr, "\n");
1306 fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name);
1307 if (ferror(hdr)) {
1308 perror(headername);
1309 exit(1);
1310 }
1311
1312 fprintf(out, "/*\n");
1313 fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n");
1314 fprintf(out, " *\n");
1315 fprintf(out, " * ASN.1 parser for %s\n", grammar_name);
1316 fprintf(out, " */\n");
1317 fprintf(out, "#include <linux/asn1_ber_bytecode.h>\n");
1318 fprintf(out, "#include \"%s.asn1.h\"\n", grammar_name);
1319 fprintf(out, "\n");
1320 if (ferror(out)) {
1321 perror(outputname);
1322 exit(1);
1323 }
1324
1325
1326 fprintf(hdr, "\n");
1327 index = 0;
1328 for (action = action_list; action; action = action->next) {
1329 action->index = index++;
1330 fprintf(hdr,
1331 "extern int %s(void *, size_t, unsigned char,"
1332 " const void *, size_t);\n",
1333 action->name);
1334 }
1335 fprintf(hdr, "\n");
1336
1337 fprintf(out, "enum %s_actions {\n", grammar_name);
1338 for (action = action_list; action; action = action->next)
1339 fprintf(out, "\tACT_%s = %u,\n",
1340 action->name, action->index);
1341 fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions);
1342 fprintf(out, "};\n");
1343
1344 fprintf(out, "\n");
1345 fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n",
1346 grammar_name, grammar_name);
1347 for (action = action_list; action; action = action->next)
1348 fprintf(out, "\t[%4u] = %s,\n", action->index, action->name);
1349 fprintf(out, "};\n");
1350
1351 if (ferror(out)) {
1352 perror(outputname);
1353 exit(1);
1354 }
1355
1356
1357 verbose("Pass 1\n");
1358 nr_entries = 0;
1359 root = &type_list[0];
1360 render_element(NULL, root->element, NULL);
1361 render_opcode(NULL, "ASN1_OP_COMPLETE,\n");
1362 render_out_of_line_list(NULL);
1363
1364 for (e = element_list; e; e = e->list_next)
1365 e->flags &= ~ELEMENT_RENDERED;
1366
1367
1368 verbose("Pass 2\n");
1369 fprintf(out, "\n");
1370 fprintf(out, "static const unsigned char %s_machine[] = {\n",
1371 grammar_name);
1372
1373 nr_entries = 0;
1374 root = &type_list[0];
1375 render_element(out, root->element, NULL);
1376 render_opcode(out, "ASN1_OP_COMPLETE,\n");
1377 render_out_of_line_list(out);
1378
1379 fprintf(out, "};\n");
1380
1381 fprintf(out, "\n");
1382 fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name);
1383 fprintf(out, "\t.machine = %s_machine,\n", grammar_name);
1384 fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name);
1385 fprintf(out, "\t.actions = %s_action_table,\n", grammar_name);
1386 fprintf(out, "};\n");
1387 }
1388
1389
1390
1391
1392 static void render_out_of_line_list(FILE *out)
1393 {
1394 struct element *e, *ce;
1395 const char *act;
1396 int entry;
1397
1398 while ((e = render_list)) {
1399 render_list = e->render_next;
1400 if (!render_list)
1401 render_list_p = &render_list;
1402
1403 render_more(out, "\n");
1404 e->entry_index = entry = nr_entries;
1405 render_depth++;
1406 for (ce = e->children; ce; ce = ce->next)
1407 render_element(out, ce, NULL);
1408 render_depth--;
1409
1410 act = e->action ? "_ACT" : "";
1411 switch (e->compound) {
1412 case SEQUENCE:
1413 render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
1414 break;
1415 case SEQUENCE_OF:
1416 render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
1417 render_opcode(out, "_jump_target(%u),\n", entry);
1418 break;
1419 case SET:
1420 render_opcode(out, "ASN1_OP_END_SET%s,\n", act);
1421 break;
1422 case SET_OF:
1423 render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
1424 render_opcode(out, "_jump_target(%u),\n", entry);
1425 break;
1426 default:
1427 break;
1428 }
1429 if (e->action)
1430 render_opcode(out, "_action(ACT_%s),\n",
1431 e->action->name);
1432 render_opcode(out, "ASN1_OP_RETURN,\n");
1433 }
1434 }
1435
1436
1437
1438
1439 static void render_element(FILE *out, struct element *e, struct element *tag)
1440 {
1441 struct element *ec, *x;
1442 const char *cond, *act;
1443 int entry, skippable = 0, outofline = 0;
1444
1445 if (e->flags & ELEMENT_SKIPPABLE ||
1446 (tag && tag->flags & ELEMENT_SKIPPABLE))
1447 skippable = 1;
1448
1449 if ((e->type_def && e->type_def->ref_count > 1) ||
1450 skippable)
1451 outofline = 1;
1452
1453 if (e->type_def && out) {
1454 render_more(out, "\t// %s\n", e->type_def->name->content);
1455 }
1456
1457
1458 cond = (e->flags & ELEMENT_CONDITIONAL ||
1459 (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : "";
1460 act = e->action ? "_ACT" : "";
1461 switch (e->compound) {
1462 case ANY:
1463 render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,",
1464 cond, act, skippable ? "_OR_SKIP" : "");
1465 if (e->name)
1466 render_more(out, "\t\t// %s", e->name->content);
1467 render_more(out, "\n");
1468 goto dont_render_tag;
1469
1470 case TAG_OVERRIDE:
1471 render_element(out, e->children, e);
1472 return;
1473
1474 case SEQUENCE:
1475 case SEQUENCE_OF:
1476 case SET:
1477 case SET_OF:
1478 render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
1479 cond,
1480 outofline ? "_JUMP" : "",
1481 skippable ? "_OR_SKIP" : "");
1482 break;
1483
1484 case CHOICE:
1485 goto dont_render_tag;
1486
1487 case TYPE_REF:
1488 if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0)
1489 goto dont_render_tag;
1490 default:
1491 render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
1492 cond, act,
1493 skippable ? "_OR_SKIP" : "");
1494 break;
1495 }
1496
1497 x = tag ?: e;
1498 if (x->name)
1499 render_more(out, "\t\t// %s", x->name->content);
1500 render_more(out, "\n");
1501
1502
1503 if (!tag || !(tag->flags & ELEMENT_TAG_SPECIFIED))
1504 tag = e;
1505
1506 if (tag->class == ASN1_UNIV &&
1507 tag->tag != 14 &&
1508 tag->tag != 15 &&
1509 tag->tag != 31)
1510 render_opcode(out, "_tag(%s, %s, %s),\n",
1511 asn1_classes[tag->class],
1512 asn1_methods[tag->method | e->method],
1513 asn1_universal_tags[tag->tag]);
1514 else
1515 render_opcode(out, "_tagn(%s, %s, %2u),\n",
1516 asn1_classes[tag->class],
1517 asn1_methods[tag->method | e->method],
1518 tag->tag);
1519 tag = NULL;
1520 dont_render_tag:
1521
1522
1523 switch (e->compound) {
1524 case TYPE_REF:
1525 render_element(out, e->type->type->element, tag);
1526 if (e->action)
1527 render_opcode(out, "ASN1_OP_%sACT,\n",
1528 skippable ? "MAYBE_" : "");
1529 break;
1530
1531 case SEQUENCE:
1532 if (outofline) {
1533
1534
1535 render_opcode(out, "_jump_target(%u),", e->entry_index);
1536 if (e->type_def && e->type_def->name)
1537 render_more(out, "\t\t// --> %s",
1538 e->type_def->name->content);
1539 render_more(out, "\n");
1540 if (!(e->flags & ELEMENT_RENDERED)) {
1541 e->flags |= ELEMENT_RENDERED;
1542 *render_list_p = e;
1543 render_list_p = &e->render_next;
1544 }
1545 return;
1546 } else {
1547
1548 render_depth++;
1549 for (ec = e->children; ec; ec = ec->next)
1550 render_element(out, ec, NULL);
1551 render_depth--;
1552 render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
1553 }
1554 break;
1555
1556 case SEQUENCE_OF:
1557 case SET_OF:
1558 if (outofline) {
1559
1560
1561 render_opcode(out, "_jump_target(%u),", e->entry_index);
1562 if (e->type_def && e->type_def->name)
1563 render_more(out, "\t\t// --> %s",
1564 e->type_def->name->content);
1565 render_more(out, "\n");
1566 if (!(e->flags & ELEMENT_RENDERED)) {
1567 e->flags |= ELEMENT_RENDERED;
1568 *render_list_p = e;
1569 render_list_p = &e->render_next;
1570 }
1571 return;
1572 } else {
1573
1574 entry = nr_entries;
1575 render_depth++;
1576 render_element(out, e->children, NULL);
1577 render_depth--;
1578 if (e->compound == SEQUENCE_OF)
1579 render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
1580 else
1581 render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
1582 render_opcode(out, "_jump_target(%u),\n", entry);
1583 }
1584 break;
1585
1586 case SET:
1587
1588
1589
1590
1591
1592
1593 fprintf(stderr, "The ASN.1 SET type is not currently supported.\n");
1594 exit(1);
1595
1596 case CHOICE:
1597 for (ec = e->children; ec; ec = ec->next)
1598 render_element(out, ec, ec);
1599 if (!skippable)
1600 render_opcode(out, "ASN1_OP_COND_FAIL,\n");
1601 if (e->action)
1602 render_opcode(out, "ASN1_OP_ACT,\n");
1603 break;
1604
1605 default:
1606 break;
1607 }
1608
1609 if (e->action)
1610 render_opcode(out, "_action(ACT_%s),\n", e->action->name);
1611 }