asn1_compiler.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545
  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 int directive_compare(const void *_key, const void *_pdir)
  303. {
  304. const struct token *token = _key;
  305. const char *const *pdir = _pdir, *dir = *pdir;
  306. size_t dlen, clen;
  307. int val;
  308. dlen = strlen(dir);
  309. clen = (dlen < token->size) ? dlen : token->size;
  310. //printf("cmp(%*.*s,%s) = ",
  311. // (int)token->size, (int)token->size, token->value,
  312. // dir);
  313. val = memcmp(token->value, dir, clen);
  314. if (val != 0) {
  315. //printf("%d [cmp]\n", val);
  316. return val;
  317. }
  318. if (dlen == token->size) {
  319. //printf("0\n");
  320. return 0;
  321. }
  322. //printf("%d\n", (int)dlen - (int)token->size);
  323. return dlen - token->size; /* shorter -> negative */
  324. }
  325. /*
  326. * Tokenise an ASN.1 grammar
  327. */
  328. static void tokenise(char *buffer, char *end)
  329. {
  330. struct token *tokens;
  331. char *line, *nl, *p, *q;
  332. unsigned tix, lineno;
  333. /* Assume we're going to have half as many tokens as we have
  334. * characters
  335. */
  336. token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token));
  337. if (!tokens) {
  338. perror(NULL);
  339. exit(1);
  340. }
  341. tix = 0;
  342. lineno = 0;
  343. while (buffer < end) {
  344. /* First of all, break out a line */
  345. lineno++;
  346. line = buffer;
  347. nl = memchr(line, '\n', end - buffer);
  348. if (!nl) {
  349. buffer = nl = end;
  350. } else {
  351. buffer = nl + 1;
  352. *nl = '\0';
  353. }
  354. /* Remove "--" comments */
  355. p = line;
  356. next_comment:
  357. while ((p = memchr(p, '-', nl - p))) {
  358. if (p[1] == '-') {
  359. /* Found a comment; see if there's a terminator */
  360. q = p + 2;
  361. while ((q = memchr(q, '-', nl - q))) {
  362. if (q[1] == '-') {
  363. /* There is - excise the comment */
  364. q += 2;
  365. memmove(p, q, nl - q);
  366. goto next_comment;
  367. }
  368. q++;
  369. }
  370. *p = '\0';
  371. nl = p;
  372. break;
  373. } else {
  374. p++;
  375. }
  376. }
  377. p = line;
  378. while (p < nl) {
  379. /* Skip white space */
  380. while (p < nl && isspace(*p))
  381. *(p++) = 0;
  382. if (p >= nl)
  383. break;
  384. tokens[tix].line = lineno;
  385. tokens[tix].value = p;
  386. /* Handle string tokens */
  387. if (isalpha(*p)) {
  388. const char **dir;
  389. /* Can be a directive, type name or element
  390. * name. Find the end of the name.
  391. */
  392. q = p + 1;
  393. while (q < nl && (isalnum(*q) || *q == '-' || *q == '_'))
  394. q++;
  395. tokens[tix].size = q - p;
  396. p = q;
  397. /* If it begins with a lowercase letter then
  398. * it's an element name
  399. */
  400. if (islower(tokens[tix].value[0])) {
  401. tokens[tix++].token_type = TOKEN_ELEMENT_NAME;
  402. continue;
  403. }
  404. /* Otherwise we need to search the directive
  405. * table
  406. */
  407. dir = bsearch(&tokens[tix], directives,
  408. sizeof(directives) / sizeof(directives[1]),
  409. sizeof(directives[1]),
  410. directive_compare);
  411. if (dir) {
  412. tokens[tix++].token_type = dir - directives;
  413. continue;
  414. }
  415. tokens[tix++].token_type = TOKEN_TYPE_NAME;
  416. continue;
  417. }
  418. /* Handle numbers */
  419. if (isdigit(*p)) {
  420. /* Find the end of the number */
  421. q = p + 1;
  422. while (q < nl && (isdigit(*q)))
  423. q++;
  424. tokens[tix].size = q - p;
  425. p = q;
  426. tokens[tix++].token_type = TOKEN_NUMBER;
  427. continue;
  428. }
  429. if (nl - p >= 3) {
  430. if (memcmp(p, "::=", 3) == 0) {
  431. p += 3;
  432. tokens[tix].size = 3;
  433. tokens[tix++].token_type = TOKEN_ASSIGNMENT;
  434. continue;
  435. }
  436. }
  437. if (nl - p >= 2) {
  438. if (memcmp(p, "({", 2) == 0) {
  439. p += 2;
  440. tokens[tix].size = 2;
  441. tokens[tix++].token_type = TOKEN_OPEN_ACTION;
  442. continue;
  443. }
  444. if (memcmp(p, "})", 2) == 0) {
  445. p += 2;
  446. tokens[tix].size = 2;
  447. tokens[tix++].token_type = TOKEN_CLOSE_ACTION;
  448. continue;
  449. }
  450. }
  451. if (nl - p >= 1) {
  452. tokens[tix].size = 1;
  453. switch (*p) {
  454. case '{':
  455. p += 1;
  456. tokens[tix++].token_type = TOKEN_OPEN_CURLY;
  457. continue;
  458. case '}':
  459. p += 1;
  460. tokens[tix++].token_type = TOKEN_CLOSE_CURLY;
  461. continue;
  462. case '[':
  463. p += 1;
  464. tokens[tix++].token_type = TOKEN_OPEN_SQUARE;
  465. continue;
  466. case ']':
  467. p += 1;
  468. tokens[tix++].token_type = TOKEN_CLOSE_SQUARE;
  469. continue;
  470. case ',':
  471. p += 1;
  472. tokens[tix++].token_type = TOKEN_COMMA;
  473. continue;
  474. default:
  475. break;
  476. }
  477. }
  478. fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n",
  479. filename, lineno, *p);
  480. exit(1);
  481. }
  482. }
  483. nr_tokens = tix;
  484. printf("Extracted %u tokens\n", nr_tokens);
  485. #if 0
  486. {
  487. int n;
  488. for (n = 0; n < nr_tokens; n++)
  489. printf("Token %3u: '%*.*s'\n",
  490. n,
  491. (int)token_list[n].size, (int)token_list[n].size,
  492. token_list[n].value);
  493. }
  494. #endif
  495. }
  496. static void build_type_list(void);
  497. static void parse(void);
  498. static void render(FILE *out, FILE *hdr);
  499. /*
  500. *
  501. */
  502. int main(int argc, char **argv)
  503. {
  504. struct stat st;
  505. ssize_t readlen;
  506. FILE *out, *hdr;
  507. char *buffer, *p;
  508. int fd;
  509. if (argc != 4) {
  510. fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n",
  511. argv[0]);
  512. exit(2);
  513. }
  514. filename = argv[1];
  515. outputname = argv[2];
  516. headername = argv[3];
  517. fd = open(filename, O_RDONLY);
  518. if (fd < 0) {
  519. perror(filename);
  520. exit(1);
  521. }
  522. if (fstat(fd, &st) < 0) {
  523. perror(filename);
  524. exit(1);
  525. }
  526. if (!(buffer = malloc(st.st_size + 1))) {
  527. perror(NULL);
  528. exit(1);
  529. }
  530. if ((readlen = read(fd, buffer, st.st_size)) < 0) {
  531. perror(filename);
  532. exit(1);
  533. }
  534. if (close(fd) < 0) {
  535. perror(filename);
  536. exit(1);
  537. }
  538. if (readlen != st.st_size) {
  539. fprintf(stderr, "%s: Short read\n", filename);
  540. exit(1);
  541. }
  542. p = strrchr(argv[1], '/');
  543. p = p ? p + 1 : argv[1];
  544. grammar_name = strdup(p);
  545. if (!p) {
  546. perror(NULL);
  547. exit(1);
  548. }
  549. p = strchr(grammar_name, '.');
  550. if (p)
  551. *p = '\0';
  552. buffer[readlen] = 0;
  553. tokenise(buffer, buffer + readlen);
  554. build_type_list();
  555. parse();
  556. out = fopen(outputname, "w");
  557. if (!out) {
  558. perror(outputname);
  559. exit(1);
  560. }
  561. hdr = fopen(headername, "w");
  562. if (!out) {
  563. perror(headername);
  564. exit(1);
  565. }
  566. render(out, hdr);
  567. if (fclose(out) < 0) {
  568. perror(outputname);
  569. exit(1);
  570. }
  571. if (fclose(hdr) < 0) {
  572. perror(headername);
  573. exit(1);
  574. }
  575. return 0;
  576. }
  577. enum compound {
  578. NOT_COMPOUND,
  579. SET,
  580. SET_OF,
  581. SEQUENCE,
  582. SEQUENCE_OF,
  583. CHOICE,
  584. ANY,
  585. TYPE_REF,
  586. TAG_OVERRIDE
  587. };
  588. struct element {
  589. struct type *type_def;
  590. struct token *name;
  591. struct token *type;
  592. struct action *action;
  593. struct element *children;
  594. struct element *next;
  595. struct element *render_next;
  596. struct element *list_next;
  597. uint8_t n_elements;
  598. enum compound compound : 8;
  599. enum asn1_class class : 8;
  600. enum asn1_method method : 8;
  601. uint8_t tag;
  602. unsigned entry_index;
  603. unsigned flags;
  604. #define ELEMENT_IMPLICIT 0x0001
  605. #define ELEMENT_EXPLICIT 0x0002
  606. #define ELEMENT_MARKED 0x0004
  607. #define ELEMENT_RENDERED 0x0008
  608. #define ELEMENT_SKIPPABLE 0x0010
  609. #define ELEMENT_CONDITIONAL 0x0020
  610. };
  611. struct type {
  612. struct token *name;
  613. struct token *def;
  614. struct element *element;
  615. unsigned ref_count;
  616. unsigned flags;
  617. #define TYPE_STOP_MARKER 0x0001
  618. #define TYPE_BEGIN 0x0002
  619. };
  620. static struct type *type_list;
  621. static struct type **type_index;
  622. static unsigned nr_types;
  623. static int type_index_compare(const void *_a, const void *_b)
  624. {
  625. const struct type *const *a = _a, *const *b = _b;
  626. if ((*a)->name->size != (*b)->name->size)
  627. return (*a)->name->size - (*b)->name->size;
  628. else
  629. return memcmp((*a)->name->value, (*b)->name->value,
  630. (*a)->name->size);
  631. }
  632. static int type_finder(const void *_key, const void *_ti)
  633. {
  634. const struct token *token = _key;
  635. const struct type *const *ti = _ti;
  636. const struct type *type = *ti;
  637. if (token->size != type->name->size)
  638. return token->size - type->name->size;
  639. else
  640. return memcmp(token->value, type->name->value,
  641. token->size);
  642. }
  643. /*
  644. * Build up a list of types and a sorted index to that list.
  645. */
  646. static void build_type_list(void)
  647. {
  648. struct type *types;
  649. unsigned nr, t, n;
  650. nr = 0;
  651. for (n = 0; n < nr_tokens - 1; n++)
  652. if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
  653. token_list[n + 1].token_type == TOKEN_ASSIGNMENT)
  654. nr++;
  655. if (nr == 0) {
  656. fprintf(stderr, "%s: No defined types\n", filename);
  657. exit(1);
  658. }
  659. nr_types = nr;
  660. types = type_list = calloc(nr + 1, sizeof(type_list[0]));
  661. if (!type_list) {
  662. perror(NULL);
  663. exit(1);
  664. }
  665. type_index = calloc(nr, sizeof(type_index[0]));
  666. if (!type_index) {
  667. perror(NULL);
  668. exit(1);
  669. }
  670. t = 0;
  671. types[t].flags |= TYPE_BEGIN;
  672. for (n = 0; n < nr_tokens - 1; n++) {
  673. if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
  674. token_list[n + 1].token_type == TOKEN_ASSIGNMENT) {
  675. types[t].name = &token_list[n];
  676. type_index[t] = &types[t];
  677. t++;
  678. }
  679. }
  680. types[t].name = &token_list[n + 1];
  681. types[t].flags |= TYPE_STOP_MARKER;
  682. qsort(type_index, nr, sizeof(type_index[0]), type_index_compare);
  683. printf("Extracted %u types\n", nr_types);
  684. #if 0
  685. for (n = 0; n < nr_types; n++) {
  686. struct type *type = type_index[n];
  687. printf("- %*.*s\n",
  688. (int)type->name->size,
  689. (int)type->name->size,
  690. type->name->value);
  691. }
  692. #endif
  693. }
  694. static struct element *parse_type(struct token **_cursor, struct token *stop,
  695. struct token *name);
  696. /*
  697. * Parse the token stream
  698. */
  699. static void parse(void)
  700. {
  701. struct token *cursor;
  702. struct type *type;
  703. /* Parse one type definition statement at a time */
  704. type = type_list;
  705. do {
  706. cursor = type->name;
  707. if (cursor[0].token_type != TOKEN_TYPE_NAME ||
  708. cursor[1].token_type != TOKEN_ASSIGNMENT)
  709. abort();
  710. cursor += 2;
  711. type->element = parse_type(&cursor, type[1].name, NULL);
  712. type->element->type_def = type;
  713. if (cursor != type[1].name) {
  714. fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n",
  715. filename, cursor->line,
  716. (int)cursor->size, (int)cursor->size, cursor->value);
  717. exit(1);
  718. }
  719. } while (type++, !(type->flags & TYPE_STOP_MARKER));
  720. printf("Extracted %u actions\n", nr_actions);
  721. }
  722. static struct element *element_list;
  723. static struct element *alloc_elem(struct token *type)
  724. {
  725. struct element *e = calloc(1, sizeof(*e));
  726. if (!e) {
  727. perror(NULL);
  728. exit(1);
  729. }
  730. e->list_next = element_list;
  731. element_list = e;
  732. return e;
  733. }
  734. static struct element *parse_compound(struct token **_cursor, struct token *end,
  735. int alternates);
  736. /*
  737. * Parse one type definition statement
  738. */
  739. static struct element *parse_type(struct token **_cursor, struct token *end,
  740. struct token *name)
  741. {
  742. struct element *top, *element;
  743. struct action *action, **ppaction;
  744. struct token *cursor = *_cursor;
  745. struct type **ref;
  746. char *p;
  747. int labelled = 0, implicit = 0;
  748. top = element = alloc_elem(cursor);
  749. element->class = ASN1_UNIV;
  750. element->method = ASN1_PRIM;
  751. element->tag = token_to_tag[cursor->token_type];
  752. element->name = name;
  753. /* Extract the tag value if one given */
  754. if (cursor->token_type == TOKEN_OPEN_SQUARE) {
  755. cursor++;
  756. if (cursor >= end)
  757. goto overrun_error;
  758. switch (cursor->token_type) {
  759. case DIRECTIVE_UNIVERSAL:
  760. element->class = ASN1_UNIV;
  761. cursor++;
  762. break;
  763. case DIRECTIVE_APPLICATION:
  764. element->class = ASN1_APPL;
  765. cursor++;
  766. break;
  767. case TOKEN_NUMBER:
  768. element->class = ASN1_CONT;
  769. break;
  770. case DIRECTIVE_PRIVATE:
  771. element->class = ASN1_PRIV;
  772. cursor++;
  773. break;
  774. default:
  775. fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n",
  776. filename, cursor->line,
  777. (int)cursor->size, (int)cursor->size, cursor->value);
  778. exit(1);
  779. }
  780. if (cursor >= end)
  781. goto overrun_error;
  782. if (cursor->token_type != TOKEN_NUMBER) {
  783. fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n",
  784. filename, cursor->line,
  785. (int)cursor->size, (int)cursor->size, cursor->value);
  786. exit(1);
  787. }
  788. element->tag &= ~0x1f;
  789. element->tag |= strtoul(cursor->value, &p, 10);
  790. if (p - cursor->value != cursor->size)
  791. abort();
  792. cursor++;
  793. if (cursor >= end)
  794. goto overrun_error;
  795. if (cursor->token_type != TOKEN_CLOSE_SQUARE) {
  796. fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n",
  797. filename, cursor->line,
  798. (int)cursor->size, (int)cursor->size, cursor->value);
  799. exit(1);
  800. }
  801. cursor++;
  802. if (cursor >= end)
  803. goto overrun_error;
  804. labelled = 1;
  805. }
  806. /* Handle implicit and explicit markers */
  807. if (cursor->token_type == DIRECTIVE_IMPLICIT) {
  808. element->flags |= ELEMENT_IMPLICIT;
  809. implicit = 1;
  810. cursor++;
  811. if (cursor >= end)
  812. goto overrun_error;
  813. } else if (cursor->token_type == DIRECTIVE_EXPLICIT) {
  814. element->flags |= ELEMENT_EXPLICIT;
  815. cursor++;
  816. if (cursor >= end)
  817. goto overrun_error;
  818. }
  819. if (labelled) {
  820. if (!implicit)
  821. element->method |= ASN1_CONS;
  822. element->compound = implicit ? TAG_OVERRIDE : SEQUENCE;
  823. element->children = alloc_elem(cursor);
  824. element = element->children;
  825. element->class = ASN1_UNIV;
  826. element->method = ASN1_PRIM;
  827. element->tag = token_to_tag[cursor->token_type];
  828. element->name = name;
  829. }
  830. /* Extract the type we're expecting here */
  831. element->type = cursor;
  832. switch (cursor->token_type) {
  833. case DIRECTIVE_ANY:
  834. element->compound = ANY;
  835. cursor++;
  836. break;
  837. case DIRECTIVE_NULL:
  838. case DIRECTIVE_BOOLEAN:
  839. case DIRECTIVE_ENUMERATED:
  840. case DIRECTIVE_INTEGER:
  841. element->compound = NOT_COMPOUND;
  842. cursor++;
  843. break;
  844. case DIRECTIVE_EXTERNAL:
  845. element->method = ASN1_CONS;
  846. case DIRECTIVE_BMPString:
  847. case DIRECTIVE_GeneralString:
  848. case DIRECTIVE_GraphicString:
  849. case DIRECTIVE_IA5String:
  850. case DIRECTIVE_ISO646String:
  851. case DIRECTIVE_NumericString:
  852. case DIRECTIVE_PrintableString:
  853. case DIRECTIVE_T61String:
  854. case DIRECTIVE_TeletexString:
  855. case DIRECTIVE_UniversalString:
  856. case DIRECTIVE_UTF8String:
  857. case DIRECTIVE_VideotexString:
  858. case DIRECTIVE_VisibleString:
  859. case DIRECTIVE_ObjectDescriptor:
  860. case DIRECTIVE_GeneralizedTime:
  861. case DIRECTIVE_UTCTime:
  862. element->compound = NOT_COMPOUND;
  863. cursor++;
  864. break;
  865. case DIRECTIVE_BIT:
  866. case DIRECTIVE_OCTET:
  867. element->compound = NOT_COMPOUND;
  868. cursor++;
  869. if (cursor >= end)
  870. goto overrun_error;
  871. if (cursor->token_type != DIRECTIVE_STRING)
  872. goto parse_error;
  873. cursor++;
  874. break;
  875. case DIRECTIVE_OBJECT:
  876. element->compound = NOT_COMPOUND;
  877. cursor++;
  878. if (cursor >= end)
  879. goto overrun_error;
  880. if (cursor->token_type != DIRECTIVE_IDENTIFIER)
  881. goto parse_error;
  882. cursor++;
  883. break;
  884. case TOKEN_TYPE_NAME:
  885. element->compound = TYPE_REF;
  886. ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]),
  887. type_finder);
  888. if (!ref) {
  889. fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n",
  890. filename, cursor->line,
  891. (int)cursor->size, (int)cursor->size, cursor->value);
  892. exit(1);
  893. }
  894. cursor->type = *ref;
  895. (*ref)->ref_count++;
  896. cursor++;
  897. break;
  898. case DIRECTIVE_CHOICE:
  899. element->compound = CHOICE;
  900. cursor++;
  901. element->children = parse_compound(&cursor, end, 1);
  902. break;
  903. case DIRECTIVE_SEQUENCE:
  904. element->compound = SEQUENCE;
  905. element->method = ASN1_CONS;
  906. cursor++;
  907. if (cursor >= end)
  908. goto overrun_error;
  909. if (cursor->token_type == DIRECTIVE_OF) {
  910. element->compound = SEQUENCE_OF;
  911. cursor++;
  912. if (cursor >= end)
  913. goto overrun_error;
  914. element->children = parse_type(&cursor, end, NULL);
  915. } else {
  916. element->children = parse_compound(&cursor, end, 0);
  917. }
  918. break;
  919. case DIRECTIVE_SET:
  920. element->compound = SET;
  921. element->method = ASN1_CONS;
  922. cursor++;
  923. if (cursor >= end)
  924. goto overrun_error;
  925. if (cursor->token_type == DIRECTIVE_OF) {
  926. element->compound = SET_OF;
  927. cursor++;
  928. if (cursor >= end)
  929. goto parse_error;
  930. element->children = parse_type(&cursor, end, NULL);
  931. } else {
  932. element->children = parse_compound(&cursor, end, 1);
  933. }
  934. break;
  935. default:
  936. fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n",
  937. filename, cursor->line,
  938. (int)cursor->size, (int)cursor->size, cursor->value);
  939. exit(1);
  940. }
  941. /* Handle elements that are optional */
  942. if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL ||
  943. cursor->token_type == DIRECTIVE_DEFAULT)
  944. ) {
  945. cursor++;
  946. top->flags |= ELEMENT_SKIPPABLE;
  947. }
  948. if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) {
  949. cursor++;
  950. if (cursor >= end)
  951. goto overrun_error;
  952. if (cursor->token_type != TOKEN_ELEMENT_NAME) {
  953. fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n",
  954. filename, cursor->line,
  955. (int)cursor->size, (int)cursor->size, cursor->value);
  956. exit(1);
  957. }
  958. action = malloc(sizeof(struct action) + cursor->size + 1);
  959. if (!action) {
  960. perror(NULL);
  961. exit(1);
  962. }
  963. action->index = 0;
  964. memcpy(action->name, cursor->value, cursor->size);
  965. action->name[cursor->size] = 0;
  966. for (ppaction = &action_list;
  967. *ppaction;
  968. ppaction = &(*ppaction)->next
  969. ) {
  970. int cmp = strcmp(action->name, (*ppaction)->name);
  971. if (cmp == 0) {
  972. free(action);
  973. action = *ppaction;
  974. goto found;
  975. }
  976. if (cmp < 0) {
  977. action->next = *ppaction;
  978. *ppaction = action;
  979. nr_actions++;
  980. goto found;
  981. }
  982. }
  983. action->next = NULL;
  984. *ppaction = action;
  985. nr_actions++;
  986. found:
  987. element->action = action;
  988. cursor->action = action;
  989. cursor++;
  990. if (cursor >= end)
  991. goto overrun_error;
  992. if (cursor->token_type != TOKEN_CLOSE_ACTION) {
  993. fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n",
  994. filename, cursor->line,
  995. (int)cursor->size, (int)cursor->size, cursor->value);
  996. exit(1);
  997. }
  998. cursor++;
  999. }
  1000. *_cursor = cursor;
  1001. return top;
  1002. parse_error:
  1003. fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n",
  1004. filename, cursor->line,
  1005. (int)cursor->size, (int)cursor->size, cursor->value);
  1006. exit(1);
  1007. overrun_error:
  1008. fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
  1009. exit(1);
  1010. }
  1011. /*
  1012. * Parse a compound type list
  1013. */
  1014. static struct element *parse_compound(struct token **_cursor, struct token *end,
  1015. int alternates)
  1016. {
  1017. struct element *children, **child_p = &children, *element;
  1018. struct token *cursor = *_cursor, *name;
  1019. if (cursor->token_type != TOKEN_OPEN_CURLY) {
  1020. fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n",
  1021. filename, cursor->line,
  1022. (int)cursor->size, (int)cursor->size, cursor->value);
  1023. exit(1);
  1024. }
  1025. cursor++;
  1026. if (cursor >= end)
  1027. goto overrun_error;
  1028. if (cursor->token_type == TOKEN_OPEN_CURLY) {
  1029. fprintf(stderr, "%s:%d: Empty compound\n",
  1030. filename, cursor->line);
  1031. exit(1);
  1032. }
  1033. for (;;) {
  1034. name = NULL;
  1035. if (cursor->token_type == TOKEN_ELEMENT_NAME) {
  1036. name = cursor;
  1037. cursor++;
  1038. if (cursor >= end)
  1039. goto overrun_error;
  1040. }
  1041. element = parse_type(&cursor, end, name);
  1042. if (alternates)
  1043. element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL;
  1044. *child_p = element;
  1045. child_p = &element->next;
  1046. if (cursor >= end)
  1047. goto overrun_error;
  1048. if (cursor->token_type != TOKEN_COMMA)
  1049. break;
  1050. cursor++;
  1051. if (cursor >= end)
  1052. goto overrun_error;
  1053. }
  1054. children->flags &= ~ELEMENT_CONDITIONAL;
  1055. if (cursor->token_type != TOKEN_CLOSE_CURLY) {
  1056. fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n",
  1057. filename, cursor->line,
  1058. (int)cursor->size, (int)cursor->size, cursor->value);
  1059. exit(1);
  1060. }
  1061. cursor++;
  1062. *_cursor = cursor;
  1063. return children;
  1064. overrun_error:
  1065. fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
  1066. exit(1);
  1067. }
  1068. static void render_element(FILE *out, struct element *e, struct element *tag);
  1069. static void render_out_of_line_list(FILE *out);
  1070. static int nr_entries;
  1071. static int render_depth = 1;
  1072. static struct element *render_list, **render_list_p = &render_list;
  1073. __attribute__((format(printf, 2, 3)))
  1074. static void render_opcode(FILE *out, const char *fmt, ...)
  1075. {
  1076. va_list va;
  1077. if (out) {
  1078. fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, "");
  1079. va_start(va, fmt);
  1080. vfprintf(out, fmt, va);
  1081. va_end(va);
  1082. }
  1083. nr_entries++;
  1084. }
  1085. __attribute__((format(printf, 2, 3)))
  1086. static void render_more(FILE *out, const char *fmt, ...)
  1087. {
  1088. va_list va;
  1089. if (out) {
  1090. va_start(va, fmt);
  1091. vfprintf(out, fmt, va);
  1092. va_end(va);
  1093. }
  1094. }
  1095. /*
  1096. * Render the grammar into a state machine definition.
  1097. */
  1098. static void render(FILE *out, FILE *hdr)
  1099. {
  1100. struct element *e;
  1101. struct action *action;
  1102. struct type *root;
  1103. int index;
  1104. fprintf(hdr, "/*\n");
  1105. fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n");
  1106. fprintf(hdr, " *\n");
  1107. fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name);
  1108. fprintf(hdr, " */\n");
  1109. fprintf(hdr, "#include <linux/asn1_decoder.h>\n");
  1110. fprintf(hdr, "\n");
  1111. fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name);
  1112. if (ferror(hdr)) {
  1113. perror(headername);
  1114. exit(1);
  1115. }
  1116. fprintf(out, "/*\n");
  1117. fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n");
  1118. fprintf(out, " *\n");
  1119. fprintf(out, " * ASN.1 parser for %s\n", grammar_name);
  1120. fprintf(out, " */\n");
  1121. fprintf(out, "#include <linux/asn1_ber_bytecode.h>\n");
  1122. fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name);
  1123. fprintf(out, "\n");
  1124. if (ferror(out)) {
  1125. perror(outputname);
  1126. exit(1);
  1127. }
  1128. /* Tabulate the action functions we might have to call */
  1129. fprintf(hdr, "\n");
  1130. index = 0;
  1131. for (action = action_list; action; action = action->next) {
  1132. action->index = index++;
  1133. fprintf(hdr,
  1134. "extern int %s(void *, size_t, unsigned char,"
  1135. " const void *, size_t);\n",
  1136. action->name);
  1137. }
  1138. fprintf(hdr, "\n");
  1139. fprintf(out, "enum %s_actions {\n", grammar_name);
  1140. for (action = action_list; action; action = action->next)
  1141. fprintf(out, "\tACT_%s = %u,\n",
  1142. action->name, action->index);
  1143. fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions);
  1144. fprintf(out, "};\n");
  1145. fprintf(out, "\n");
  1146. fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n",
  1147. grammar_name, grammar_name);
  1148. for (action = action_list; action; action = action->next)
  1149. fprintf(out, "\t[%4u] = %s,\n", action->index, action->name);
  1150. fprintf(out, "};\n");
  1151. if (ferror(out)) {
  1152. perror(outputname);
  1153. exit(1);
  1154. }
  1155. /* We do two passes - the first one calculates all the offsets */
  1156. printf("Pass 1\n");
  1157. nr_entries = 0;
  1158. root = &type_list[0];
  1159. render_element(NULL, root->element, NULL);
  1160. render_opcode(NULL, "ASN1_OP_COMPLETE,\n");
  1161. render_out_of_line_list(NULL);
  1162. for (e = element_list; e; e = e->list_next)
  1163. e->flags &= ~ELEMENT_RENDERED;
  1164. /* And then we actually render */
  1165. printf("Pass 2\n");
  1166. fprintf(out, "\n");
  1167. fprintf(out, "static const unsigned char %s_machine[] = {\n",
  1168. grammar_name);
  1169. nr_entries = 0;
  1170. root = &type_list[0];
  1171. render_element(out, root->element, NULL);
  1172. render_opcode(out, "ASN1_OP_COMPLETE,\n");
  1173. render_out_of_line_list(out);
  1174. fprintf(out, "};\n");
  1175. fprintf(out, "\n");
  1176. fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name);
  1177. fprintf(out, "\t.machine = %s_machine,\n", grammar_name);
  1178. fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name);
  1179. fprintf(out, "\t.actions = %s_action_table,\n", grammar_name);
  1180. fprintf(out, "};\n");
  1181. }
  1182. /*
  1183. * Render the out-of-line elements
  1184. */
  1185. static void render_out_of_line_list(FILE *out)
  1186. {
  1187. struct element *e, *ce;
  1188. const char *act;
  1189. int entry;
  1190. while ((e = render_list)) {
  1191. render_list = e->render_next;
  1192. if (!render_list)
  1193. render_list_p = &render_list;
  1194. render_more(out, "\n");
  1195. e->entry_index = entry = nr_entries;
  1196. render_depth++;
  1197. for (ce = e->children; ce; ce = ce->next)
  1198. render_element(out, ce, NULL);
  1199. render_depth--;
  1200. act = e->action ? "_ACT" : "";
  1201. switch (e->compound) {
  1202. case SEQUENCE:
  1203. render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
  1204. break;
  1205. case SEQUENCE_OF:
  1206. render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
  1207. render_opcode(out, "_jump_target(%u),\n", entry);
  1208. break;
  1209. case SET:
  1210. render_opcode(out, "ASN1_OP_END_SET%s,\n", act);
  1211. break;
  1212. case SET_OF:
  1213. render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
  1214. render_opcode(out, "_jump_target(%u),\n", entry);
  1215. break;
  1216. }
  1217. if (e->action)
  1218. render_opcode(out, "_action(ACT_%s),\n",
  1219. e->action->name);
  1220. render_opcode(out, "ASN1_OP_RETURN,\n");
  1221. }
  1222. }
  1223. /*
  1224. * Render an element.
  1225. */
  1226. static void render_element(FILE *out, struct element *e, struct element *tag)
  1227. {
  1228. struct element *ec;
  1229. const char *cond, *act;
  1230. int entry, skippable = 0, outofline = 0;
  1231. if (e->flags & ELEMENT_SKIPPABLE ||
  1232. (tag && tag->flags & ELEMENT_SKIPPABLE))
  1233. skippable = 1;
  1234. if ((e->type_def && e->type_def->ref_count > 1) ||
  1235. skippable)
  1236. outofline = 1;
  1237. if (e->type_def && out) {
  1238. render_more(out, "\t// %*.*s\n",
  1239. (int)e->type_def->name->size, (int)e->type_def->name->size,
  1240. e->type_def->name->value);
  1241. }
  1242. /* Render the operation */
  1243. cond = (e->flags & ELEMENT_CONDITIONAL ||
  1244. (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : "";
  1245. act = e->action ? "_ACT" : "";
  1246. switch (e->compound) {
  1247. case ANY:
  1248. render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act);
  1249. if (e->name)
  1250. render_more(out, "\t\t// %*.*s",
  1251. (int)e->name->size, (int)e->name->size,
  1252. e->name->value);
  1253. render_more(out, "\n");
  1254. goto dont_render_tag;
  1255. case TAG_OVERRIDE:
  1256. render_element(out, e->children, e);
  1257. return;
  1258. case SEQUENCE:
  1259. case SEQUENCE_OF:
  1260. case SET:
  1261. case SET_OF:
  1262. render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
  1263. cond,
  1264. outofline ? "_JUMP" : "",
  1265. skippable ? "_OR_SKIP" : "");
  1266. break;
  1267. case CHOICE:
  1268. goto dont_render_tag;
  1269. case TYPE_REF:
  1270. if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0)
  1271. goto dont_render_tag;
  1272. default:
  1273. render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
  1274. cond, act,
  1275. skippable ? "_OR_SKIP" : "");
  1276. break;
  1277. }
  1278. if (e->name)
  1279. render_more(out, "\t\t// %*.*s",
  1280. (int)e->name->size, (int)e->name->size,
  1281. e->name->value);
  1282. render_more(out, "\n");
  1283. /* Render the tag */
  1284. if (!tag)
  1285. tag = e;
  1286. if (tag->class == ASN1_UNIV &&
  1287. tag->tag != 14 &&
  1288. tag->tag != 15 &&
  1289. tag->tag != 31)
  1290. render_opcode(out, "_tag(%s, %s, %s),\n",
  1291. asn1_classes[tag->class],
  1292. asn1_methods[tag->method | e->method],
  1293. asn1_universal_tags[tag->tag]);
  1294. else
  1295. render_opcode(out, "_tagn(%s, %s, %2u),\n",
  1296. asn1_classes[tag->class],
  1297. asn1_methods[tag->method | e->method],
  1298. tag->tag);
  1299. tag = NULL;
  1300. dont_render_tag:
  1301. /* Deal with compound types */
  1302. switch (e->compound) {
  1303. case TYPE_REF:
  1304. render_element(out, e->type->type->element, tag);
  1305. if (e->action)
  1306. render_opcode(out, "ASN1_OP_ACT,\n");
  1307. break;
  1308. case SEQUENCE:
  1309. if (outofline) {
  1310. /* Render out-of-line for multiple use or
  1311. * skipability */
  1312. render_opcode(out, "_jump_target(%u),", e->entry_index);
  1313. if (e->type_def && e->type_def->name)
  1314. render_more(out, "\t\t// --> %*.*s",
  1315. (int)e->type_def->name->size,
  1316. (int)e->type_def->name->size,
  1317. e->type_def->name->value);
  1318. render_more(out, "\n");
  1319. if (!(e->flags & ELEMENT_RENDERED)) {
  1320. e->flags |= ELEMENT_RENDERED;
  1321. *render_list_p = e;
  1322. render_list_p = &e->render_next;
  1323. }
  1324. return;
  1325. } else {
  1326. /* Render inline for single use */
  1327. render_depth++;
  1328. for (ec = e->children; ec; ec = ec->next)
  1329. render_element(out, ec, NULL);
  1330. render_depth--;
  1331. render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
  1332. }
  1333. break;
  1334. case SEQUENCE_OF:
  1335. case SET_OF:
  1336. if (outofline) {
  1337. /* Render out-of-line for multiple use or
  1338. * skipability */
  1339. render_opcode(out, "_jump_target(%u),", e->entry_index);
  1340. if (e->type_def && e->type_def->name)
  1341. render_more(out, "\t\t// --> %*.*s",
  1342. (int)e->type_def->name->size,
  1343. (int)e->type_def->name->size,
  1344. e->type_def->name->value);
  1345. render_more(out, "\n");
  1346. if (!(e->flags & ELEMENT_RENDERED)) {
  1347. e->flags |= ELEMENT_RENDERED;
  1348. *render_list_p = e;
  1349. render_list_p = &e->render_next;
  1350. }
  1351. return;
  1352. } else {
  1353. /* Render inline for single use */
  1354. entry = nr_entries;
  1355. render_depth++;
  1356. render_element(out, e->children, NULL);
  1357. render_depth--;
  1358. if (e->compound == SEQUENCE_OF)
  1359. render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
  1360. else
  1361. render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
  1362. render_opcode(out, "_jump_target(%u),\n", entry);
  1363. }
  1364. break;
  1365. case SET:
  1366. /* I can't think of a nice way to do SET support without having
  1367. * a stack of bitmasks to make sure no element is repeated.
  1368. * The bitmask has also to be checked that no non-optional
  1369. * elements are left out whilst not preventing optional
  1370. * elements from being left out.
  1371. */
  1372. fprintf(stderr, "The ASN.1 SET type is not currently supported.\n");
  1373. exit(1);
  1374. case CHOICE:
  1375. for (ec = e->children; ec; ec = ec->next)
  1376. render_element(out, ec, NULL);
  1377. if (!skippable)
  1378. render_opcode(out, "ASN1_OP_COND_FAIL,\n");
  1379. if (e->action)
  1380. render_opcode(out, "ASN1_OP_ACT,\n");
  1381. break;
  1382. default:
  1383. break;
  1384. }
  1385. if (e->action)
  1386. render_opcode(out, "_action(ACT_%s),\n", e->action->name);
  1387. }