asn1_compiler.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555
  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_MARKED 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. if (p - cursor->value != cursor->size)
  797. abort();
  798. cursor++;
  799. if (cursor >= end)
  800. goto overrun_error;
  801. if (cursor->token_type != TOKEN_CLOSE_SQUARE) {
  802. fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n",
  803. filename, cursor->line,
  804. (int)cursor->size, (int)cursor->size, cursor->value);
  805. exit(1);
  806. }
  807. cursor++;
  808. if (cursor >= end)
  809. goto overrun_error;
  810. labelled = 1;
  811. }
  812. /* Handle implicit and explicit markers */
  813. if (cursor->token_type == DIRECTIVE_IMPLICIT) {
  814. element->flags |= ELEMENT_IMPLICIT;
  815. implicit = 1;
  816. cursor++;
  817. if (cursor >= end)
  818. goto overrun_error;
  819. } else if (cursor->token_type == DIRECTIVE_EXPLICIT) {
  820. element->flags |= ELEMENT_EXPLICIT;
  821. cursor++;
  822. if (cursor >= end)
  823. goto overrun_error;
  824. }
  825. if (labelled) {
  826. if (!implicit)
  827. element->method |= ASN1_CONS;
  828. element->compound = implicit ? TAG_OVERRIDE : SEQUENCE;
  829. element->children = alloc_elem(cursor);
  830. element = element->children;
  831. element->class = ASN1_UNIV;
  832. element->method = ASN1_PRIM;
  833. element->tag = token_to_tag[cursor->token_type];
  834. element->name = name;
  835. }
  836. /* Extract the type we're expecting here */
  837. element->type = cursor;
  838. switch (cursor->token_type) {
  839. case DIRECTIVE_ANY:
  840. element->compound = ANY;
  841. cursor++;
  842. break;
  843. case DIRECTIVE_NULL:
  844. case DIRECTIVE_BOOLEAN:
  845. case DIRECTIVE_ENUMERATED:
  846. case DIRECTIVE_INTEGER:
  847. element->compound = NOT_COMPOUND;
  848. cursor++;
  849. break;
  850. case DIRECTIVE_EXTERNAL:
  851. element->method = ASN1_CONS;
  852. case DIRECTIVE_BMPString:
  853. case DIRECTIVE_GeneralString:
  854. case DIRECTIVE_GraphicString:
  855. case DIRECTIVE_IA5String:
  856. case DIRECTIVE_ISO646String:
  857. case DIRECTIVE_NumericString:
  858. case DIRECTIVE_PrintableString:
  859. case DIRECTIVE_T61String:
  860. case DIRECTIVE_TeletexString:
  861. case DIRECTIVE_UniversalString:
  862. case DIRECTIVE_UTF8String:
  863. case DIRECTIVE_VideotexString:
  864. case DIRECTIVE_VisibleString:
  865. case DIRECTIVE_ObjectDescriptor:
  866. case DIRECTIVE_GeneralizedTime:
  867. case DIRECTIVE_UTCTime:
  868. element->compound = NOT_COMPOUND;
  869. cursor++;
  870. break;
  871. case DIRECTIVE_BIT:
  872. case DIRECTIVE_OCTET:
  873. element->compound = NOT_COMPOUND;
  874. cursor++;
  875. if (cursor >= end)
  876. goto overrun_error;
  877. if (cursor->token_type != DIRECTIVE_STRING)
  878. goto parse_error;
  879. cursor++;
  880. break;
  881. case DIRECTIVE_OBJECT:
  882. element->compound = NOT_COMPOUND;
  883. cursor++;
  884. if (cursor >= end)
  885. goto overrun_error;
  886. if (cursor->token_type != DIRECTIVE_IDENTIFIER)
  887. goto parse_error;
  888. cursor++;
  889. break;
  890. case TOKEN_TYPE_NAME:
  891. element->compound = TYPE_REF;
  892. ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]),
  893. type_finder);
  894. if (!ref) {
  895. fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n",
  896. filename, cursor->line,
  897. (int)cursor->size, (int)cursor->size, cursor->value);
  898. exit(1);
  899. }
  900. cursor->type = *ref;
  901. (*ref)->ref_count++;
  902. cursor++;
  903. break;
  904. case DIRECTIVE_CHOICE:
  905. element->compound = CHOICE;
  906. cursor++;
  907. element->children = parse_compound(&cursor, end, 1);
  908. break;
  909. case DIRECTIVE_SEQUENCE:
  910. element->compound = SEQUENCE;
  911. element->method = ASN1_CONS;
  912. cursor++;
  913. if (cursor >= end)
  914. goto overrun_error;
  915. if (cursor->token_type == DIRECTIVE_OF) {
  916. element->compound = SEQUENCE_OF;
  917. cursor++;
  918. if (cursor >= end)
  919. goto overrun_error;
  920. element->children = parse_type(&cursor, end, NULL);
  921. } else {
  922. element->children = parse_compound(&cursor, end, 0);
  923. }
  924. break;
  925. case DIRECTIVE_SET:
  926. element->compound = SET;
  927. element->method = ASN1_CONS;
  928. cursor++;
  929. if (cursor >= end)
  930. goto overrun_error;
  931. if (cursor->token_type == DIRECTIVE_OF) {
  932. element->compound = SET_OF;
  933. cursor++;
  934. if (cursor >= end)
  935. goto parse_error;
  936. element->children = parse_type(&cursor, end, NULL);
  937. } else {
  938. element->children = parse_compound(&cursor, end, 1);
  939. }
  940. break;
  941. default:
  942. fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n",
  943. filename, cursor->line,
  944. (int)cursor->size, (int)cursor->size, cursor->value);
  945. exit(1);
  946. }
  947. /* Handle elements that are optional */
  948. if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL ||
  949. cursor->token_type == DIRECTIVE_DEFAULT)
  950. ) {
  951. cursor++;
  952. top->flags |= ELEMENT_SKIPPABLE;
  953. }
  954. if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) {
  955. cursor++;
  956. if (cursor >= end)
  957. goto overrun_error;
  958. if (cursor->token_type != TOKEN_ELEMENT_NAME) {
  959. fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n",
  960. filename, cursor->line,
  961. (int)cursor->size, (int)cursor->size, cursor->value);
  962. exit(1);
  963. }
  964. action = malloc(sizeof(struct action) + cursor->size + 1);
  965. if (!action) {
  966. perror(NULL);
  967. exit(1);
  968. }
  969. action->index = 0;
  970. memcpy(action->name, cursor->value, cursor->size);
  971. action->name[cursor->size] = 0;
  972. for (ppaction = &action_list;
  973. *ppaction;
  974. ppaction = &(*ppaction)->next
  975. ) {
  976. int cmp = strcmp(action->name, (*ppaction)->name);
  977. if (cmp == 0) {
  978. free(action);
  979. action = *ppaction;
  980. goto found;
  981. }
  982. if (cmp < 0) {
  983. action->next = *ppaction;
  984. *ppaction = action;
  985. nr_actions++;
  986. goto found;
  987. }
  988. }
  989. action->next = NULL;
  990. *ppaction = action;
  991. nr_actions++;
  992. found:
  993. element->action = action;
  994. cursor->action = action;
  995. cursor++;
  996. if (cursor >= end)
  997. goto overrun_error;
  998. if (cursor->token_type != TOKEN_CLOSE_ACTION) {
  999. fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n",
  1000. filename, cursor->line,
  1001. (int)cursor->size, (int)cursor->size, cursor->value);
  1002. exit(1);
  1003. }
  1004. cursor++;
  1005. }
  1006. *_cursor = cursor;
  1007. return top;
  1008. parse_error:
  1009. fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n",
  1010. filename, cursor->line,
  1011. (int)cursor->size, (int)cursor->size, cursor->value);
  1012. exit(1);
  1013. overrun_error:
  1014. fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
  1015. exit(1);
  1016. }
  1017. /*
  1018. * Parse a compound type list
  1019. */
  1020. static struct element *parse_compound(struct token **_cursor, struct token *end,
  1021. int alternates)
  1022. {
  1023. struct element *children, **child_p = &children, *element;
  1024. struct token *cursor = *_cursor, *name;
  1025. if (cursor->token_type != TOKEN_OPEN_CURLY) {
  1026. fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n",
  1027. filename, cursor->line,
  1028. (int)cursor->size, (int)cursor->size, cursor->value);
  1029. exit(1);
  1030. }
  1031. cursor++;
  1032. if (cursor >= end)
  1033. goto overrun_error;
  1034. if (cursor->token_type == TOKEN_OPEN_CURLY) {
  1035. fprintf(stderr, "%s:%d: Empty compound\n",
  1036. filename, cursor->line);
  1037. exit(1);
  1038. }
  1039. for (;;) {
  1040. name = NULL;
  1041. if (cursor->token_type == TOKEN_ELEMENT_NAME) {
  1042. name = cursor;
  1043. cursor++;
  1044. if (cursor >= end)
  1045. goto overrun_error;
  1046. }
  1047. element = parse_type(&cursor, end, name);
  1048. if (alternates)
  1049. element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL;
  1050. *child_p = element;
  1051. child_p = &element->next;
  1052. if (cursor >= end)
  1053. goto overrun_error;
  1054. if (cursor->token_type != TOKEN_COMMA)
  1055. break;
  1056. cursor++;
  1057. if (cursor >= end)
  1058. goto overrun_error;
  1059. }
  1060. children->flags &= ~ELEMENT_CONDITIONAL;
  1061. if (cursor->token_type != TOKEN_CLOSE_CURLY) {
  1062. fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n",
  1063. filename, cursor->line,
  1064. (int)cursor->size, (int)cursor->size, cursor->value);
  1065. exit(1);
  1066. }
  1067. cursor++;
  1068. *_cursor = cursor;
  1069. return children;
  1070. overrun_error:
  1071. fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
  1072. exit(1);
  1073. }
  1074. static void render_element(FILE *out, struct element *e, struct element *tag);
  1075. static void render_out_of_line_list(FILE *out);
  1076. static int nr_entries;
  1077. static int render_depth = 1;
  1078. static struct element *render_list, **render_list_p = &render_list;
  1079. __attribute__((format(printf, 2, 3)))
  1080. static void render_opcode(FILE *out, const char *fmt, ...)
  1081. {
  1082. va_list va;
  1083. if (out) {
  1084. fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, "");
  1085. va_start(va, fmt);
  1086. vfprintf(out, fmt, va);
  1087. va_end(va);
  1088. }
  1089. nr_entries++;
  1090. }
  1091. __attribute__((format(printf, 2, 3)))
  1092. static void render_more(FILE *out, const char *fmt, ...)
  1093. {
  1094. va_list va;
  1095. if (out) {
  1096. va_start(va, fmt);
  1097. vfprintf(out, fmt, va);
  1098. va_end(va);
  1099. }
  1100. }
  1101. /*
  1102. * Render the grammar into a state machine definition.
  1103. */
  1104. static void render(FILE *out, FILE *hdr)
  1105. {
  1106. struct element *e;
  1107. struct action *action;
  1108. struct type *root;
  1109. int index;
  1110. fprintf(hdr, "/*\n");
  1111. fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n");
  1112. fprintf(hdr, " *\n");
  1113. fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name);
  1114. fprintf(hdr, " */\n");
  1115. fprintf(hdr, "#include <linux/asn1_decoder.h>\n");
  1116. fprintf(hdr, "\n");
  1117. fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name);
  1118. if (ferror(hdr)) {
  1119. perror(headername);
  1120. exit(1);
  1121. }
  1122. fprintf(out, "/*\n");
  1123. fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n");
  1124. fprintf(out, " *\n");
  1125. fprintf(out, " * ASN.1 parser for %s\n", grammar_name);
  1126. fprintf(out, " */\n");
  1127. fprintf(out, "#include <linux/asn1_ber_bytecode.h>\n");
  1128. fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name);
  1129. fprintf(out, "\n");
  1130. if (ferror(out)) {
  1131. perror(outputname);
  1132. exit(1);
  1133. }
  1134. /* Tabulate the action functions we might have to call */
  1135. fprintf(hdr, "\n");
  1136. index = 0;
  1137. for (action = action_list; action; action = action->next) {
  1138. action->index = index++;
  1139. fprintf(hdr,
  1140. "extern int %s(void *, size_t, unsigned char,"
  1141. " const void *, size_t);\n",
  1142. action->name);
  1143. }
  1144. fprintf(hdr, "\n");
  1145. fprintf(out, "enum %s_actions {\n", grammar_name);
  1146. for (action = action_list; action; action = action->next)
  1147. fprintf(out, "\tACT_%s = %u,\n",
  1148. action->name, action->index);
  1149. fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions);
  1150. fprintf(out, "};\n");
  1151. fprintf(out, "\n");
  1152. fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n",
  1153. grammar_name, grammar_name);
  1154. for (action = action_list; action; action = action->next)
  1155. fprintf(out, "\t[%4u] = %s,\n", action->index, action->name);
  1156. fprintf(out, "};\n");
  1157. if (ferror(out)) {
  1158. perror(outputname);
  1159. exit(1);
  1160. }
  1161. /* We do two passes - the first one calculates all the offsets */
  1162. debug("Pass 1\n");
  1163. nr_entries = 0;
  1164. root = &type_list[0];
  1165. render_element(NULL, root->element, NULL);
  1166. render_opcode(NULL, "ASN1_OP_COMPLETE,\n");
  1167. render_out_of_line_list(NULL);
  1168. for (e = element_list; e; e = e->list_next)
  1169. e->flags &= ~ELEMENT_RENDERED;
  1170. /* And then we actually render */
  1171. debug("Pass 2\n");
  1172. fprintf(out, "\n");
  1173. fprintf(out, "static const unsigned char %s_machine[] = {\n",
  1174. grammar_name);
  1175. nr_entries = 0;
  1176. root = &type_list[0];
  1177. render_element(out, root->element, NULL);
  1178. render_opcode(out, "ASN1_OP_COMPLETE,\n");
  1179. render_out_of_line_list(out);
  1180. fprintf(out, "};\n");
  1181. fprintf(out, "\n");
  1182. fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name);
  1183. fprintf(out, "\t.machine = %s_machine,\n", grammar_name);
  1184. fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name);
  1185. fprintf(out, "\t.actions = %s_action_table,\n", grammar_name);
  1186. fprintf(out, "};\n");
  1187. }
  1188. /*
  1189. * Render the out-of-line elements
  1190. */
  1191. static void render_out_of_line_list(FILE *out)
  1192. {
  1193. struct element *e, *ce;
  1194. const char *act;
  1195. int entry;
  1196. while ((e = render_list)) {
  1197. render_list = e->render_next;
  1198. if (!render_list)
  1199. render_list_p = &render_list;
  1200. render_more(out, "\n");
  1201. e->entry_index = entry = nr_entries;
  1202. render_depth++;
  1203. for (ce = e->children; ce; ce = ce->next)
  1204. render_element(out, ce, NULL);
  1205. render_depth--;
  1206. act = e->action ? "_ACT" : "";
  1207. switch (e->compound) {
  1208. case SEQUENCE:
  1209. render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
  1210. break;
  1211. case SEQUENCE_OF:
  1212. render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
  1213. render_opcode(out, "_jump_target(%u),\n", entry);
  1214. break;
  1215. case SET:
  1216. render_opcode(out, "ASN1_OP_END_SET%s,\n", act);
  1217. break;
  1218. case SET_OF:
  1219. render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
  1220. render_opcode(out, "_jump_target(%u),\n", entry);
  1221. break;
  1222. default:
  1223. break;
  1224. }
  1225. if (e->action)
  1226. render_opcode(out, "_action(ACT_%s),\n",
  1227. e->action->name);
  1228. render_opcode(out, "ASN1_OP_RETURN,\n");
  1229. }
  1230. }
  1231. /*
  1232. * Render an element.
  1233. */
  1234. static void render_element(FILE *out, struct element *e, struct element *tag)
  1235. {
  1236. struct element *ec;
  1237. const char *cond, *act;
  1238. int entry, skippable = 0, outofline = 0;
  1239. if (e->flags & ELEMENT_SKIPPABLE ||
  1240. (tag && tag->flags & ELEMENT_SKIPPABLE))
  1241. skippable = 1;
  1242. if ((e->type_def && e->type_def->ref_count > 1) ||
  1243. skippable)
  1244. outofline = 1;
  1245. if (e->type_def && out) {
  1246. render_more(out, "\t// %*.*s\n",
  1247. (int)e->type_def->name->size, (int)e->type_def->name->size,
  1248. e->type_def->name->value);
  1249. }
  1250. /* Render the operation */
  1251. cond = (e->flags & ELEMENT_CONDITIONAL ||
  1252. (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : "";
  1253. act = e->action ? "_ACT" : "";
  1254. switch (e->compound) {
  1255. case ANY:
  1256. render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act);
  1257. if (e->name)
  1258. render_more(out, "\t\t// %*.*s",
  1259. (int)e->name->size, (int)e->name->size,
  1260. e->name->value);
  1261. render_more(out, "\n");
  1262. goto dont_render_tag;
  1263. case TAG_OVERRIDE:
  1264. render_element(out, e->children, e);
  1265. return;
  1266. case SEQUENCE:
  1267. case SEQUENCE_OF:
  1268. case SET:
  1269. case SET_OF:
  1270. render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
  1271. cond,
  1272. outofline ? "_JUMP" : "",
  1273. skippable ? "_OR_SKIP" : "");
  1274. break;
  1275. case CHOICE:
  1276. goto dont_render_tag;
  1277. case TYPE_REF:
  1278. if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0)
  1279. goto dont_render_tag;
  1280. default:
  1281. render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
  1282. cond, act,
  1283. skippable ? "_OR_SKIP" : "");
  1284. break;
  1285. }
  1286. if (e->name)
  1287. render_more(out, "\t\t// %*.*s",
  1288. (int)e->name->size, (int)e->name->size,
  1289. e->name->value);
  1290. render_more(out, "\n");
  1291. /* Render the tag */
  1292. if (!tag)
  1293. tag = e;
  1294. if (tag->class == ASN1_UNIV &&
  1295. tag->tag != 14 &&
  1296. tag->tag != 15 &&
  1297. tag->tag != 31)
  1298. render_opcode(out, "_tag(%s, %s, %s),\n",
  1299. asn1_classes[tag->class],
  1300. asn1_methods[tag->method | e->method],
  1301. asn1_universal_tags[tag->tag]);
  1302. else
  1303. render_opcode(out, "_tagn(%s, %s, %2u),\n",
  1304. asn1_classes[tag->class],
  1305. asn1_methods[tag->method | e->method],
  1306. tag->tag);
  1307. tag = NULL;
  1308. dont_render_tag:
  1309. /* Deal with compound types */
  1310. switch (e->compound) {
  1311. case TYPE_REF:
  1312. render_element(out, e->type->type->element, tag);
  1313. if (e->action)
  1314. render_opcode(out, "ASN1_OP_ACT,\n");
  1315. break;
  1316. case SEQUENCE:
  1317. if (outofline) {
  1318. /* Render out-of-line for multiple use or
  1319. * skipability */
  1320. render_opcode(out, "_jump_target(%u),", e->entry_index);
  1321. if (e->type_def && e->type_def->name)
  1322. render_more(out, "\t\t// --> %*.*s",
  1323. (int)e->type_def->name->size,
  1324. (int)e->type_def->name->size,
  1325. e->type_def->name->value);
  1326. render_more(out, "\n");
  1327. if (!(e->flags & ELEMENT_RENDERED)) {
  1328. e->flags |= ELEMENT_RENDERED;
  1329. *render_list_p = e;
  1330. render_list_p = &e->render_next;
  1331. }
  1332. return;
  1333. } else {
  1334. /* Render inline for single use */
  1335. render_depth++;
  1336. for (ec = e->children; ec; ec = ec->next)
  1337. render_element(out, ec, NULL);
  1338. render_depth--;
  1339. render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
  1340. }
  1341. break;
  1342. case SEQUENCE_OF:
  1343. case SET_OF:
  1344. if (outofline) {
  1345. /* Render out-of-line for multiple use or
  1346. * skipability */
  1347. render_opcode(out, "_jump_target(%u),", e->entry_index);
  1348. if (e->type_def && e->type_def->name)
  1349. render_more(out, "\t\t// --> %*.*s",
  1350. (int)e->type_def->name->size,
  1351. (int)e->type_def->name->size,
  1352. e->type_def->name->value);
  1353. render_more(out, "\n");
  1354. if (!(e->flags & ELEMENT_RENDERED)) {
  1355. e->flags |= ELEMENT_RENDERED;
  1356. *render_list_p = e;
  1357. render_list_p = &e->render_next;
  1358. }
  1359. return;
  1360. } else {
  1361. /* Render inline for single use */
  1362. entry = nr_entries;
  1363. render_depth++;
  1364. render_element(out, e->children, NULL);
  1365. render_depth--;
  1366. if (e->compound == SEQUENCE_OF)
  1367. render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
  1368. else
  1369. render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
  1370. render_opcode(out, "_jump_target(%u),\n", entry);
  1371. }
  1372. break;
  1373. case SET:
  1374. /* I can't think of a nice way to do SET support without having
  1375. * a stack of bitmasks to make sure no element is repeated.
  1376. * The bitmask has also to be checked that no non-optional
  1377. * elements are left out whilst not preventing optional
  1378. * elements from being left out.
  1379. */
  1380. fprintf(stderr, "The ASN.1 SET type is not currently supported.\n");
  1381. exit(1);
  1382. case CHOICE:
  1383. for (ec = e->children; ec; ec = ec->next)
  1384. render_element(out, ec, NULL);
  1385. if (!skippable)
  1386. render_opcode(out, "ASN1_OP_COND_FAIL,\n");
  1387. if (e->action)
  1388. render_opcode(out, "ASN1_OP_ACT,\n");
  1389. break;
  1390. default:
  1391. break;
  1392. }
  1393. if (e->action)
  1394. render_opcode(out, "_action(ACT_%s),\n", e->action->name);
  1395. }