asn1_compiler.c 36 KB

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