asn1_compiler.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560
  1. /* Simplified ASN.1 notation parser
  2. *
  3. * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public Licence
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the Licence, or (at your option) any later version.
  10. */
  11. #include <stdarg.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <stdint.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17. #include <unistd.h>
  18. #include <fcntl.h>
  19. #include <sys/stat.h>
  20. #include <linux/asn1_ber_bytecode.h>
  21. enum token_type {
  22. DIRECTIVE_ABSENT,
  23. DIRECTIVE_ALL,
  24. DIRECTIVE_ANY,
  25. DIRECTIVE_APPLICATION,
  26. DIRECTIVE_AUTOMATIC,
  27. DIRECTIVE_BEGIN,
  28. DIRECTIVE_BIT,
  29. DIRECTIVE_BMPString,
  30. DIRECTIVE_BOOLEAN,
  31. DIRECTIVE_BY,
  32. DIRECTIVE_CHARACTER,
  33. DIRECTIVE_CHOICE,
  34. DIRECTIVE_CLASS,
  35. DIRECTIVE_COMPONENT,
  36. DIRECTIVE_COMPONENTS,
  37. DIRECTIVE_CONSTRAINED,
  38. DIRECTIVE_CONTAINING,
  39. DIRECTIVE_DEFAULT,
  40. DIRECTIVE_DEFINED,
  41. DIRECTIVE_DEFINITIONS,
  42. DIRECTIVE_EMBEDDED,
  43. DIRECTIVE_ENCODED,
  44. DIRECTIVE_ENCODING_CONTROL,
  45. DIRECTIVE_END,
  46. DIRECTIVE_ENUMERATED,
  47. DIRECTIVE_EXCEPT,
  48. DIRECTIVE_EXPLICIT,
  49. DIRECTIVE_EXPORTS,
  50. DIRECTIVE_EXTENSIBILITY,
  51. DIRECTIVE_EXTERNAL,
  52. DIRECTIVE_FALSE,
  53. DIRECTIVE_FROM,
  54. DIRECTIVE_GeneralString,
  55. DIRECTIVE_GeneralizedTime,
  56. DIRECTIVE_GraphicString,
  57. DIRECTIVE_IA5String,
  58. DIRECTIVE_IDENTIFIER,
  59. DIRECTIVE_IMPLICIT,
  60. DIRECTIVE_IMPLIED,
  61. DIRECTIVE_IMPORTS,
  62. DIRECTIVE_INCLUDES,
  63. DIRECTIVE_INSTANCE,
  64. DIRECTIVE_INSTRUCTIONS,
  65. DIRECTIVE_INTEGER,
  66. DIRECTIVE_INTERSECTION,
  67. DIRECTIVE_ISO646String,
  68. DIRECTIVE_MAX,
  69. DIRECTIVE_MIN,
  70. DIRECTIVE_MINUS_INFINITY,
  71. DIRECTIVE_NULL,
  72. DIRECTIVE_NumericString,
  73. DIRECTIVE_OBJECT,
  74. DIRECTIVE_OCTET,
  75. DIRECTIVE_OF,
  76. DIRECTIVE_OPTIONAL,
  77. DIRECTIVE_ObjectDescriptor,
  78. DIRECTIVE_PATTERN,
  79. DIRECTIVE_PDV,
  80. DIRECTIVE_PLUS_INFINITY,
  81. DIRECTIVE_PRESENT,
  82. DIRECTIVE_PRIVATE,
  83. DIRECTIVE_PrintableString,
  84. DIRECTIVE_REAL,
  85. DIRECTIVE_RELATIVE_OID,
  86. DIRECTIVE_SEQUENCE,
  87. DIRECTIVE_SET,
  88. DIRECTIVE_SIZE,
  89. DIRECTIVE_STRING,
  90. DIRECTIVE_SYNTAX,
  91. DIRECTIVE_T61String,
  92. DIRECTIVE_TAGS,
  93. DIRECTIVE_TRUE,
  94. DIRECTIVE_TeletexString,
  95. DIRECTIVE_UNION,
  96. DIRECTIVE_UNIQUE,
  97. DIRECTIVE_UNIVERSAL,
  98. DIRECTIVE_UTCTime,
  99. DIRECTIVE_UTF8String,
  100. DIRECTIVE_UniversalString,
  101. DIRECTIVE_VideotexString,
  102. DIRECTIVE_VisibleString,
  103. DIRECTIVE_WITH,
  104. NR__DIRECTIVES,
  105. TOKEN_ASSIGNMENT = NR__DIRECTIVES,
  106. TOKEN_OPEN_CURLY,
  107. TOKEN_CLOSE_CURLY,
  108. TOKEN_OPEN_SQUARE,
  109. TOKEN_CLOSE_SQUARE,
  110. TOKEN_OPEN_ACTION,
  111. TOKEN_CLOSE_ACTION,
  112. TOKEN_COMMA,
  113. TOKEN_NUMBER,
  114. TOKEN_TYPE_NAME,
  115. TOKEN_ELEMENT_NAME,
  116. NR__TOKENS
  117. };
  118. static const unsigned char token_to_tag[NR__TOKENS] = {
  119. /* EOC goes first */
  120. [DIRECTIVE_BOOLEAN] = ASN1_BOOL,
  121. [DIRECTIVE_INTEGER] = ASN1_INT,
  122. [DIRECTIVE_BIT] = ASN1_BTS,
  123. [DIRECTIVE_OCTET] = ASN1_OTS,
  124. [DIRECTIVE_NULL] = ASN1_NULL,
  125. [DIRECTIVE_OBJECT] = ASN1_OID,
  126. [DIRECTIVE_ObjectDescriptor] = ASN1_ODE,
  127. [DIRECTIVE_EXTERNAL] = ASN1_EXT,
  128. [DIRECTIVE_REAL] = ASN1_REAL,
  129. [DIRECTIVE_ENUMERATED] = ASN1_ENUM,
  130. [DIRECTIVE_EMBEDDED] = 0,
  131. [DIRECTIVE_UTF8String] = ASN1_UTF8STR,
  132. [DIRECTIVE_RELATIVE_OID] = ASN1_RELOID,
  133. /* 14 */
  134. /* 15 */
  135. [DIRECTIVE_SEQUENCE] = ASN1_SEQ,
  136. [DIRECTIVE_SET] = ASN1_SET,
  137. [DIRECTIVE_NumericString] = ASN1_NUMSTR,
  138. [DIRECTIVE_PrintableString] = ASN1_PRNSTR,
  139. [DIRECTIVE_T61String] = ASN1_TEXSTR,
  140. [DIRECTIVE_TeletexString] = ASN1_TEXSTR,
  141. [DIRECTIVE_VideotexString] = ASN1_VIDSTR,
  142. [DIRECTIVE_IA5String] = ASN1_IA5STR,
  143. [DIRECTIVE_UTCTime] = ASN1_UNITIM,
  144. [DIRECTIVE_GeneralizedTime] = ASN1_GENTIM,
  145. [DIRECTIVE_GraphicString] = ASN1_GRASTR,
  146. [DIRECTIVE_VisibleString] = ASN1_VISSTR,
  147. [DIRECTIVE_GeneralString] = ASN1_GENSTR,
  148. [DIRECTIVE_UniversalString] = ASN1_UNITIM,
  149. [DIRECTIVE_CHARACTER] = ASN1_CHRSTR,
  150. [DIRECTIVE_BMPString] = ASN1_BMPSTR,
  151. };
  152. static const char asn1_classes[4][5] = {
  153. [ASN1_UNIV] = "UNIV",
  154. [ASN1_APPL] = "APPL",
  155. [ASN1_CONT] = "CONT",
  156. [ASN1_PRIV] = "PRIV"
  157. };
  158. static const char asn1_methods[2][5] = {
  159. [ASN1_UNIV] = "PRIM",
  160. [ASN1_APPL] = "CONS"
  161. };
  162. static const char *const asn1_universal_tags[32] = {
  163. "EOC",
  164. "BOOL",
  165. "INT",
  166. "BTS",
  167. "OTS",
  168. "NULL",
  169. "OID",
  170. "ODE",
  171. "EXT",
  172. "REAL",
  173. "ENUM",
  174. "EPDV",
  175. "UTF8STR",
  176. "RELOID",
  177. NULL, /* 14 */
  178. NULL, /* 15 */
  179. "SEQ",
  180. "SET",
  181. "NUMSTR",
  182. "PRNSTR",
  183. "TEXSTR",
  184. "VIDSTR",
  185. "IA5STR",
  186. "UNITIM",
  187. "GENTIM",
  188. "GRASTR",
  189. "VISSTR",
  190. "GENSTR",
  191. "UNISTR",
  192. "CHRSTR",
  193. "BMPSTR",
  194. NULL /* 31 */
  195. };
  196. static const char *filename;
  197. static const char *grammar_name;
  198. static const char *outputname;
  199. static const char *headername;
  200. static const char *const directives[NR__DIRECTIVES] = {
  201. #define _(X) [DIRECTIVE_##X] = #X
  202. _(ABSENT),
  203. _(ALL),
  204. _(ANY),
  205. _(APPLICATION),
  206. _(AUTOMATIC),
  207. _(BEGIN),
  208. _(BIT),
  209. _(BMPString),
  210. _(BOOLEAN),
  211. _(BY),
  212. _(CHARACTER),
  213. _(CHOICE),
  214. _(CLASS),
  215. _(COMPONENT),
  216. _(COMPONENTS),
  217. _(CONSTRAINED),
  218. _(CONTAINING),
  219. _(DEFAULT),
  220. _(DEFINED),
  221. _(DEFINITIONS),
  222. _(EMBEDDED),
  223. _(ENCODED),
  224. [DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL",
  225. _(END),
  226. _(ENUMERATED),
  227. _(EXCEPT),
  228. _(EXPLICIT),
  229. _(EXPORTS),
  230. _(EXTENSIBILITY),
  231. _(EXTERNAL),
  232. _(FALSE),
  233. _(FROM),
  234. _(GeneralString),
  235. _(GeneralizedTime),
  236. _(GraphicString),
  237. _(IA5String),
  238. _(IDENTIFIER),
  239. _(IMPLICIT),
  240. _(IMPLIED),
  241. _(IMPORTS),
  242. _(INCLUDES),
  243. _(INSTANCE),
  244. _(INSTRUCTIONS),
  245. _(INTEGER),
  246. _(INTERSECTION),
  247. _(ISO646String),
  248. _(MAX),
  249. _(MIN),
  250. [DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY",
  251. [DIRECTIVE_NULL] = "NULL",
  252. _(NumericString),
  253. _(OBJECT),
  254. _(OCTET),
  255. _(OF),
  256. _(OPTIONAL),
  257. _(ObjectDescriptor),
  258. _(PATTERN),
  259. _(PDV),
  260. [DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY",
  261. _(PRESENT),
  262. _(PRIVATE),
  263. _(PrintableString),
  264. _(REAL),
  265. [DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID",
  266. _(SEQUENCE),
  267. _(SET),
  268. _(SIZE),
  269. _(STRING),
  270. _(SYNTAX),
  271. _(T61String),
  272. _(TAGS),
  273. _(TRUE),
  274. _(TeletexString),
  275. _(UNION),
  276. _(UNIQUE),
  277. _(UNIVERSAL),
  278. _(UTCTime),
  279. _(UTF8String),
  280. _(UniversalString),
  281. _(VideotexString),
  282. _(VisibleString),
  283. _(WITH)
  284. };
  285. struct action {
  286. struct action *next;
  287. unsigned char index;
  288. char name[];
  289. };
  290. static struct action *action_list;
  291. static unsigned nr_actions;
  292. struct token {
  293. unsigned short line;
  294. enum token_type token_type : 8;
  295. unsigned char size;
  296. struct action *action;
  297. const char *value;
  298. struct type *type;
  299. };
  300. static struct token *token_list;
  301. static unsigned nr_tokens;
  302. static _Bool verbose;
  303. #define debug(fmt, ...) do { if (verbose) printf(fmt, ## __VA_ARGS__); } while (0)
  304. static int directive_compare(const void *_key, const void *_pdir)
  305. {
  306. const struct token *token = _key;
  307. const char *const *pdir = _pdir, *dir = *pdir;
  308. size_t dlen, clen;
  309. int val;
  310. dlen = strlen(dir);
  311. clen = (dlen < token->size) ? dlen : token->size;
  312. //debug("cmp(%*.*s,%s) = ",
  313. // (int)token->size, (int)token->size, token->value,
  314. // dir);
  315. val = memcmp(token->value, dir, clen);
  316. if (val != 0) {
  317. //debug("%d [cmp]\n", val);
  318. return val;
  319. }
  320. if (dlen == token->size) {
  321. //debug("0\n");
  322. return 0;
  323. }
  324. //debug("%d\n", (int)dlen - (int)token->size);
  325. return dlen - token->size; /* shorter -> negative */
  326. }
  327. /*
  328. * Tokenise an ASN.1 grammar
  329. */
  330. static void tokenise(char *buffer, char *end)
  331. {
  332. struct token *tokens;
  333. char *line, *nl, *p, *q;
  334. unsigned tix, lineno;
  335. /* Assume we're going to have half as many tokens as we have
  336. * characters
  337. */
  338. token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token));
  339. if (!tokens) {
  340. perror(NULL);
  341. exit(1);
  342. }
  343. tix = 0;
  344. lineno = 0;
  345. while (buffer < end) {
  346. /* First of all, break out a line */
  347. lineno++;
  348. line = buffer;
  349. nl = memchr(line, '\n', end - buffer);
  350. if (!nl) {
  351. buffer = nl = end;
  352. } else {
  353. buffer = nl + 1;
  354. *nl = '\0';
  355. }
  356. /* Remove "--" comments */
  357. p = line;
  358. next_comment:
  359. while ((p = memchr(p, '-', nl - p))) {
  360. if (p[1] == '-') {
  361. /* Found a comment; see if there's a terminator */
  362. q = p + 2;
  363. while ((q = memchr(q, '-', nl - q))) {
  364. if (q[1] == '-') {
  365. /* There is - excise the comment */
  366. q += 2;
  367. memmove(p, q, nl - q);
  368. goto next_comment;
  369. }
  370. q++;
  371. }
  372. *p = '\0';
  373. nl = p;
  374. break;
  375. } else {
  376. p++;
  377. }
  378. }
  379. p = line;
  380. while (p < nl) {
  381. /* Skip white space */
  382. while (p < nl && isspace(*p))
  383. *(p++) = 0;
  384. if (p >= nl)
  385. break;
  386. tokens[tix].line = lineno;
  387. tokens[tix].value = p;
  388. /* Handle string tokens */
  389. if (isalpha(*p)) {
  390. const char **dir;
  391. /* Can be a directive, type name or element
  392. * name. Find the end of the name.
  393. */
  394. q = p + 1;
  395. while (q < nl && (isalnum(*q) || *q == '-' || *q == '_'))
  396. q++;
  397. tokens[tix].size = q - p;
  398. p = q;
  399. /* If it begins with a lowercase letter then
  400. * it's an element name
  401. */
  402. if (islower(tokens[tix].value[0])) {
  403. tokens[tix++].token_type = TOKEN_ELEMENT_NAME;
  404. continue;
  405. }
  406. /* Otherwise we need to search the directive
  407. * table
  408. */
  409. dir = bsearch(&tokens[tix], directives,
  410. sizeof(directives) / sizeof(directives[1]),
  411. sizeof(directives[1]),
  412. directive_compare);
  413. if (dir) {
  414. tokens[tix++].token_type = dir - directives;
  415. continue;
  416. }
  417. tokens[tix++].token_type = TOKEN_TYPE_NAME;
  418. continue;
  419. }
  420. /* Handle numbers */
  421. if (isdigit(*p)) {
  422. /* Find the end of the number */
  423. q = p + 1;
  424. while (q < nl && (isdigit(*q)))
  425. q++;
  426. tokens[tix].size = q - p;
  427. p = q;
  428. tokens[tix++].token_type = TOKEN_NUMBER;
  429. continue;
  430. }
  431. if (nl - p >= 3) {
  432. if (memcmp(p, "::=", 3) == 0) {
  433. p += 3;
  434. tokens[tix].size = 3;
  435. tokens[tix++].token_type = TOKEN_ASSIGNMENT;
  436. continue;
  437. }
  438. }
  439. if (nl - p >= 2) {
  440. if (memcmp(p, "({", 2) == 0) {
  441. p += 2;
  442. tokens[tix].size = 2;
  443. tokens[tix++].token_type = TOKEN_OPEN_ACTION;
  444. continue;
  445. }
  446. if (memcmp(p, "})", 2) == 0) {
  447. p += 2;
  448. tokens[tix].size = 2;
  449. tokens[tix++].token_type = TOKEN_CLOSE_ACTION;
  450. continue;
  451. }
  452. }
  453. if (nl - p >= 1) {
  454. tokens[tix].size = 1;
  455. switch (*p) {
  456. case '{':
  457. p += 1;
  458. tokens[tix++].token_type = TOKEN_OPEN_CURLY;
  459. continue;
  460. case '}':
  461. p += 1;
  462. tokens[tix++].token_type = TOKEN_CLOSE_CURLY;
  463. continue;
  464. case '[':
  465. p += 1;
  466. tokens[tix++].token_type = TOKEN_OPEN_SQUARE;
  467. continue;
  468. case ']':
  469. p += 1;
  470. tokens[tix++].token_type = TOKEN_CLOSE_SQUARE;
  471. continue;
  472. case ',':
  473. p += 1;
  474. tokens[tix++].token_type = TOKEN_COMMA;
  475. continue;
  476. default:
  477. break;
  478. }
  479. }
  480. fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n",
  481. filename, lineno, *p);
  482. exit(1);
  483. }
  484. }
  485. nr_tokens = tix;
  486. debug("Extracted %u tokens\n", nr_tokens);
  487. #if 0
  488. {
  489. int n;
  490. for (n = 0; n < nr_tokens; n++)
  491. debug("Token %3u: '%*.*s'\n",
  492. n,
  493. (int)token_list[n].size, (int)token_list[n].size,
  494. token_list[n].value);
  495. }
  496. #endif
  497. }
  498. static void build_type_list(void);
  499. static void parse(void);
  500. static void render(FILE *out, FILE *hdr);
  501. /*
  502. *
  503. */
  504. int main(int argc, char **argv)
  505. {
  506. struct stat st;
  507. ssize_t readlen;
  508. FILE *out, *hdr;
  509. char *buffer, *p;
  510. char *kbuild_verbose;
  511. int fd;
  512. if (argc != 4) {
  513. fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n",
  514. argv[0]);
  515. exit(2);
  516. }
  517. kbuild_verbose = getenv("KBUILD_VERBOSE");
  518. if (kbuild_verbose)
  519. verbose = atoi(kbuild_verbose);
  520. filename = argv[1];
  521. outputname = argv[2];
  522. headername = argv[3];
  523. fd = open(filename, O_RDONLY);
  524. if (fd < 0) {
  525. perror(filename);
  526. exit(1);
  527. }
  528. if (fstat(fd, &st) < 0) {
  529. perror(filename);
  530. exit(1);
  531. }
  532. if (!(buffer = malloc(st.st_size + 1))) {
  533. perror(NULL);
  534. exit(1);
  535. }
  536. if ((readlen = read(fd, buffer, st.st_size)) < 0) {
  537. perror(filename);
  538. exit(1);
  539. }
  540. if (close(fd) < 0) {
  541. perror(filename);
  542. exit(1);
  543. }
  544. if (readlen != st.st_size) {
  545. fprintf(stderr, "%s: Short read\n", filename);
  546. exit(1);
  547. }
  548. p = strrchr(argv[1], '/');
  549. p = p ? p + 1 : argv[1];
  550. grammar_name = strdup(p);
  551. if (!p) {
  552. perror(NULL);
  553. exit(1);
  554. }
  555. p = strchr(grammar_name, '.');
  556. if (p)
  557. *p = '\0';
  558. buffer[readlen] = 0;
  559. tokenise(buffer, buffer + readlen);
  560. build_type_list();
  561. parse();
  562. out = fopen(outputname, "w");
  563. if (!out) {
  564. perror(outputname);
  565. exit(1);
  566. }
  567. hdr = fopen(headername, "w");
  568. if (!out) {
  569. perror(headername);
  570. exit(1);
  571. }
  572. render(out, hdr);
  573. if (fclose(out) < 0) {
  574. perror(outputname);
  575. exit(1);
  576. }
  577. if (fclose(hdr) < 0) {
  578. perror(headername);
  579. exit(1);
  580. }
  581. return 0;
  582. }
  583. enum compound {
  584. NOT_COMPOUND,
  585. SET,
  586. SET_OF,
  587. SEQUENCE,
  588. SEQUENCE_OF,
  589. CHOICE,
  590. ANY,
  591. TYPE_REF,
  592. TAG_OVERRIDE
  593. };
  594. struct element {
  595. struct type *type_def;
  596. struct token *name;
  597. struct token *type;
  598. struct action *action;
  599. struct element *children;
  600. struct element *next;
  601. struct element *render_next;
  602. struct element *list_next;
  603. uint8_t n_elements;
  604. enum compound compound : 8;
  605. enum asn1_class class : 8;
  606. enum asn1_method method : 8;
  607. uint8_t tag;
  608. unsigned entry_index;
  609. unsigned flags;
  610. #define ELEMENT_IMPLICIT 0x0001
  611. #define ELEMENT_EXPLICIT 0x0002
  612. #define ELEMENT_TAG_SPECIFIED 0x0004
  613. #define ELEMENT_RENDERED 0x0008
  614. #define ELEMENT_SKIPPABLE 0x0010
  615. #define ELEMENT_CONDITIONAL 0x0020
  616. };
  617. struct type {
  618. struct token *name;
  619. struct token *def;
  620. struct element *element;
  621. unsigned ref_count;
  622. unsigned flags;
  623. #define TYPE_STOP_MARKER 0x0001
  624. #define TYPE_BEGIN 0x0002
  625. };
  626. static struct type *type_list;
  627. static struct type **type_index;
  628. static unsigned nr_types;
  629. static int type_index_compare(const void *_a, const void *_b)
  630. {
  631. const struct type *const *a = _a, *const *b = _b;
  632. if ((*a)->name->size != (*b)->name->size)
  633. return (*a)->name->size - (*b)->name->size;
  634. else
  635. return memcmp((*a)->name->value, (*b)->name->value,
  636. (*a)->name->size);
  637. }
  638. static int type_finder(const void *_key, const void *_ti)
  639. {
  640. const struct token *token = _key;
  641. const struct type *const *ti = _ti;
  642. const struct type *type = *ti;
  643. if (token->size != type->name->size)
  644. return token->size - type->name->size;
  645. else
  646. return memcmp(token->value, type->name->value,
  647. token->size);
  648. }
  649. /*
  650. * Build up a list of types and a sorted index to that list.
  651. */
  652. static void build_type_list(void)
  653. {
  654. struct type *types;
  655. unsigned nr, t, n;
  656. nr = 0;
  657. for (n = 0; n < nr_tokens - 1; n++)
  658. if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
  659. token_list[n + 1].token_type == TOKEN_ASSIGNMENT)
  660. nr++;
  661. if (nr == 0) {
  662. fprintf(stderr, "%s: No defined types\n", filename);
  663. exit(1);
  664. }
  665. nr_types = nr;
  666. types = type_list = calloc(nr + 1, sizeof(type_list[0]));
  667. if (!type_list) {
  668. perror(NULL);
  669. exit(1);
  670. }
  671. type_index = calloc(nr, sizeof(type_index[0]));
  672. if (!type_index) {
  673. perror(NULL);
  674. exit(1);
  675. }
  676. t = 0;
  677. types[t].flags |= TYPE_BEGIN;
  678. for (n = 0; n < nr_tokens - 1; n++) {
  679. if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
  680. token_list[n + 1].token_type == TOKEN_ASSIGNMENT) {
  681. types[t].name = &token_list[n];
  682. type_index[t] = &types[t];
  683. t++;
  684. }
  685. }
  686. types[t].name = &token_list[n + 1];
  687. types[t].flags |= TYPE_STOP_MARKER;
  688. qsort(type_index, nr, sizeof(type_index[0]), type_index_compare);
  689. debug("Extracted %u types\n", nr_types);
  690. #if 0
  691. for (n = 0; n < nr_types; n++) {
  692. struct type *type = type_index[n];
  693. debug("- %*.*s\n",
  694. (int)type->name->size,
  695. (int)type->name->size,
  696. type->name->value);
  697. }
  698. #endif
  699. }
  700. static struct element *parse_type(struct token **_cursor, struct token *stop,
  701. struct token *name);
  702. /*
  703. * Parse the token stream
  704. */
  705. static void parse(void)
  706. {
  707. struct token *cursor;
  708. struct type *type;
  709. /* Parse one type definition statement at a time */
  710. type = type_list;
  711. do {
  712. cursor = type->name;
  713. if (cursor[0].token_type != TOKEN_TYPE_NAME ||
  714. cursor[1].token_type != TOKEN_ASSIGNMENT)
  715. abort();
  716. cursor += 2;
  717. type->element = parse_type(&cursor, type[1].name, NULL);
  718. type->element->type_def = type;
  719. if (cursor != type[1].name) {
  720. fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n",
  721. filename, cursor->line,
  722. (int)cursor->size, (int)cursor->size, cursor->value);
  723. exit(1);
  724. }
  725. } while (type++, !(type->flags & TYPE_STOP_MARKER));
  726. debug("Extracted %u actions\n", nr_actions);
  727. }
  728. static struct element *element_list;
  729. static struct element *alloc_elem(struct token *type)
  730. {
  731. struct element *e = calloc(1, sizeof(*e));
  732. if (!e) {
  733. perror(NULL);
  734. exit(1);
  735. }
  736. e->list_next = element_list;
  737. element_list = e;
  738. return e;
  739. }
  740. static struct element *parse_compound(struct token **_cursor, struct token *end,
  741. int alternates);
  742. /*
  743. * Parse one type definition statement
  744. */
  745. static struct element *parse_type(struct token **_cursor, struct token *end,
  746. struct token *name)
  747. {
  748. struct element *top, *element;
  749. struct action *action, **ppaction;
  750. struct token *cursor = *_cursor;
  751. struct type **ref;
  752. char *p;
  753. int labelled = 0, implicit = 0;
  754. top = element = alloc_elem(cursor);
  755. element->class = ASN1_UNIV;
  756. element->method = ASN1_PRIM;
  757. element->tag = token_to_tag[cursor->token_type];
  758. element->name = name;
  759. /* Extract the tag value if one given */
  760. if (cursor->token_type == TOKEN_OPEN_SQUARE) {
  761. cursor++;
  762. if (cursor >= end)
  763. goto overrun_error;
  764. switch (cursor->token_type) {
  765. case DIRECTIVE_UNIVERSAL:
  766. element->class = ASN1_UNIV;
  767. cursor++;
  768. break;
  769. case DIRECTIVE_APPLICATION:
  770. element->class = ASN1_APPL;
  771. cursor++;
  772. break;
  773. case TOKEN_NUMBER:
  774. element->class = ASN1_CONT;
  775. break;
  776. case DIRECTIVE_PRIVATE:
  777. element->class = ASN1_PRIV;
  778. cursor++;
  779. break;
  780. default:
  781. fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n",
  782. filename, cursor->line,
  783. (int)cursor->size, (int)cursor->size, cursor->value);
  784. exit(1);
  785. }
  786. if (cursor >= end)
  787. goto overrun_error;
  788. if (cursor->token_type != TOKEN_NUMBER) {
  789. fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n",
  790. filename, cursor->line,
  791. (int)cursor->size, (int)cursor->size, cursor->value);
  792. exit(1);
  793. }
  794. element->tag &= ~0x1f;
  795. element->tag |= strtoul(cursor->value, &p, 10);
  796. element->flags |= ELEMENT_TAG_SPECIFIED;
  797. if (p - cursor->value != cursor->size)
  798. abort();
  799. cursor++;
  800. if (cursor >= end)
  801. goto overrun_error;
  802. if (cursor->token_type != TOKEN_CLOSE_SQUARE) {
  803. fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n",
  804. filename, cursor->line,
  805. (int)cursor->size, (int)cursor->size, cursor->value);
  806. exit(1);
  807. }
  808. cursor++;
  809. if (cursor >= end)
  810. goto overrun_error;
  811. labelled = 1;
  812. }
  813. /* Handle implicit and explicit markers */
  814. if (cursor->token_type == DIRECTIVE_IMPLICIT) {
  815. element->flags |= ELEMENT_IMPLICIT;
  816. implicit = 1;
  817. cursor++;
  818. if (cursor >= end)
  819. goto overrun_error;
  820. } else if (cursor->token_type == DIRECTIVE_EXPLICIT) {
  821. element->flags |= ELEMENT_EXPLICIT;
  822. cursor++;
  823. if (cursor >= end)
  824. goto overrun_error;
  825. }
  826. if (labelled) {
  827. if (!implicit)
  828. element->method |= ASN1_CONS;
  829. element->compound = implicit ? TAG_OVERRIDE : SEQUENCE;
  830. element->children = alloc_elem(cursor);
  831. element = element->children;
  832. element->class = ASN1_UNIV;
  833. element->method = ASN1_PRIM;
  834. element->tag = token_to_tag[cursor->token_type];
  835. element->name = name;
  836. }
  837. /* Extract the type we're expecting here */
  838. element->type = cursor;
  839. switch (cursor->token_type) {
  840. case DIRECTIVE_ANY:
  841. element->compound = ANY;
  842. cursor++;
  843. break;
  844. case DIRECTIVE_NULL:
  845. case DIRECTIVE_BOOLEAN:
  846. case DIRECTIVE_ENUMERATED:
  847. case DIRECTIVE_INTEGER:
  848. element->compound = NOT_COMPOUND;
  849. cursor++;
  850. break;
  851. case DIRECTIVE_EXTERNAL:
  852. element->method = ASN1_CONS;
  853. case DIRECTIVE_BMPString:
  854. case DIRECTIVE_GeneralString:
  855. case DIRECTIVE_GraphicString:
  856. case DIRECTIVE_IA5String:
  857. case DIRECTIVE_ISO646String:
  858. case DIRECTIVE_NumericString:
  859. case DIRECTIVE_PrintableString:
  860. case DIRECTIVE_T61String:
  861. case DIRECTIVE_TeletexString:
  862. case DIRECTIVE_UniversalString:
  863. case DIRECTIVE_UTF8String:
  864. case DIRECTIVE_VideotexString:
  865. case DIRECTIVE_VisibleString:
  866. case DIRECTIVE_ObjectDescriptor:
  867. case DIRECTIVE_GeneralizedTime:
  868. case DIRECTIVE_UTCTime:
  869. element->compound = NOT_COMPOUND;
  870. cursor++;
  871. break;
  872. case DIRECTIVE_BIT:
  873. case DIRECTIVE_OCTET:
  874. element->compound = NOT_COMPOUND;
  875. cursor++;
  876. if (cursor >= end)
  877. goto overrun_error;
  878. if (cursor->token_type != DIRECTIVE_STRING)
  879. goto parse_error;
  880. cursor++;
  881. break;
  882. case DIRECTIVE_OBJECT:
  883. element->compound = NOT_COMPOUND;
  884. cursor++;
  885. if (cursor >= end)
  886. goto overrun_error;
  887. if (cursor->token_type != DIRECTIVE_IDENTIFIER)
  888. goto parse_error;
  889. cursor++;
  890. break;
  891. case TOKEN_TYPE_NAME:
  892. element->compound = TYPE_REF;
  893. ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]),
  894. type_finder);
  895. if (!ref) {
  896. fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n",
  897. filename, cursor->line,
  898. (int)cursor->size, (int)cursor->size, cursor->value);
  899. exit(1);
  900. }
  901. cursor->type = *ref;
  902. (*ref)->ref_count++;
  903. cursor++;
  904. break;
  905. case DIRECTIVE_CHOICE:
  906. element->compound = CHOICE;
  907. cursor++;
  908. element->children = parse_compound(&cursor, end, 1);
  909. break;
  910. case DIRECTIVE_SEQUENCE:
  911. element->compound = SEQUENCE;
  912. element->method = ASN1_CONS;
  913. cursor++;
  914. if (cursor >= end)
  915. goto overrun_error;
  916. if (cursor->token_type == DIRECTIVE_OF) {
  917. element->compound = SEQUENCE_OF;
  918. cursor++;
  919. if (cursor >= end)
  920. goto overrun_error;
  921. element->children = parse_type(&cursor, end, NULL);
  922. } else {
  923. element->children = parse_compound(&cursor, end, 0);
  924. }
  925. break;
  926. case DIRECTIVE_SET:
  927. element->compound = SET;
  928. element->method = ASN1_CONS;
  929. cursor++;
  930. if (cursor >= end)
  931. goto overrun_error;
  932. if (cursor->token_type == DIRECTIVE_OF) {
  933. element->compound = SET_OF;
  934. cursor++;
  935. if (cursor >= end)
  936. goto parse_error;
  937. element->children = parse_type(&cursor, end, NULL);
  938. } else {
  939. element->children = parse_compound(&cursor, end, 1);
  940. }
  941. break;
  942. default:
  943. fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n",
  944. filename, cursor->line,
  945. (int)cursor->size, (int)cursor->size, cursor->value);
  946. exit(1);
  947. }
  948. /* Handle elements that are optional */
  949. if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL ||
  950. cursor->token_type == DIRECTIVE_DEFAULT)
  951. ) {
  952. cursor++;
  953. top->flags |= ELEMENT_SKIPPABLE;
  954. }
  955. if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) {
  956. cursor++;
  957. if (cursor >= end)
  958. goto overrun_error;
  959. if (cursor->token_type != TOKEN_ELEMENT_NAME) {
  960. fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n",
  961. filename, cursor->line,
  962. (int)cursor->size, (int)cursor->size, cursor->value);
  963. exit(1);
  964. }
  965. action = malloc(sizeof(struct action) + cursor->size + 1);
  966. if (!action) {
  967. perror(NULL);
  968. exit(1);
  969. }
  970. action->index = 0;
  971. memcpy(action->name, cursor->value, cursor->size);
  972. action->name[cursor->size] = 0;
  973. for (ppaction = &action_list;
  974. *ppaction;
  975. ppaction = &(*ppaction)->next
  976. ) {
  977. int cmp = strcmp(action->name, (*ppaction)->name);
  978. if (cmp == 0) {
  979. free(action);
  980. action = *ppaction;
  981. goto found;
  982. }
  983. if (cmp < 0) {
  984. action->next = *ppaction;
  985. *ppaction = action;
  986. nr_actions++;
  987. goto found;
  988. }
  989. }
  990. action->next = NULL;
  991. *ppaction = action;
  992. nr_actions++;
  993. found:
  994. element->action = action;
  995. cursor->action = action;
  996. cursor++;
  997. if (cursor >= end)
  998. goto overrun_error;
  999. if (cursor->token_type != TOKEN_CLOSE_ACTION) {
  1000. fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n",
  1001. filename, cursor->line,
  1002. (int)cursor->size, (int)cursor->size, cursor->value);
  1003. exit(1);
  1004. }
  1005. cursor++;
  1006. }
  1007. *_cursor = cursor;
  1008. return top;
  1009. parse_error:
  1010. fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n",
  1011. filename, cursor->line,
  1012. (int)cursor->size, (int)cursor->size, cursor->value);
  1013. exit(1);
  1014. overrun_error:
  1015. fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
  1016. exit(1);
  1017. }
  1018. /*
  1019. * Parse a compound type list
  1020. */
  1021. static struct element *parse_compound(struct token **_cursor, struct token *end,
  1022. int alternates)
  1023. {
  1024. struct element *children, **child_p = &children, *element;
  1025. struct token *cursor = *_cursor, *name;
  1026. if (cursor->token_type != TOKEN_OPEN_CURLY) {
  1027. fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n",
  1028. filename, cursor->line,
  1029. (int)cursor->size, (int)cursor->size, cursor->value);
  1030. exit(1);
  1031. }
  1032. cursor++;
  1033. if (cursor >= end)
  1034. goto overrun_error;
  1035. if (cursor->token_type == TOKEN_OPEN_CURLY) {
  1036. fprintf(stderr, "%s:%d: Empty compound\n",
  1037. filename, cursor->line);
  1038. exit(1);
  1039. }
  1040. for (;;) {
  1041. name = NULL;
  1042. if (cursor->token_type == TOKEN_ELEMENT_NAME) {
  1043. name = cursor;
  1044. cursor++;
  1045. if (cursor >= end)
  1046. goto overrun_error;
  1047. }
  1048. element = parse_type(&cursor, end, name);
  1049. if (alternates)
  1050. element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL;
  1051. *child_p = element;
  1052. child_p = &element->next;
  1053. if (cursor >= end)
  1054. goto overrun_error;
  1055. if (cursor->token_type != TOKEN_COMMA)
  1056. break;
  1057. cursor++;
  1058. if (cursor >= end)
  1059. goto overrun_error;
  1060. }
  1061. children->flags &= ~ELEMENT_CONDITIONAL;
  1062. if (cursor->token_type != TOKEN_CLOSE_CURLY) {
  1063. fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n",
  1064. filename, cursor->line,
  1065. (int)cursor->size, (int)cursor->size, cursor->value);
  1066. exit(1);
  1067. }
  1068. cursor++;
  1069. *_cursor = cursor;
  1070. return children;
  1071. overrun_error:
  1072. fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
  1073. exit(1);
  1074. }
  1075. static void render_element(FILE *out, struct element *e, struct element *tag);
  1076. static void render_out_of_line_list(FILE *out);
  1077. static int nr_entries;
  1078. static int render_depth = 1;
  1079. static struct element *render_list, **render_list_p = &render_list;
  1080. __attribute__((format(printf, 2, 3)))
  1081. static void render_opcode(FILE *out, const char *fmt, ...)
  1082. {
  1083. va_list va;
  1084. if (out) {
  1085. fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, "");
  1086. va_start(va, fmt);
  1087. vfprintf(out, fmt, va);
  1088. va_end(va);
  1089. }
  1090. nr_entries++;
  1091. }
  1092. __attribute__((format(printf, 2, 3)))
  1093. static void render_more(FILE *out, const char *fmt, ...)
  1094. {
  1095. va_list va;
  1096. if (out) {
  1097. va_start(va, fmt);
  1098. vfprintf(out, fmt, va);
  1099. va_end(va);
  1100. }
  1101. }
  1102. /*
  1103. * Render the grammar into a state machine definition.
  1104. */
  1105. static void render(FILE *out, FILE *hdr)
  1106. {
  1107. struct element *e;
  1108. struct action *action;
  1109. struct type *root;
  1110. int index;
  1111. fprintf(hdr, "/*\n");
  1112. fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n");
  1113. fprintf(hdr, " *\n");
  1114. fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name);
  1115. fprintf(hdr, " */\n");
  1116. fprintf(hdr, "#include <linux/asn1_decoder.h>\n");
  1117. fprintf(hdr, "\n");
  1118. fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name);
  1119. if (ferror(hdr)) {
  1120. perror(headername);
  1121. exit(1);
  1122. }
  1123. fprintf(out, "/*\n");
  1124. fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n");
  1125. fprintf(out, " *\n");
  1126. fprintf(out, " * ASN.1 parser for %s\n", grammar_name);
  1127. fprintf(out, " */\n");
  1128. fprintf(out, "#include <linux/asn1_ber_bytecode.h>\n");
  1129. fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name);
  1130. fprintf(out, "\n");
  1131. if (ferror(out)) {
  1132. perror(outputname);
  1133. exit(1);
  1134. }
  1135. /* Tabulate the action functions we might have to call */
  1136. fprintf(hdr, "\n");
  1137. index = 0;
  1138. for (action = action_list; action; action = action->next) {
  1139. action->index = index++;
  1140. fprintf(hdr,
  1141. "extern int %s(void *, size_t, unsigned char,"
  1142. " const void *, size_t);\n",
  1143. action->name);
  1144. }
  1145. fprintf(hdr, "\n");
  1146. fprintf(out, "enum %s_actions {\n", grammar_name);
  1147. for (action = action_list; action; action = action->next)
  1148. fprintf(out, "\tACT_%s = %u,\n",
  1149. action->name, action->index);
  1150. fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions);
  1151. fprintf(out, "};\n");
  1152. fprintf(out, "\n");
  1153. fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n",
  1154. grammar_name, grammar_name);
  1155. for (action = action_list; action; action = action->next)
  1156. fprintf(out, "\t[%4u] = %s,\n", action->index, action->name);
  1157. fprintf(out, "};\n");
  1158. if (ferror(out)) {
  1159. perror(outputname);
  1160. exit(1);
  1161. }
  1162. /* We do two passes - the first one calculates all the offsets */
  1163. debug("Pass 1\n");
  1164. nr_entries = 0;
  1165. root = &type_list[0];
  1166. render_element(NULL, root->element, NULL);
  1167. render_opcode(NULL, "ASN1_OP_COMPLETE,\n");
  1168. render_out_of_line_list(NULL);
  1169. for (e = element_list; e; e = e->list_next)
  1170. e->flags &= ~ELEMENT_RENDERED;
  1171. /* And then we actually render */
  1172. debug("Pass 2\n");
  1173. fprintf(out, "\n");
  1174. fprintf(out, "static const unsigned char %s_machine[] = {\n",
  1175. grammar_name);
  1176. nr_entries = 0;
  1177. root = &type_list[0];
  1178. render_element(out, root->element, NULL);
  1179. render_opcode(out, "ASN1_OP_COMPLETE,\n");
  1180. render_out_of_line_list(out);
  1181. fprintf(out, "};\n");
  1182. fprintf(out, "\n");
  1183. fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name);
  1184. fprintf(out, "\t.machine = %s_machine,\n", grammar_name);
  1185. fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name);
  1186. fprintf(out, "\t.actions = %s_action_table,\n", grammar_name);
  1187. fprintf(out, "};\n");
  1188. }
  1189. /*
  1190. * Render the out-of-line elements
  1191. */
  1192. static void render_out_of_line_list(FILE *out)
  1193. {
  1194. struct element *e, *ce;
  1195. const char *act;
  1196. int entry;
  1197. while ((e = render_list)) {
  1198. render_list = e->render_next;
  1199. if (!render_list)
  1200. render_list_p = &render_list;
  1201. render_more(out, "\n");
  1202. e->entry_index = entry = nr_entries;
  1203. render_depth++;
  1204. for (ce = e->children; ce; ce = ce->next)
  1205. render_element(out, ce, NULL);
  1206. render_depth--;
  1207. act = e->action ? "_ACT" : "";
  1208. switch (e->compound) {
  1209. case SEQUENCE:
  1210. render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
  1211. break;
  1212. case SEQUENCE_OF:
  1213. render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
  1214. render_opcode(out, "_jump_target(%u),\n", entry);
  1215. break;
  1216. case SET:
  1217. render_opcode(out, "ASN1_OP_END_SET%s,\n", act);
  1218. break;
  1219. case SET_OF:
  1220. render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
  1221. render_opcode(out, "_jump_target(%u),\n", entry);
  1222. break;
  1223. default:
  1224. break;
  1225. }
  1226. if (e->action)
  1227. render_opcode(out, "_action(ACT_%s),\n",
  1228. e->action->name);
  1229. render_opcode(out, "ASN1_OP_RETURN,\n");
  1230. }
  1231. }
  1232. /*
  1233. * Render an element.
  1234. */
  1235. static void render_element(FILE *out, struct element *e, struct element *tag)
  1236. {
  1237. struct element *ec, *x;
  1238. const char *cond, *act;
  1239. int entry, skippable = 0, outofline = 0;
  1240. if (e->flags & ELEMENT_SKIPPABLE ||
  1241. (tag && tag->flags & ELEMENT_SKIPPABLE))
  1242. skippable = 1;
  1243. if ((e->type_def && e->type_def->ref_count > 1) ||
  1244. skippable)
  1245. outofline = 1;
  1246. if (e->type_def && out) {
  1247. render_more(out, "\t// %*.*s\n",
  1248. (int)e->type_def->name->size, (int)e->type_def->name->size,
  1249. e->type_def->name->value);
  1250. }
  1251. /* Render the operation */
  1252. cond = (e->flags & ELEMENT_CONDITIONAL ||
  1253. (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : "";
  1254. act = e->action ? "_ACT" : "";
  1255. switch (e->compound) {
  1256. case ANY:
  1257. render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,",
  1258. cond, act, skippable ? "_OR_SKIP" : "");
  1259. if (e->name)
  1260. render_more(out, "\t\t// %*.*s",
  1261. (int)e->name->size, (int)e->name->size,
  1262. e->name->value);
  1263. render_more(out, "\n");
  1264. goto dont_render_tag;
  1265. case TAG_OVERRIDE:
  1266. render_element(out, e->children, e);
  1267. return;
  1268. case SEQUENCE:
  1269. case SEQUENCE_OF:
  1270. case SET:
  1271. case SET_OF:
  1272. render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
  1273. cond,
  1274. outofline ? "_JUMP" : "",
  1275. skippable ? "_OR_SKIP" : "");
  1276. break;
  1277. case CHOICE:
  1278. goto dont_render_tag;
  1279. case TYPE_REF:
  1280. if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0)
  1281. goto dont_render_tag;
  1282. default:
  1283. render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
  1284. cond, act,
  1285. skippable ? "_OR_SKIP" : "");
  1286. break;
  1287. }
  1288. x = tag ?: e;
  1289. if (x->name)
  1290. render_more(out, "\t\t// %*.*s",
  1291. (int)x->name->size, (int)x->name->size,
  1292. x->name->value);
  1293. render_more(out, "\n");
  1294. /* Render the tag */
  1295. if (!tag || !(tag->flags & ELEMENT_TAG_SPECIFIED))
  1296. tag = e;
  1297. if (tag->class == ASN1_UNIV &&
  1298. tag->tag != 14 &&
  1299. tag->tag != 15 &&
  1300. tag->tag != 31)
  1301. render_opcode(out, "_tag(%s, %s, %s),\n",
  1302. asn1_classes[tag->class],
  1303. asn1_methods[tag->method | e->method],
  1304. asn1_universal_tags[tag->tag]);
  1305. else
  1306. render_opcode(out, "_tagn(%s, %s, %2u),\n",
  1307. asn1_classes[tag->class],
  1308. asn1_methods[tag->method | e->method],
  1309. tag->tag);
  1310. tag = NULL;
  1311. dont_render_tag:
  1312. /* Deal with compound types */
  1313. switch (e->compound) {
  1314. case TYPE_REF:
  1315. render_element(out, e->type->type->element, tag);
  1316. if (e->action)
  1317. render_opcode(out, "ASN1_OP_%sACT,\n",
  1318. skippable ? "MAYBE_" : "");
  1319. break;
  1320. case SEQUENCE:
  1321. if (outofline) {
  1322. /* Render out-of-line for multiple use or
  1323. * skipability */
  1324. render_opcode(out, "_jump_target(%u),", e->entry_index);
  1325. if (e->type_def && e->type_def->name)
  1326. render_more(out, "\t\t// --> %*.*s",
  1327. (int)e->type_def->name->size,
  1328. (int)e->type_def->name->size,
  1329. e->type_def->name->value);
  1330. render_more(out, "\n");
  1331. if (!(e->flags & ELEMENT_RENDERED)) {
  1332. e->flags |= ELEMENT_RENDERED;
  1333. *render_list_p = e;
  1334. render_list_p = &e->render_next;
  1335. }
  1336. return;
  1337. } else {
  1338. /* Render inline for single use */
  1339. render_depth++;
  1340. for (ec = e->children; ec; ec = ec->next)
  1341. render_element(out, ec, NULL);
  1342. render_depth--;
  1343. render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
  1344. }
  1345. break;
  1346. case SEQUENCE_OF:
  1347. case SET_OF:
  1348. if (outofline) {
  1349. /* Render out-of-line for multiple use or
  1350. * skipability */
  1351. render_opcode(out, "_jump_target(%u),", e->entry_index);
  1352. if (e->type_def && e->type_def->name)
  1353. render_more(out, "\t\t// --> %*.*s",
  1354. (int)e->type_def->name->size,
  1355. (int)e->type_def->name->size,
  1356. e->type_def->name->value);
  1357. render_more(out, "\n");
  1358. if (!(e->flags & ELEMENT_RENDERED)) {
  1359. e->flags |= ELEMENT_RENDERED;
  1360. *render_list_p = e;
  1361. render_list_p = &e->render_next;
  1362. }
  1363. return;
  1364. } else {
  1365. /* Render inline for single use */
  1366. entry = nr_entries;
  1367. render_depth++;
  1368. render_element(out, e->children, NULL);
  1369. render_depth--;
  1370. if (e->compound == SEQUENCE_OF)
  1371. render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
  1372. else
  1373. render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
  1374. render_opcode(out, "_jump_target(%u),\n", entry);
  1375. }
  1376. break;
  1377. case SET:
  1378. /* I can't think of a nice way to do SET support without having
  1379. * a stack of bitmasks to make sure no element is repeated.
  1380. * The bitmask has also to be checked that no non-optional
  1381. * elements are left out whilst not preventing optional
  1382. * elements from being left out.
  1383. */
  1384. fprintf(stderr, "The ASN.1 SET type is not currently supported.\n");
  1385. exit(1);
  1386. case CHOICE:
  1387. for (ec = e->children; ec; ec = ec->next)
  1388. render_element(out, ec, ec);
  1389. if (!skippable)
  1390. render_opcode(out, "ASN1_OP_COND_FAIL,\n");
  1391. if (e->action)
  1392. render_opcode(out, "ASN1_OP_ACT,\n");
  1393. break;
  1394. default:
  1395. break;
  1396. }
  1397. if (e->action)
  1398. render_opcode(out, "_action(ACT_%s),\n", e->action->name);
  1399. }