asn1_compiler.c 35 KB

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