18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* Simplified ASN.1 notation parser 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <stdarg.h> 98c2ecf20Sopenharmony_ci#include <stdio.h> 108c2ecf20Sopenharmony_ci#include <stdlib.h> 118c2ecf20Sopenharmony_ci#include <stdint.h> 128c2ecf20Sopenharmony_ci#include <stdbool.h> 138c2ecf20Sopenharmony_ci#include <string.h> 148c2ecf20Sopenharmony_ci#include <ctype.h> 158c2ecf20Sopenharmony_ci#include <unistd.h> 168c2ecf20Sopenharmony_ci#include <fcntl.h> 178c2ecf20Sopenharmony_ci#include <sys/stat.h> 188c2ecf20Sopenharmony_ci#include <linux/asn1_ber_bytecode.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cienum token_type { 218c2ecf20Sopenharmony_ci DIRECTIVE_ABSENT, 228c2ecf20Sopenharmony_ci DIRECTIVE_ALL, 238c2ecf20Sopenharmony_ci DIRECTIVE_ANY, 248c2ecf20Sopenharmony_ci DIRECTIVE_APPLICATION, 258c2ecf20Sopenharmony_ci DIRECTIVE_AUTOMATIC, 268c2ecf20Sopenharmony_ci DIRECTIVE_BEGIN, 278c2ecf20Sopenharmony_ci DIRECTIVE_BIT, 288c2ecf20Sopenharmony_ci DIRECTIVE_BMPString, 298c2ecf20Sopenharmony_ci DIRECTIVE_BOOLEAN, 308c2ecf20Sopenharmony_ci DIRECTIVE_BY, 318c2ecf20Sopenharmony_ci DIRECTIVE_CHARACTER, 328c2ecf20Sopenharmony_ci DIRECTIVE_CHOICE, 338c2ecf20Sopenharmony_ci DIRECTIVE_CLASS, 348c2ecf20Sopenharmony_ci DIRECTIVE_COMPONENT, 358c2ecf20Sopenharmony_ci DIRECTIVE_COMPONENTS, 368c2ecf20Sopenharmony_ci DIRECTIVE_CONSTRAINED, 378c2ecf20Sopenharmony_ci DIRECTIVE_CONTAINING, 388c2ecf20Sopenharmony_ci DIRECTIVE_DEFAULT, 398c2ecf20Sopenharmony_ci DIRECTIVE_DEFINED, 408c2ecf20Sopenharmony_ci DIRECTIVE_DEFINITIONS, 418c2ecf20Sopenharmony_ci DIRECTIVE_EMBEDDED, 428c2ecf20Sopenharmony_ci DIRECTIVE_ENCODED, 438c2ecf20Sopenharmony_ci DIRECTIVE_ENCODING_CONTROL, 448c2ecf20Sopenharmony_ci DIRECTIVE_END, 458c2ecf20Sopenharmony_ci DIRECTIVE_ENUMERATED, 468c2ecf20Sopenharmony_ci DIRECTIVE_EXCEPT, 478c2ecf20Sopenharmony_ci DIRECTIVE_EXPLICIT, 488c2ecf20Sopenharmony_ci DIRECTIVE_EXPORTS, 498c2ecf20Sopenharmony_ci DIRECTIVE_EXTENSIBILITY, 508c2ecf20Sopenharmony_ci DIRECTIVE_EXTERNAL, 518c2ecf20Sopenharmony_ci DIRECTIVE_FALSE, 528c2ecf20Sopenharmony_ci DIRECTIVE_FROM, 538c2ecf20Sopenharmony_ci DIRECTIVE_GeneralString, 548c2ecf20Sopenharmony_ci DIRECTIVE_GeneralizedTime, 558c2ecf20Sopenharmony_ci DIRECTIVE_GraphicString, 568c2ecf20Sopenharmony_ci DIRECTIVE_IA5String, 578c2ecf20Sopenharmony_ci DIRECTIVE_IDENTIFIER, 588c2ecf20Sopenharmony_ci DIRECTIVE_IMPLICIT, 598c2ecf20Sopenharmony_ci DIRECTIVE_IMPLIED, 608c2ecf20Sopenharmony_ci DIRECTIVE_IMPORTS, 618c2ecf20Sopenharmony_ci DIRECTIVE_INCLUDES, 628c2ecf20Sopenharmony_ci DIRECTIVE_INSTANCE, 638c2ecf20Sopenharmony_ci DIRECTIVE_INSTRUCTIONS, 648c2ecf20Sopenharmony_ci DIRECTIVE_INTEGER, 658c2ecf20Sopenharmony_ci DIRECTIVE_INTERSECTION, 668c2ecf20Sopenharmony_ci DIRECTIVE_ISO646String, 678c2ecf20Sopenharmony_ci DIRECTIVE_MAX, 688c2ecf20Sopenharmony_ci DIRECTIVE_MIN, 698c2ecf20Sopenharmony_ci DIRECTIVE_MINUS_INFINITY, 708c2ecf20Sopenharmony_ci DIRECTIVE_NULL, 718c2ecf20Sopenharmony_ci DIRECTIVE_NumericString, 728c2ecf20Sopenharmony_ci DIRECTIVE_OBJECT, 738c2ecf20Sopenharmony_ci DIRECTIVE_OCTET, 748c2ecf20Sopenharmony_ci DIRECTIVE_OF, 758c2ecf20Sopenharmony_ci DIRECTIVE_OPTIONAL, 768c2ecf20Sopenharmony_ci DIRECTIVE_ObjectDescriptor, 778c2ecf20Sopenharmony_ci DIRECTIVE_PATTERN, 788c2ecf20Sopenharmony_ci DIRECTIVE_PDV, 798c2ecf20Sopenharmony_ci DIRECTIVE_PLUS_INFINITY, 808c2ecf20Sopenharmony_ci DIRECTIVE_PRESENT, 818c2ecf20Sopenharmony_ci DIRECTIVE_PRIVATE, 828c2ecf20Sopenharmony_ci DIRECTIVE_PrintableString, 838c2ecf20Sopenharmony_ci DIRECTIVE_REAL, 848c2ecf20Sopenharmony_ci DIRECTIVE_RELATIVE_OID, 858c2ecf20Sopenharmony_ci DIRECTIVE_SEQUENCE, 868c2ecf20Sopenharmony_ci DIRECTIVE_SET, 878c2ecf20Sopenharmony_ci DIRECTIVE_SIZE, 888c2ecf20Sopenharmony_ci DIRECTIVE_STRING, 898c2ecf20Sopenharmony_ci DIRECTIVE_SYNTAX, 908c2ecf20Sopenharmony_ci DIRECTIVE_T61String, 918c2ecf20Sopenharmony_ci DIRECTIVE_TAGS, 928c2ecf20Sopenharmony_ci DIRECTIVE_TRUE, 938c2ecf20Sopenharmony_ci DIRECTIVE_TeletexString, 948c2ecf20Sopenharmony_ci DIRECTIVE_UNION, 958c2ecf20Sopenharmony_ci DIRECTIVE_UNIQUE, 968c2ecf20Sopenharmony_ci DIRECTIVE_UNIVERSAL, 978c2ecf20Sopenharmony_ci DIRECTIVE_UTCTime, 988c2ecf20Sopenharmony_ci DIRECTIVE_UTF8String, 998c2ecf20Sopenharmony_ci DIRECTIVE_UniversalString, 1008c2ecf20Sopenharmony_ci DIRECTIVE_VideotexString, 1018c2ecf20Sopenharmony_ci DIRECTIVE_VisibleString, 1028c2ecf20Sopenharmony_ci DIRECTIVE_WITH, 1038c2ecf20Sopenharmony_ci NR__DIRECTIVES, 1048c2ecf20Sopenharmony_ci TOKEN_ASSIGNMENT = NR__DIRECTIVES, 1058c2ecf20Sopenharmony_ci TOKEN_OPEN_CURLY, 1068c2ecf20Sopenharmony_ci TOKEN_CLOSE_CURLY, 1078c2ecf20Sopenharmony_ci TOKEN_OPEN_SQUARE, 1088c2ecf20Sopenharmony_ci TOKEN_CLOSE_SQUARE, 1098c2ecf20Sopenharmony_ci TOKEN_OPEN_ACTION, 1108c2ecf20Sopenharmony_ci TOKEN_CLOSE_ACTION, 1118c2ecf20Sopenharmony_ci TOKEN_COMMA, 1128c2ecf20Sopenharmony_ci TOKEN_NUMBER, 1138c2ecf20Sopenharmony_ci TOKEN_TYPE_NAME, 1148c2ecf20Sopenharmony_ci TOKEN_ELEMENT_NAME, 1158c2ecf20Sopenharmony_ci NR__TOKENS 1168c2ecf20Sopenharmony_ci}; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic const unsigned char token_to_tag[NR__TOKENS] = { 1198c2ecf20Sopenharmony_ci /* EOC goes first */ 1208c2ecf20Sopenharmony_ci [DIRECTIVE_BOOLEAN] = ASN1_BOOL, 1218c2ecf20Sopenharmony_ci [DIRECTIVE_INTEGER] = ASN1_INT, 1228c2ecf20Sopenharmony_ci [DIRECTIVE_BIT] = ASN1_BTS, 1238c2ecf20Sopenharmony_ci [DIRECTIVE_OCTET] = ASN1_OTS, 1248c2ecf20Sopenharmony_ci [DIRECTIVE_NULL] = ASN1_NULL, 1258c2ecf20Sopenharmony_ci [DIRECTIVE_OBJECT] = ASN1_OID, 1268c2ecf20Sopenharmony_ci [DIRECTIVE_ObjectDescriptor] = ASN1_ODE, 1278c2ecf20Sopenharmony_ci [DIRECTIVE_EXTERNAL] = ASN1_EXT, 1288c2ecf20Sopenharmony_ci [DIRECTIVE_REAL] = ASN1_REAL, 1298c2ecf20Sopenharmony_ci [DIRECTIVE_ENUMERATED] = ASN1_ENUM, 1308c2ecf20Sopenharmony_ci [DIRECTIVE_EMBEDDED] = 0, 1318c2ecf20Sopenharmony_ci [DIRECTIVE_UTF8String] = ASN1_UTF8STR, 1328c2ecf20Sopenharmony_ci [DIRECTIVE_RELATIVE_OID] = ASN1_RELOID, 1338c2ecf20Sopenharmony_ci /* 14 */ 1348c2ecf20Sopenharmony_ci /* 15 */ 1358c2ecf20Sopenharmony_ci [DIRECTIVE_SEQUENCE] = ASN1_SEQ, 1368c2ecf20Sopenharmony_ci [DIRECTIVE_SET] = ASN1_SET, 1378c2ecf20Sopenharmony_ci [DIRECTIVE_NumericString] = ASN1_NUMSTR, 1388c2ecf20Sopenharmony_ci [DIRECTIVE_PrintableString] = ASN1_PRNSTR, 1398c2ecf20Sopenharmony_ci [DIRECTIVE_T61String] = ASN1_TEXSTR, 1408c2ecf20Sopenharmony_ci [DIRECTIVE_TeletexString] = ASN1_TEXSTR, 1418c2ecf20Sopenharmony_ci [DIRECTIVE_VideotexString] = ASN1_VIDSTR, 1428c2ecf20Sopenharmony_ci [DIRECTIVE_IA5String] = ASN1_IA5STR, 1438c2ecf20Sopenharmony_ci [DIRECTIVE_UTCTime] = ASN1_UNITIM, 1448c2ecf20Sopenharmony_ci [DIRECTIVE_GeneralizedTime] = ASN1_GENTIM, 1458c2ecf20Sopenharmony_ci [DIRECTIVE_GraphicString] = ASN1_GRASTR, 1468c2ecf20Sopenharmony_ci [DIRECTIVE_VisibleString] = ASN1_VISSTR, 1478c2ecf20Sopenharmony_ci [DIRECTIVE_GeneralString] = ASN1_GENSTR, 1488c2ecf20Sopenharmony_ci [DIRECTIVE_UniversalString] = ASN1_UNITIM, 1498c2ecf20Sopenharmony_ci [DIRECTIVE_CHARACTER] = ASN1_CHRSTR, 1508c2ecf20Sopenharmony_ci [DIRECTIVE_BMPString] = ASN1_BMPSTR, 1518c2ecf20Sopenharmony_ci}; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cistatic const char asn1_classes[4][5] = { 1548c2ecf20Sopenharmony_ci [ASN1_UNIV] = "UNIV", 1558c2ecf20Sopenharmony_ci [ASN1_APPL] = "APPL", 1568c2ecf20Sopenharmony_ci [ASN1_CONT] = "CONT", 1578c2ecf20Sopenharmony_ci [ASN1_PRIV] = "PRIV" 1588c2ecf20Sopenharmony_ci}; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistatic const char asn1_methods[2][5] = { 1618c2ecf20Sopenharmony_ci [ASN1_UNIV] = "PRIM", 1628c2ecf20Sopenharmony_ci [ASN1_APPL] = "CONS" 1638c2ecf20Sopenharmony_ci}; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic const char *const asn1_universal_tags[32] = { 1668c2ecf20Sopenharmony_ci "EOC", 1678c2ecf20Sopenharmony_ci "BOOL", 1688c2ecf20Sopenharmony_ci "INT", 1698c2ecf20Sopenharmony_ci "BTS", 1708c2ecf20Sopenharmony_ci "OTS", 1718c2ecf20Sopenharmony_ci "NULL", 1728c2ecf20Sopenharmony_ci "OID", 1738c2ecf20Sopenharmony_ci "ODE", 1748c2ecf20Sopenharmony_ci "EXT", 1758c2ecf20Sopenharmony_ci "REAL", 1768c2ecf20Sopenharmony_ci "ENUM", 1778c2ecf20Sopenharmony_ci "EPDV", 1788c2ecf20Sopenharmony_ci "UTF8STR", 1798c2ecf20Sopenharmony_ci "RELOID", 1808c2ecf20Sopenharmony_ci NULL, /* 14 */ 1818c2ecf20Sopenharmony_ci NULL, /* 15 */ 1828c2ecf20Sopenharmony_ci "SEQ", 1838c2ecf20Sopenharmony_ci "SET", 1848c2ecf20Sopenharmony_ci "NUMSTR", 1858c2ecf20Sopenharmony_ci "PRNSTR", 1868c2ecf20Sopenharmony_ci "TEXSTR", 1878c2ecf20Sopenharmony_ci "VIDSTR", 1888c2ecf20Sopenharmony_ci "IA5STR", 1898c2ecf20Sopenharmony_ci "UNITIM", 1908c2ecf20Sopenharmony_ci "GENTIM", 1918c2ecf20Sopenharmony_ci "GRASTR", 1928c2ecf20Sopenharmony_ci "VISSTR", 1938c2ecf20Sopenharmony_ci "GENSTR", 1948c2ecf20Sopenharmony_ci "UNISTR", 1958c2ecf20Sopenharmony_ci "CHRSTR", 1968c2ecf20Sopenharmony_ci "BMPSTR", 1978c2ecf20Sopenharmony_ci NULL /* 31 */ 1988c2ecf20Sopenharmony_ci}; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic const char *filename; 2018c2ecf20Sopenharmony_cistatic const char *grammar_name; 2028c2ecf20Sopenharmony_cistatic const char *outputname; 2038c2ecf20Sopenharmony_cistatic const char *headername; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic const char *const directives[NR__DIRECTIVES] = { 2068c2ecf20Sopenharmony_ci#define _(X) [DIRECTIVE_##X] = #X 2078c2ecf20Sopenharmony_ci _(ABSENT), 2088c2ecf20Sopenharmony_ci _(ALL), 2098c2ecf20Sopenharmony_ci _(ANY), 2108c2ecf20Sopenharmony_ci _(APPLICATION), 2118c2ecf20Sopenharmony_ci _(AUTOMATIC), 2128c2ecf20Sopenharmony_ci _(BEGIN), 2138c2ecf20Sopenharmony_ci _(BIT), 2148c2ecf20Sopenharmony_ci _(BMPString), 2158c2ecf20Sopenharmony_ci _(BOOLEAN), 2168c2ecf20Sopenharmony_ci _(BY), 2178c2ecf20Sopenharmony_ci _(CHARACTER), 2188c2ecf20Sopenharmony_ci _(CHOICE), 2198c2ecf20Sopenharmony_ci _(CLASS), 2208c2ecf20Sopenharmony_ci _(COMPONENT), 2218c2ecf20Sopenharmony_ci _(COMPONENTS), 2228c2ecf20Sopenharmony_ci _(CONSTRAINED), 2238c2ecf20Sopenharmony_ci _(CONTAINING), 2248c2ecf20Sopenharmony_ci _(DEFAULT), 2258c2ecf20Sopenharmony_ci _(DEFINED), 2268c2ecf20Sopenharmony_ci _(DEFINITIONS), 2278c2ecf20Sopenharmony_ci _(EMBEDDED), 2288c2ecf20Sopenharmony_ci _(ENCODED), 2298c2ecf20Sopenharmony_ci [DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL", 2308c2ecf20Sopenharmony_ci _(END), 2318c2ecf20Sopenharmony_ci _(ENUMERATED), 2328c2ecf20Sopenharmony_ci _(EXCEPT), 2338c2ecf20Sopenharmony_ci _(EXPLICIT), 2348c2ecf20Sopenharmony_ci _(EXPORTS), 2358c2ecf20Sopenharmony_ci _(EXTENSIBILITY), 2368c2ecf20Sopenharmony_ci _(EXTERNAL), 2378c2ecf20Sopenharmony_ci _(FALSE), 2388c2ecf20Sopenharmony_ci _(FROM), 2398c2ecf20Sopenharmony_ci _(GeneralString), 2408c2ecf20Sopenharmony_ci _(GeneralizedTime), 2418c2ecf20Sopenharmony_ci _(GraphicString), 2428c2ecf20Sopenharmony_ci _(IA5String), 2438c2ecf20Sopenharmony_ci _(IDENTIFIER), 2448c2ecf20Sopenharmony_ci _(IMPLICIT), 2458c2ecf20Sopenharmony_ci _(IMPLIED), 2468c2ecf20Sopenharmony_ci _(IMPORTS), 2478c2ecf20Sopenharmony_ci _(INCLUDES), 2488c2ecf20Sopenharmony_ci _(INSTANCE), 2498c2ecf20Sopenharmony_ci _(INSTRUCTIONS), 2508c2ecf20Sopenharmony_ci _(INTEGER), 2518c2ecf20Sopenharmony_ci _(INTERSECTION), 2528c2ecf20Sopenharmony_ci _(ISO646String), 2538c2ecf20Sopenharmony_ci _(MAX), 2548c2ecf20Sopenharmony_ci _(MIN), 2558c2ecf20Sopenharmony_ci [DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY", 2568c2ecf20Sopenharmony_ci [DIRECTIVE_NULL] = "NULL", 2578c2ecf20Sopenharmony_ci _(NumericString), 2588c2ecf20Sopenharmony_ci _(OBJECT), 2598c2ecf20Sopenharmony_ci _(OCTET), 2608c2ecf20Sopenharmony_ci _(OF), 2618c2ecf20Sopenharmony_ci _(OPTIONAL), 2628c2ecf20Sopenharmony_ci _(ObjectDescriptor), 2638c2ecf20Sopenharmony_ci _(PATTERN), 2648c2ecf20Sopenharmony_ci _(PDV), 2658c2ecf20Sopenharmony_ci [DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY", 2668c2ecf20Sopenharmony_ci _(PRESENT), 2678c2ecf20Sopenharmony_ci _(PRIVATE), 2688c2ecf20Sopenharmony_ci _(PrintableString), 2698c2ecf20Sopenharmony_ci _(REAL), 2708c2ecf20Sopenharmony_ci [DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID", 2718c2ecf20Sopenharmony_ci _(SEQUENCE), 2728c2ecf20Sopenharmony_ci _(SET), 2738c2ecf20Sopenharmony_ci _(SIZE), 2748c2ecf20Sopenharmony_ci _(STRING), 2758c2ecf20Sopenharmony_ci _(SYNTAX), 2768c2ecf20Sopenharmony_ci _(T61String), 2778c2ecf20Sopenharmony_ci _(TAGS), 2788c2ecf20Sopenharmony_ci _(TRUE), 2798c2ecf20Sopenharmony_ci _(TeletexString), 2808c2ecf20Sopenharmony_ci _(UNION), 2818c2ecf20Sopenharmony_ci _(UNIQUE), 2828c2ecf20Sopenharmony_ci _(UNIVERSAL), 2838c2ecf20Sopenharmony_ci _(UTCTime), 2848c2ecf20Sopenharmony_ci _(UTF8String), 2858c2ecf20Sopenharmony_ci _(UniversalString), 2868c2ecf20Sopenharmony_ci _(VideotexString), 2878c2ecf20Sopenharmony_ci _(VisibleString), 2888c2ecf20Sopenharmony_ci _(WITH) 2898c2ecf20Sopenharmony_ci}; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistruct action { 2928c2ecf20Sopenharmony_ci struct action *next; 2938c2ecf20Sopenharmony_ci char *name; 2948c2ecf20Sopenharmony_ci unsigned char index; 2958c2ecf20Sopenharmony_ci}; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic struct action *action_list; 2988c2ecf20Sopenharmony_cistatic unsigned nr_actions; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistruct token { 3018c2ecf20Sopenharmony_ci unsigned short line; 3028c2ecf20Sopenharmony_ci enum token_type token_type : 8; 3038c2ecf20Sopenharmony_ci unsigned char size; 3048c2ecf20Sopenharmony_ci struct action *action; 3058c2ecf20Sopenharmony_ci char *content; 3068c2ecf20Sopenharmony_ci struct type *type; 3078c2ecf20Sopenharmony_ci}; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_cistatic struct token *token_list; 3108c2ecf20Sopenharmony_cistatic unsigned nr_tokens; 3118c2ecf20Sopenharmony_cistatic bool verbose_opt; 3128c2ecf20Sopenharmony_cistatic bool debug_opt; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci#define verbose(fmt, ...) do { if (verbose_opt) printf(fmt, ## __VA_ARGS__); } while (0) 3158c2ecf20Sopenharmony_ci#define debug(fmt, ...) do { if (debug_opt) printf(fmt, ## __VA_ARGS__); } while (0) 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic int directive_compare(const void *_key, const void *_pdir) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci const struct token *token = _key; 3208c2ecf20Sopenharmony_ci const char *const *pdir = _pdir, *dir = *pdir; 3218c2ecf20Sopenharmony_ci size_t dlen, clen; 3228c2ecf20Sopenharmony_ci int val; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci dlen = strlen(dir); 3258c2ecf20Sopenharmony_ci clen = (dlen < token->size) ? dlen : token->size; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci //debug("cmp(%s,%s) = ", token->content, dir); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci val = memcmp(token->content, dir, clen); 3308c2ecf20Sopenharmony_ci if (val != 0) { 3318c2ecf20Sopenharmony_ci //debug("%d [cmp]\n", val); 3328c2ecf20Sopenharmony_ci return val; 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci if (dlen == token->size) { 3368c2ecf20Sopenharmony_ci //debug("0\n"); 3378c2ecf20Sopenharmony_ci return 0; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci //debug("%d\n", (int)dlen - (int)token->size); 3408c2ecf20Sopenharmony_ci return dlen - token->size; /* shorter -> negative */ 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci/* 3448c2ecf20Sopenharmony_ci * Tokenise an ASN.1 grammar 3458c2ecf20Sopenharmony_ci */ 3468c2ecf20Sopenharmony_cistatic void tokenise(char *buffer, char *end) 3478c2ecf20Sopenharmony_ci{ 3488c2ecf20Sopenharmony_ci struct token *tokens; 3498c2ecf20Sopenharmony_ci char *line, *nl, *start, *p, *q; 3508c2ecf20Sopenharmony_ci unsigned tix, lineno; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci /* Assume we're going to have half as many tokens as we have 3538c2ecf20Sopenharmony_ci * characters 3548c2ecf20Sopenharmony_ci */ 3558c2ecf20Sopenharmony_ci token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token)); 3568c2ecf20Sopenharmony_ci if (!tokens) { 3578c2ecf20Sopenharmony_ci perror(NULL); 3588c2ecf20Sopenharmony_ci exit(1); 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci tix = 0; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci lineno = 0; 3638c2ecf20Sopenharmony_ci while (buffer < end) { 3648c2ecf20Sopenharmony_ci /* First of all, break out a line */ 3658c2ecf20Sopenharmony_ci lineno++; 3668c2ecf20Sopenharmony_ci line = buffer; 3678c2ecf20Sopenharmony_ci nl = memchr(line, '\n', end - buffer); 3688c2ecf20Sopenharmony_ci if (!nl) { 3698c2ecf20Sopenharmony_ci buffer = nl = end; 3708c2ecf20Sopenharmony_ci } else { 3718c2ecf20Sopenharmony_ci buffer = nl + 1; 3728c2ecf20Sopenharmony_ci *nl = '\0'; 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci /* Remove "--" comments */ 3768c2ecf20Sopenharmony_ci p = line; 3778c2ecf20Sopenharmony_ci next_comment: 3788c2ecf20Sopenharmony_ci while ((p = memchr(p, '-', nl - p))) { 3798c2ecf20Sopenharmony_ci if (p[1] == '-') { 3808c2ecf20Sopenharmony_ci /* Found a comment; see if there's a terminator */ 3818c2ecf20Sopenharmony_ci q = p + 2; 3828c2ecf20Sopenharmony_ci while ((q = memchr(q, '-', nl - q))) { 3838c2ecf20Sopenharmony_ci if (q[1] == '-') { 3848c2ecf20Sopenharmony_ci /* There is - excise the comment */ 3858c2ecf20Sopenharmony_ci q += 2; 3868c2ecf20Sopenharmony_ci memmove(p, q, nl - q); 3878c2ecf20Sopenharmony_ci goto next_comment; 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci q++; 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci *p = '\0'; 3928c2ecf20Sopenharmony_ci nl = p; 3938c2ecf20Sopenharmony_ci break; 3948c2ecf20Sopenharmony_ci } else { 3958c2ecf20Sopenharmony_ci p++; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci p = line; 4008c2ecf20Sopenharmony_ci while (p < nl) { 4018c2ecf20Sopenharmony_ci /* Skip white space */ 4028c2ecf20Sopenharmony_ci while (p < nl && isspace(*p)) 4038c2ecf20Sopenharmony_ci *(p++) = 0; 4048c2ecf20Sopenharmony_ci if (p >= nl) 4058c2ecf20Sopenharmony_ci break; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci tokens[tix].line = lineno; 4088c2ecf20Sopenharmony_ci start = p; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* Handle string tokens */ 4118c2ecf20Sopenharmony_ci if (isalpha(*p)) { 4128c2ecf20Sopenharmony_ci const char **dir; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci /* Can be a directive, type name or element 4158c2ecf20Sopenharmony_ci * name. Find the end of the name. 4168c2ecf20Sopenharmony_ci */ 4178c2ecf20Sopenharmony_ci q = p + 1; 4188c2ecf20Sopenharmony_ci while (q < nl && (isalnum(*q) || *q == '-' || *q == '_')) 4198c2ecf20Sopenharmony_ci q++; 4208c2ecf20Sopenharmony_ci tokens[tix].size = q - p; 4218c2ecf20Sopenharmony_ci p = q; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci tokens[tix].content = malloc(tokens[tix].size + 1); 4248c2ecf20Sopenharmony_ci if (!tokens[tix].content) { 4258c2ecf20Sopenharmony_ci perror(NULL); 4268c2ecf20Sopenharmony_ci exit(1); 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci memcpy(tokens[tix].content, start, tokens[tix].size); 4298c2ecf20Sopenharmony_ci tokens[tix].content[tokens[tix].size] = 0; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci /* If it begins with a lowercase letter then 4328c2ecf20Sopenharmony_ci * it's an element name 4338c2ecf20Sopenharmony_ci */ 4348c2ecf20Sopenharmony_ci if (islower(tokens[tix].content[0])) { 4358c2ecf20Sopenharmony_ci tokens[tix++].token_type = TOKEN_ELEMENT_NAME; 4368c2ecf20Sopenharmony_ci continue; 4378c2ecf20Sopenharmony_ci } 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* Otherwise we need to search the directive 4408c2ecf20Sopenharmony_ci * table 4418c2ecf20Sopenharmony_ci */ 4428c2ecf20Sopenharmony_ci dir = bsearch(&tokens[tix], directives, 4438c2ecf20Sopenharmony_ci sizeof(directives) / sizeof(directives[1]), 4448c2ecf20Sopenharmony_ci sizeof(directives[1]), 4458c2ecf20Sopenharmony_ci directive_compare); 4468c2ecf20Sopenharmony_ci if (dir) { 4478c2ecf20Sopenharmony_ci tokens[tix++].token_type = dir - directives; 4488c2ecf20Sopenharmony_ci continue; 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci tokens[tix++].token_type = TOKEN_TYPE_NAME; 4528c2ecf20Sopenharmony_ci continue; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci /* Handle numbers */ 4568c2ecf20Sopenharmony_ci if (isdigit(*p)) { 4578c2ecf20Sopenharmony_ci /* Find the end of the number */ 4588c2ecf20Sopenharmony_ci q = p + 1; 4598c2ecf20Sopenharmony_ci while (q < nl && (isdigit(*q))) 4608c2ecf20Sopenharmony_ci q++; 4618c2ecf20Sopenharmony_ci tokens[tix].size = q - p; 4628c2ecf20Sopenharmony_ci p = q; 4638c2ecf20Sopenharmony_ci tokens[tix].content = malloc(tokens[tix].size + 1); 4648c2ecf20Sopenharmony_ci if (!tokens[tix].content) { 4658c2ecf20Sopenharmony_ci perror(NULL); 4668c2ecf20Sopenharmony_ci exit(1); 4678c2ecf20Sopenharmony_ci } 4688c2ecf20Sopenharmony_ci memcpy(tokens[tix].content, start, tokens[tix].size); 4698c2ecf20Sopenharmony_ci tokens[tix].content[tokens[tix].size] = 0; 4708c2ecf20Sopenharmony_ci tokens[tix++].token_type = TOKEN_NUMBER; 4718c2ecf20Sopenharmony_ci continue; 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci if (nl - p >= 3) { 4758c2ecf20Sopenharmony_ci if (memcmp(p, "::=", 3) == 0) { 4768c2ecf20Sopenharmony_ci p += 3; 4778c2ecf20Sopenharmony_ci tokens[tix].size = 3; 4788c2ecf20Sopenharmony_ci tokens[tix].content = "::="; 4798c2ecf20Sopenharmony_ci tokens[tix++].token_type = TOKEN_ASSIGNMENT; 4808c2ecf20Sopenharmony_ci continue; 4818c2ecf20Sopenharmony_ci } 4828c2ecf20Sopenharmony_ci } 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if (nl - p >= 2) { 4858c2ecf20Sopenharmony_ci if (memcmp(p, "({", 2) == 0) { 4868c2ecf20Sopenharmony_ci p += 2; 4878c2ecf20Sopenharmony_ci tokens[tix].size = 2; 4888c2ecf20Sopenharmony_ci tokens[tix].content = "({"; 4898c2ecf20Sopenharmony_ci tokens[tix++].token_type = TOKEN_OPEN_ACTION; 4908c2ecf20Sopenharmony_ci continue; 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci if (memcmp(p, "})", 2) == 0) { 4938c2ecf20Sopenharmony_ci p += 2; 4948c2ecf20Sopenharmony_ci tokens[tix].size = 2; 4958c2ecf20Sopenharmony_ci tokens[tix].content = "})"; 4968c2ecf20Sopenharmony_ci tokens[tix++].token_type = TOKEN_CLOSE_ACTION; 4978c2ecf20Sopenharmony_ci continue; 4988c2ecf20Sopenharmony_ci } 4998c2ecf20Sopenharmony_ci } 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci if (nl - p >= 1) { 5028c2ecf20Sopenharmony_ci tokens[tix].size = 1; 5038c2ecf20Sopenharmony_ci switch (*p) { 5048c2ecf20Sopenharmony_ci case '{': 5058c2ecf20Sopenharmony_ci p += 1; 5068c2ecf20Sopenharmony_ci tokens[tix].content = "{"; 5078c2ecf20Sopenharmony_ci tokens[tix++].token_type = TOKEN_OPEN_CURLY; 5088c2ecf20Sopenharmony_ci continue; 5098c2ecf20Sopenharmony_ci case '}': 5108c2ecf20Sopenharmony_ci p += 1; 5118c2ecf20Sopenharmony_ci tokens[tix].content = "}"; 5128c2ecf20Sopenharmony_ci tokens[tix++].token_type = TOKEN_CLOSE_CURLY; 5138c2ecf20Sopenharmony_ci continue; 5148c2ecf20Sopenharmony_ci case '[': 5158c2ecf20Sopenharmony_ci p += 1; 5168c2ecf20Sopenharmony_ci tokens[tix].content = "["; 5178c2ecf20Sopenharmony_ci tokens[tix++].token_type = TOKEN_OPEN_SQUARE; 5188c2ecf20Sopenharmony_ci continue; 5198c2ecf20Sopenharmony_ci case ']': 5208c2ecf20Sopenharmony_ci p += 1; 5218c2ecf20Sopenharmony_ci tokens[tix].content = "]"; 5228c2ecf20Sopenharmony_ci tokens[tix++].token_type = TOKEN_CLOSE_SQUARE; 5238c2ecf20Sopenharmony_ci continue; 5248c2ecf20Sopenharmony_ci case ',': 5258c2ecf20Sopenharmony_ci p += 1; 5268c2ecf20Sopenharmony_ci tokens[tix].content = ","; 5278c2ecf20Sopenharmony_ci tokens[tix++].token_type = TOKEN_COMMA; 5288c2ecf20Sopenharmony_ci continue; 5298c2ecf20Sopenharmony_ci default: 5308c2ecf20Sopenharmony_ci break; 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci } 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n", 5358c2ecf20Sopenharmony_ci filename, lineno, *p); 5368c2ecf20Sopenharmony_ci exit(1); 5378c2ecf20Sopenharmony_ci } 5388c2ecf20Sopenharmony_ci } 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci nr_tokens = tix; 5418c2ecf20Sopenharmony_ci verbose("Extracted %u tokens\n", nr_tokens); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci#if 0 5448c2ecf20Sopenharmony_ci { 5458c2ecf20Sopenharmony_ci int n; 5468c2ecf20Sopenharmony_ci for (n = 0; n < nr_tokens; n++) 5478c2ecf20Sopenharmony_ci debug("Token %3u: '%s'\n", n, token_list[n].content); 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci#endif 5508c2ecf20Sopenharmony_ci} 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_cistatic void build_type_list(void); 5538c2ecf20Sopenharmony_cistatic void parse(void); 5548c2ecf20Sopenharmony_cistatic void dump_elements(void); 5558c2ecf20Sopenharmony_cistatic void render(FILE *out, FILE *hdr); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci/* 5588c2ecf20Sopenharmony_ci * 5598c2ecf20Sopenharmony_ci */ 5608c2ecf20Sopenharmony_ciint main(int argc, char **argv) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci struct stat st; 5638c2ecf20Sopenharmony_ci ssize_t readlen; 5648c2ecf20Sopenharmony_ci FILE *out, *hdr; 5658c2ecf20Sopenharmony_ci char *buffer, *p; 5668c2ecf20Sopenharmony_ci char *kbuild_verbose; 5678c2ecf20Sopenharmony_ci int fd; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci kbuild_verbose = getenv("KBUILD_VERBOSE"); 5708c2ecf20Sopenharmony_ci if (kbuild_verbose) 5718c2ecf20Sopenharmony_ci verbose_opt = atoi(kbuild_verbose); 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci while (argc > 4) { 5748c2ecf20Sopenharmony_ci if (strcmp(argv[1], "-v") == 0) 5758c2ecf20Sopenharmony_ci verbose_opt = true; 5768c2ecf20Sopenharmony_ci else if (strcmp(argv[1], "-d") == 0) 5778c2ecf20Sopenharmony_ci debug_opt = true; 5788c2ecf20Sopenharmony_ci else 5798c2ecf20Sopenharmony_ci break; 5808c2ecf20Sopenharmony_ci memmove(&argv[1], &argv[2], (argc - 2) * sizeof(char *)); 5818c2ecf20Sopenharmony_ci argc--; 5828c2ecf20Sopenharmony_ci } 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci if (argc != 4) { 5858c2ecf20Sopenharmony_ci fprintf(stderr, "Format: %s [-v] [-d] <grammar-file> <c-file> <hdr-file>\n", 5868c2ecf20Sopenharmony_ci argv[0]); 5878c2ecf20Sopenharmony_ci exit(2); 5888c2ecf20Sopenharmony_ci } 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci filename = argv[1]; 5918c2ecf20Sopenharmony_ci outputname = argv[2]; 5928c2ecf20Sopenharmony_ci headername = argv[3]; 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci fd = open(filename, O_RDONLY); 5958c2ecf20Sopenharmony_ci if (fd < 0) { 5968c2ecf20Sopenharmony_ci perror(filename); 5978c2ecf20Sopenharmony_ci exit(1); 5988c2ecf20Sopenharmony_ci } 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci if (fstat(fd, &st) < 0) { 6018c2ecf20Sopenharmony_ci perror(filename); 6028c2ecf20Sopenharmony_ci exit(1); 6038c2ecf20Sopenharmony_ci } 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci if (!(buffer = malloc(st.st_size + 1))) { 6068c2ecf20Sopenharmony_ci perror(NULL); 6078c2ecf20Sopenharmony_ci exit(1); 6088c2ecf20Sopenharmony_ci } 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci if ((readlen = read(fd, buffer, st.st_size)) < 0) { 6118c2ecf20Sopenharmony_ci perror(filename); 6128c2ecf20Sopenharmony_ci exit(1); 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci if (close(fd) < 0) { 6168c2ecf20Sopenharmony_ci perror(filename); 6178c2ecf20Sopenharmony_ci exit(1); 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci if (readlen != st.st_size) { 6218c2ecf20Sopenharmony_ci fprintf(stderr, "%s: Short read\n", filename); 6228c2ecf20Sopenharmony_ci exit(1); 6238c2ecf20Sopenharmony_ci } 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci p = strrchr(argv[1], '/'); 6268c2ecf20Sopenharmony_ci p = p ? p + 1 : argv[1]; 6278c2ecf20Sopenharmony_ci grammar_name = strdup(p); 6288c2ecf20Sopenharmony_ci if (!grammar_name) { 6298c2ecf20Sopenharmony_ci perror(NULL); 6308c2ecf20Sopenharmony_ci exit(1); 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci p = strchr(grammar_name, '.'); 6338c2ecf20Sopenharmony_ci if (p) 6348c2ecf20Sopenharmony_ci *p = '\0'; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci buffer[readlen] = 0; 6378c2ecf20Sopenharmony_ci tokenise(buffer, buffer + readlen); 6388c2ecf20Sopenharmony_ci build_type_list(); 6398c2ecf20Sopenharmony_ci parse(); 6408c2ecf20Sopenharmony_ci dump_elements(); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci out = fopen(outputname, "w"); 6438c2ecf20Sopenharmony_ci if (!out) { 6448c2ecf20Sopenharmony_ci perror(outputname); 6458c2ecf20Sopenharmony_ci exit(1); 6468c2ecf20Sopenharmony_ci } 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci hdr = fopen(headername, "w"); 6498c2ecf20Sopenharmony_ci if (!hdr) { 6508c2ecf20Sopenharmony_ci perror(headername); 6518c2ecf20Sopenharmony_ci exit(1); 6528c2ecf20Sopenharmony_ci } 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci render(out, hdr); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci if (fclose(out) < 0) { 6578c2ecf20Sopenharmony_ci perror(outputname); 6588c2ecf20Sopenharmony_ci exit(1); 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci if (fclose(hdr) < 0) { 6628c2ecf20Sopenharmony_ci perror(headername); 6638c2ecf20Sopenharmony_ci exit(1); 6648c2ecf20Sopenharmony_ci } 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci return 0; 6678c2ecf20Sopenharmony_ci} 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_cienum compound { 6708c2ecf20Sopenharmony_ci NOT_COMPOUND, 6718c2ecf20Sopenharmony_ci SET, 6728c2ecf20Sopenharmony_ci SET_OF, 6738c2ecf20Sopenharmony_ci SEQUENCE, 6748c2ecf20Sopenharmony_ci SEQUENCE_OF, 6758c2ecf20Sopenharmony_ci CHOICE, 6768c2ecf20Sopenharmony_ci ANY, 6778c2ecf20Sopenharmony_ci TYPE_REF, 6788c2ecf20Sopenharmony_ci TAG_OVERRIDE 6798c2ecf20Sopenharmony_ci}; 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_cistruct element { 6828c2ecf20Sopenharmony_ci struct type *type_def; 6838c2ecf20Sopenharmony_ci struct token *name; 6848c2ecf20Sopenharmony_ci struct token *type; 6858c2ecf20Sopenharmony_ci struct action *action; 6868c2ecf20Sopenharmony_ci struct element *children; 6878c2ecf20Sopenharmony_ci struct element *next; 6888c2ecf20Sopenharmony_ci struct element *render_next; 6898c2ecf20Sopenharmony_ci struct element *list_next; 6908c2ecf20Sopenharmony_ci uint8_t n_elements; 6918c2ecf20Sopenharmony_ci enum compound compound : 8; 6928c2ecf20Sopenharmony_ci enum asn1_class class : 8; 6938c2ecf20Sopenharmony_ci enum asn1_method method : 8; 6948c2ecf20Sopenharmony_ci uint8_t tag; 6958c2ecf20Sopenharmony_ci unsigned entry_index; 6968c2ecf20Sopenharmony_ci unsigned flags; 6978c2ecf20Sopenharmony_ci#define ELEMENT_IMPLICIT 0x0001 6988c2ecf20Sopenharmony_ci#define ELEMENT_EXPLICIT 0x0002 6998c2ecf20Sopenharmony_ci#define ELEMENT_TAG_SPECIFIED 0x0004 7008c2ecf20Sopenharmony_ci#define ELEMENT_RENDERED 0x0008 7018c2ecf20Sopenharmony_ci#define ELEMENT_SKIPPABLE 0x0010 7028c2ecf20Sopenharmony_ci#define ELEMENT_CONDITIONAL 0x0020 7038c2ecf20Sopenharmony_ci}; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_cistruct type { 7068c2ecf20Sopenharmony_ci struct token *name; 7078c2ecf20Sopenharmony_ci struct token *def; 7088c2ecf20Sopenharmony_ci struct element *element; 7098c2ecf20Sopenharmony_ci unsigned ref_count; 7108c2ecf20Sopenharmony_ci unsigned flags; 7118c2ecf20Sopenharmony_ci#define TYPE_STOP_MARKER 0x0001 7128c2ecf20Sopenharmony_ci#define TYPE_BEGIN 0x0002 7138c2ecf20Sopenharmony_ci}; 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_cistatic struct type *type_list; 7168c2ecf20Sopenharmony_cistatic struct type **type_index; 7178c2ecf20Sopenharmony_cistatic unsigned nr_types; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_cistatic int type_index_compare(const void *_a, const void *_b) 7208c2ecf20Sopenharmony_ci{ 7218c2ecf20Sopenharmony_ci const struct type *const *a = _a, *const *b = _b; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci if ((*a)->name->size != (*b)->name->size) 7248c2ecf20Sopenharmony_ci return (*a)->name->size - (*b)->name->size; 7258c2ecf20Sopenharmony_ci else 7268c2ecf20Sopenharmony_ci return memcmp((*a)->name->content, (*b)->name->content, 7278c2ecf20Sopenharmony_ci (*a)->name->size); 7288c2ecf20Sopenharmony_ci} 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_cistatic int type_finder(const void *_key, const void *_ti) 7318c2ecf20Sopenharmony_ci{ 7328c2ecf20Sopenharmony_ci const struct token *token = _key; 7338c2ecf20Sopenharmony_ci const struct type *const *ti = _ti; 7348c2ecf20Sopenharmony_ci const struct type *type = *ti; 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci if (token->size != type->name->size) 7378c2ecf20Sopenharmony_ci return token->size - type->name->size; 7388c2ecf20Sopenharmony_ci else 7398c2ecf20Sopenharmony_ci return memcmp(token->content, type->name->content, 7408c2ecf20Sopenharmony_ci token->size); 7418c2ecf20Sopenharmony_ci} 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci/* 7448c2ecf20Sopenharmony_ci * Build up a list of types and a sorted index to that list. 7458c2ecf20Sopenharmony_ci */ 7468c2ecf20Sopenharmony_cistatic void build_type_list(void) 7478c2ecf20Sopenharmony_ci{ 7488c2ecf20Sopenharmony_ci struct type *types; 7498c2ecf20Sopenharmony_ci unsigned nr, t, n; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci nr = 0; 7528c2ecf20Sopenharmony_ci for (n = 0; n < nr_tokens - 1; n++) 7538c2ecf20Sopenharmony_ci if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && 7548c2ecf20Sopenharmony_ci token_list[n + 1].token_type == TOKEN_ASSIGNMENT) 7558c2ecf20Sopenharmony_ci nr++; 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci if (nr == 0) { 7588c2ecf20Sopenharmony_ci fprintf(stderr, "%s: No defined types\n", filename); 7598c2ecf20Sopenharmony_ci exit(1); 7608c2ecf20Sopenharmony_ci } 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci nr_types = nr; 7638c2ecf20Sopenharmony_ci types = type_list = calloc(nr + 1, sizeof(type_list[0])); 7648c2ecf20Sopenharmony_ci if (!type_list) { 7658c2ecf20Sopenharmony_ci perror(NULL); 7668c2ecf20Sopenharmony_ci exit(1); 7678c2ecf20Sopenharmony_ci } 7688c2ecf20Sopenharmony_ci type_index = calloc(nr, sizeof(type_index[0])); 7698c2ecf20Sopenharmony_ci if (!type_index) { 7708c2ecf20Sopenharmony_ci perror(NULL); 7718c2ecf20Sopenharmony_ci exit(1); 7728c2ecf20Sopenharmony_ci } 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci t = 0; 7758c2ecf20Sopenharmony_ci types[t].flags |= TYPE_BEGIN; 7768c2ecf20Sopenharmony_ci for (n = 0; n < nr_tokens - 1; n++) { 7778c2ecf20Sopenharmony_ci if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && 7788c2ecf20Sopenharmony_ci token_list[n + 1].token_type == TOKEN_ASSIGNMENT) { 7798c2ecf20Sopenharmony_ci types[t].name = &token_list[n]; 7808c2ecf20Sopenharmony_ci type_index[t] = &types[t]; 7818c2ecf20Sopenharmony_ci t++; 7828c2ecf20Sopenharmony_ci } 7838c2ecf20Sopenharmony_ci } 7848c2ecf20Sopenharmony_ci types[t].name = &token_list[n + 1]; 7858c2ecf20Sopenharmony_ci types[t].flags |= TYPE_STOP_MARKER; 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci verbose("Extracted %u types\n", nr_types); 7908c2ecf20Sopenharmony_ci#if 0 7918c2ecf20Sopenharmony_ci for (n = 0; n < nr_types; n++) { 7928c2ecf20Sopenharmony_ci struct type *type = type_index[n]; 7938c2ecf20Sopenharmony_ci debug("- %*.*s\n", type->name->content); 7948c2ecf20Sopenharmony_ci } 7958c2ecf20Sopenharmony_ci#endif 7968c2ecf20Sopenharmony_ci} 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_cistatic struct element *parse_type(struct token **_cursor, struct token *stop, 7998c2ecf20Sopenharmony_ci struct token *name); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci/* 8028c2ecf20Sopenharmony_ci * Parse the token stream 8038c2ecf20Sopenharmony_ci */ 8048c2ecf20Sopenharmony_cistatic void parse(void) 8058c2ecf20Sopenharmony_ci{ 8068c2ecf20Sopenharmony_ci struct token *cursor; 8078c2ecf20Sopenharmony_ci struct type *type; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci /* Parse one type definition statement at a time */ 8108c2ecf20Sopenharmony_ci type = type_list; 8118c2ecf20Sopenharmony_ci do { 8128c2ecf20Sopenharmony_ci cursor = type->name; 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci if (cursor[0].token_type != TOKEN_TYPE_NAME || 8158c2ecf20Sopenharmony_ci cursor[1].token_type != TOKEN_ASSIGNMENT) 8168c2ecf20Sopenharmony_ci abort(); 8178c2ecf20Sopenharmony_ci cursor += 2; 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci type->element = parse_type(&cursor, type[1].name, NULL); 8208c2ecf20Sopenharmony_ci type->element->type_def = type; 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci if (cursor != type[1].name) { 8238c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d: Parse error at token '%s'\n", 8248c2ecf20Sopenharmony_ci filename, cursor->line, cursor->content); 8258c2ecf20Sopenharmony_ci exit(1); 8268c2ecf20Sopenharmony_ci } 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci } while (type++, !(type->flags & TYPE_STOP_MARKER)); 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci verbose("Extracted %u actions\n", nr_actions); 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_cistatic struct element *element_list; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_cistatic struct element *alloc_elem(struct token *type) 8368c2ecf20Sopenharmony_ci{ 8378c2ecf20Sopenharmony_ci struct element *e = calloc(1, sizeof(*e)); 8388c2ecf20Sopenharmony_ci if (!e) { 8398c2ecf20Sopenharmony_ci perror(NULL); 8408c2ecf20Sopenharmony_ci exit(1); 8418c2ecf20Sopenharmony_ci } 8428c2ecf20Sopenharmony_ci e->list_next = element_list; 8438c2ecf20Sopenharmony_ci element_list = e; 8448c2ecf20Sopenharmony_ci return e; 8458c2ecf20Sopenharmony_ci} 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_cistatic struct element *parse_compound(struct token **_cursor, struct token *end, 8488c2ecf20Sopenharmony_ci int alternates); 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci/* 8518c2ecf20Sopenharmony_ci * Parse one type definition statement 8528c2ecf20Sopenharmony_ci */ 8538c2ecf20Sopenharmony_cistatic struct element *parse_type(struct token **_cursor, struct token *end, 8548c2ecf20Sopenharmony_ci struct token *name) 8558c2ecf20Sopenharmony_ci{ 8568c2ecf20Sopenharmony_ci struct element *top, *element; 8578c2ecf20Sopenharmony_ci struct action *action, **ppaction; 8588c2ecf20Sopenharmony_ci struct token *cursor = *_cursor; 8598c2ecf20Sopenharmony_ci struct type **ref; 8608c2ecf20Sopenharmony_ci char *p; 8618c2ecf20Sopenharmony_ci int labelled = 0, implicit = 0; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci top = element = alloc_elem(cursor); 8648c2ecf20Sopenharmony_ci element->class = ASN1_UNIV; 8658c2ecf20Sopenharmony_ci element->method = ASN1_PRIM; 8668c2ecf20Sopenharmony_ci element->tag = token_to_tag[cursor->token_type]; 8678c2ecf20Sopenharmony_ci element->name = name; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci /* Extract the tag value if one given */ 8708c2ecf20Sopenharmony_ci if (cursor->token_type == TOKEN_OPEN_SQUARE) { 8718c2ecf20Sopenharmony_ci cursor++; 8728c2ecf20Sopenharmony_ci if (cursor >= end) 8738c2ecf20Sopenharmony_ci goto overrun_error; 8748c2ecf20Sopenharmony_ci switch (cursor->token_type) { 8758c2ecf20Sopenharmony_ci case DIRECTIVE_UNIVERSAL: 8768c2ecf20Sopenharmony_ci element->class = ASN1_UNIV; 8778c2ecf20Sopenharmony_ci cursor++; 8788c2ecf20Sopenharmony_ci break; 8798c2ecf20Sopenharmony_ci case DIRECTIVE_APPLICATION: 8808c2ecf20Sopenharmony_ci element->class = ASN1_APPL; 8818c2ecf20Sopenharmony_ci cursor++; 8828c2ecf20Sopenharmony_ci break; 8838c2ecf20Sopenharmony_ci case TOKEN_NUMBER: 8848c2ecf20Sopenharmony_ci element->class = ASN1_CONT; 8858c2ecf20Sopenharmony_ci break; 8868c2ecf20Sopenharmony_ci case DIRECTIVE_PRIVATE: 8878c2ecf20Sopenharmony_ci element->class = ASN1_PRIV; 8888c2ecf20Sopenharmony_ci cursor++; 8898c2ecf20Sopenharmony_ci break; 8908c2ecf20Sopenharmony_ci default: 8918c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d: Unrecognised tag class token '%s'\n", 8928c2ecf20Sopenharmony_ci filename, cursor->line, cursor->content); 8938c2ecf20Sopenharmony_ci exit(1); 8948c2ecf20Sopenharmony_ci } 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci if (cursor >= end) 8978c2ecf20Sopenharmony_ci goto overrun_error; 8988c2ecf20Sopenharmony_ci if (cursor->token_type != TOKEN_NUMBER) { 8998c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d: Missing tag number '%s'\n", 9008c2ecf20Sopenharmony_ci filename, cursor->line, cursor->content); 9018c2ecf20Sopenharmony_ci exit(1); 9028c2ecf20Sopenharmony_ci } 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci element->tag &= ~0x1f; 9058c2ecf20Sopenharmony_ci element->tag |= strtoul(cursor->content, &p, 10); 9068c2ecf20Sopenharmony_ci element->flags |= ELEMENT_TAG_SPECIFIED; 9078c2ecf20Sopenharmony_ci if (p - cursor->content != cursor->size) 9088c2ecf20Sopenharmony_ci abort(); 9098c2ecf20Sopenharmony_ci cursor++; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci if (cursor >= end) 9128c2ecf20Sopenharmony_ci goto overrun_error; 9138c2ecf20Sopenharmony_ci if (cursor->token_type != TOKEN_CLOSE_SQUARE) { 9148c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d: Missing closing square bracket '%s'\n", 9158c2ecf20Sopenharmony_ci filename, cursor->line, cursor->content); 9168c2ecf20Sopenharmony_ci exit(1); 9178c2ecf20Sopenharmony_ci } 9188c2ecf20Sopenharmony_ci cursor++; 9198c2ecf20Sopenharmony_ci if (cursor >= end) 9208c2ecf20Sopenharmony_ci goto overrun_error; 9218c2ecf20Sopenharmony_ci labelled = 1; 9228c2ecf20Sopenharmony_ci } 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci /* Handle implicit and explicit markers */ 9258c2ecf20Sopenharmony_ci if (cursor->token_type == DIRECTIVE_IMPLICIT) { 9268c2ecf20Sopenharmony_ci element->flags |= ELEMENT_IMPLICIT; 9278c2ecf20Sopenharmony_ci implicit = 1; 9288c2ecf20Sopenharmony_ci cursor++; 9298c2ecf20Sopenharmony_ci if (cursor >= end) 9308c2ecf20Sopenharmony_ci goto overrun_error; 9318c2ecf20Sopenharmony_ci } else if (cursor->token_type == DIRECTIVE_EXPLICIT) { 9328c2ecf20Sopenharmony_ci element->flags |= ELEMENT_EXPLICIT; 9338c2ecf20Sopenharmony_ci cursor++; 9348c2ecf20Sopenharmony_ci if (cursor >= end) 9358c2ecf20Sopenharmony_ci goto overrun_error; 9368c2ecf20Sopenharmony_ci } 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci if (labelled) { 9398c2ecf20Sopenharmony_ci if (!implicit) 9408c2ecf20Sopenharmony_ci element->method |= ASN1_CONS; 9418c2ecf20Sopenharmony_ci element->compound = implicit ? TAG_OVERRIDE : SEQUENCE; 9428c2ecf20Sopenharmony_ci element->children = alloc_elem(cursor); 9438c2ecf20Sopenharmony_ci element = element->children; 9448c2ecf20Sopenharmony_ci element->class = ASN1_UNIV; 9458c2ecf20Sopenharmony_ci element->method = ASN1_PRIM; 9468c2ecf20Sopenharmony_ci element->tag = token_to_tag[cursor->token_type]; 9478c2ecf20Sopenharmony_ci element->name = name; 9488c2ecf20Sopenharmony_ci } 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci /* Extract the type we're expecting here */ 9518c2ecf20Sopenharmony_ci element->type = cursor; 9528c2ecf20Sopenharmony_ci switch (cursor->token_type) { 9538c2ecf20Sopenharmony_ci case DIRECTIVE_ANY: 9548c2ecf20Sopenharmony_ci element->compound = ANY; 9558c2ecf20Sopenharmony_ci cursor++; 9568c2ecf20Sopenharmony_ci break; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci case DIRECTIVE_NULL: 9598c2ecf20Sopenharmony_ci case DIRECTIVE_BOOLEAN: 9608c2ecf20Sopenharmony_ci case DIRECTIVE_ENUMERATED: 9618c2ecf20Sopenharmony_ci case DIRECTIVE_INTEGER: 9628c2ecf20Sopenharmony_ci element->compound = NOT_COMPOUND; 9638c2ecf20Sopenharmony_ci cursor++; 9648c2ecf20Sopenharmony_ci break; 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci case DIRECTIVE_EXTERNAL: 9678c2ecf20Sopenharmony_ci element->method = ASN1_CONS; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci case DIRECTIVE_BMPString: 9708c2ecf20Sopenharmony_ci case DIRECTIVE_GeneralString: 9718c2ecf20Sopenharmony_ci case DIRECTIVE_GraphicString: 9728c2ecf20Sopenharmony_ci case DIRECTIVE_IA5String: 9738c2ecf20Sopenharmony_ci case DIRECTIVE_ISO646String: 9748c2ecf20Sopenharmony_ci case DIRECTIVE_NumericString: 9758c2ecf20Sopenharmony_ci case DIRECTIVE_PrintableString: 9768c2ecf20Sopenharmony_ci case DIRECTIVE_T61String: 9778c2ecf20Sopenharmony_ci case DIRECTIVE_TeletexString: 9788c2ecf20Sopenharmony_ci case DIRECTIVE_UniversalString: 9798c2ecf20Sopenharmony_ci case DIRECTIVE_UTF8String: 9808c2ecf20Sopenharmony_ci case DIRECTIVE_VideotexString: 9818c2ecf20Sopenharmony_ci case DIRECTIVE_VisibleString: 9828c2ecf20Sopenharmony_ci case DIRECTIVE_ObjectDescriptor: 9838c2ecf20Sopenharmony_ci case DIRECTIVE_GeneralizedTime: 9848c2ecf20Sopenharmony_ci case DIRECTIVE_UTCTime: 9858c2ecf20Sopenharmony_ci element->compound = NOT_COMPOUND; 9868c2ecf20Sopenharmony_ci cursor++; 9878c2ecf20Sopenharmony_ci break; 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci case DIRECTIVE_BIT: 9908c2ecf20Sopenharmony_ci case DIRECTIVE_OCTET: 9918c2ecf20Sopenharmony_ci element->compound = NOT_COMPOUND; 9928c2ecf20Sopenharmony_ci cursor++; 9938c2ecf20Sopenharmony_ci if (cursor >= end) 9948c2ecf20Sopenharmony_ci goto overrun_error; 9958c2ecf20Sopenharmony_ci if (cursor->token_type != DIRECTIVE_STRING) 9968c2ecf20Sopenharmony_ci goto parse_error; 9978c2ecf20Sopenharmony_ci cursor++; 9988c2ecf20Sopenharmony_ci break; 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci case DIRECTIVE_OBJECT: 10018c2ecf20Sopenharmony_ci element->compound = NOT_COMPOUND; 10028c2ecf20Sopenharmony_ci cursor++; 10038c2ecf20Sopenharmony_ci if (cursor >= end) 10048c2ecf20Sopenharmony_ci goto overrun_error; 10058c2ecf20Sopenharmony_ci if (cursor->token_type != DIRECTIVE_IDENTIFIER) 10068c2ecf20Sopenharmony_ci goto parse_error; 10078c2ecf20Sopenharmony_ci cursor++; 10088c2ecf20Sopenharmony_ci break; 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci case TOKEN_TYPE_NAME: 10118c2ecf20Sopenharmony_ci element->compound = TYPE_REF; 10128c2ecf20Sopenharmony_ci ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]), 10138c2ecf20Sopenharmony_ci type_finder); 10148c2ecf20Sopenharmony_ci if (!ref) { 10158c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d: Type '%s' undefined\n", 10168c2ecf20Sopenharmony_ci filename, cursor->line, cursor->content); 10178c2ecf20Sopenharmony_ci exit(1); 10188c2ecf20Sopenharmony_ci } 10198c2ecf20Sopenharmony_ci cursor->type = *ref; 10208c2ecf20Sopenharmony_ci (*ref)->ref_count++; 10218c2ecf20Sopenharmony_ci cursor++; 10228c2ecf20Sopenharmony_ci break; 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci case DIRECTIVE_CHOICE: 10258c2ecf20Sopenharmony_ci element->compound = CHOICE; 10268c2ecf20Sopenharmony_ci cursor++; 10278c2ecf20Sopenharmony_ci element->children = parse_compound(&cursor, end, 1); 10288c2ecf20Sopenharmony_ci break; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci case DIRECTIVE_SEQUENCE: 10318c2ecf20Sopenharmony_ci element->compound = SEQUENCE; 10328c2ecf20Sopenharmony_ci element->method = ASN1_CONS; 10338c2ecf20Sopenharmony_ci cursor++; 10348c2ecf20Sopenharmony_ci if (cursor >= end) 10358c2ecf20Sopenharmony_ci goto overrun_error; 10368c2ecf20Sopenharmony_ci if (cursor->token_type == DIRECTIVE_OF) { 10378c2ecf20Sopenharmony_ci element->compound = SEQUENCE_OF; 10388c2ecf20Sopenharmony_ci cursor++; 10398c2ecf20Sopenharmony_ci if (cursor >= end) 10408c2ecf20Sopenharmony_ci goto overrun_error; 10418c2ecf20Sopenharmony_ci element->children = parse_type(&cursor, end, NULL); 10428c2ecf20Sopenharmony_ci } else { 10438c2ecf20Sopenharmony_ci element->children = parse_compound(&cursor, end, 0); 10448c2ecf20Sopenharmony_ci } 10458c2ecf20Sopenharmony_ci break; 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci case DIRECTIVE_SET: 10488c2ecf20Sopenharmony_ci element->compound = SET; 10498c2ecf20Sopenharmony_ci element->method = ASN1_CONS; 10508c2ecf20Sopenharmony_ci cursor++; 10518c2ecf20Sopenharmony_ci if (cursor >= end) 10528c2ecf20Sopenharmony_ci goto overrun_error; 10538c2ecf20Sopenharmony_ci if (cursor->token_type == DIRECTIVE_OF) { 10548c2ecf20Sopenharmony_ci element->compound = SET_OF; 10558c2ecf20Sopenharmony_ci cursor++; 10568c2ecf20Sopenharmony_ci if (cursor >= end) 10578c2ecf20Sopenharmony_ci goto parse_error; 10588c2ecf20Sopenharmony_ci element->children = parse_type(&cursor, end, NULL); 10598c2ecf20Sopenharmony_ci } else { 10608c2ecf20Sopenharmony_ci element->children = parse_compound(&cursor, end, 1); 10618c2ecf20Sopenharmony_ci } 10628c2ecf20Sopenharmony_ci break; 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci default: 10658c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d: Token '%s' does not introduce a type\n", 10668c2ecf20Sopenharmony_ci filename, cursor->line, cursor->content); 10678c2ecf20Sopenharmony_ci exit(1); 10688c2ecf20Sopenharmony_ci } 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci /* Handle elements that are optional */ 10718c2ecf20Sopenharmony_ci if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL || 10728c2ecf20Sopenharmony_ci cursor->token_type == DIRECTIVE_DEFAULT) 10738c2ecf20Sopenharmony_ci ) { 10748c2ecf20Sopenharmony_ci cursor++; 10758c2ecf20Sopenharmony_ci top->flags |= ELEMENT_SKIPPABLE; 10768c2ecf20Sopenharmony_ci } 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) { 10798c2ecf20Sopenharmony_ci cursor++; 10808c2ecf20Sopenharmony_ci if (cursor >= end) 10818c2ecf20Sopenharmony_ci goto overrun_error; 10828c2ecf20Sopenharmony_ci if (cursor->token_type != TOKEN_ELEMENT_NAME) { 10838c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d: Token '%s' is not an action function name\n", 10848c2ecf20Sopenharmony_ci filename, cursor->line, cursor->content); 10858c2ecf20Sopenharmony_ci exit(1); 10868c2ecf20Sopenharmony_ci } 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci action = malloc(sizeof(struct action)); 10898c2ecf20Sopenharmony_ci if (!action) { 10908c2ecf20Sopenharmony_ci perror(NULL); 10918c2ecf20Sopenharmony_ci exit(1); 10928c2ecf20Sopenharmony_ci } 10938c2ecf20Sopenharmony_ci action->index = 0; 10948c2ecf20Sopenharmony_ci action->name = cursor->content; 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci for (ppaction = &action_list; 10978c2ecf20Sopenharmony_ci *ppaction; 10988c2ecf20Sopenharmony_ci ppaction = &(*ppaction)->next 10998c2ecf20Sopenharmony_ci ) { 11008c2ecf20Sopenharmony_ci int cmp = strcmp(action->name, (*ppaction)->name); 11018c2ecf20Sopenharmony_ci if (cmp == 0) { 11028c2ecf20Sopenharmony_ci free(action); 11038c2ecf20Sopenharmony_ci action = *ppaction; 11048c2ecf20Sopenharmony_ci goto found; 11058c2ecf20Sopenharmony_ci } 11068c2ecf20Sopenharmony_ci if (cmp < 0) { 11078c2ecf20Sopenharmony_ci action->next = *ppaction; 11088c2ecf20Sopenharmony_ci *ppaction = action; 11098c2ecf20Sopenharmony_ci nr_actions++; 11108c2ecf20Sopenharmony_ci goto found; 11118c2ecf20Sopenharmony_ci } 11128c2ecf20Sopenharmony_ci } 11138c2ecf20Sopenharmony_ci action->next = NULL; 11148c2ecf20Sopenharmony_ci *ppaction = action; 11158c2ecf20Sopenharmony_ci nr_actions++; 11168c2ecf20Sopenharmony_ci found: 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci element->action = action; 11198c2ecf20Sopenharmony_ci cursor->action = action; 11208c2ecf20Sopenharmony_ci cursor++; 11218c2ecf20Sopenharmony_ci if (cursor >= end) 11228c2ecf20Sopenharmony_ci goto overrun_error; 11238c2ecf20Sopenharmony_ci if (cursor->token_type != TOKEN_CLOSE_ACTION) { 11248c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d: Missing close action, got '%s'\n", 11258c2ecf20Sopenharmony_ci filename, cursor->line, cursor->content); 11268c2ecf20Sopenharmony_ci exit(1); 11278c2ecf20Sopenharmony_ci } 11288c2ecf20Sopenharmony_ci cursor++; 11298c2ecf20Sopenharmony_ci } 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci *_cursor = cursor; 11328c2ecf20Sopenharmony_ci return top; 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ciparse_error: 11358c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d: Unexpected token '%s'\n", 11368c2ecf20Sopenharmony_ci filename, cursor->line, cursor->content); 11378c2ecf20Sopenharmony_ci exit(1); 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_cioverrun_error: 11408c2ecf20Sopenharmony_ci fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); 11418c2ecf20Sopenharmony_ci exit(1); 11428c2ecf20Sopenharmony_ci} 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci/* 11458c2ecf20Sopenharmony_ci * Parse a compound type list 11468c2ecf20Sopenharmony_ci */ 11478c2ecf20Sopenharmony_cistatic struct element *parse_compound(struct token **_cursor, struct token *end, 11488c2ecf20Sopenharmony_ci int alternates) 11498c2ecf20Sopenharmony_ci{ 11508c2ecf20Sopenharmony_ci struct element *children, **child_p = &children, *element; 11518c2ecf20Sopenharmony_ci struct token *cursor = *_cursor, *name; 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci if (cursor->token_type != TOKEN_OPEN_CURLY) { 11548c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d: Expected compound to start with brace not '%s'\n", 11558c2ecf20Sopenharmony_ci filename, cursor->line, cursor->content); 11568c2ecf20Sopenharmony_ci exit(1); 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci cursor++; 11598c2ecf20Sopenharmony_ci if (cursor >= end) 11608c2ecf20Sopenharmony_ci goto overrun_error; 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci if (cursor->token_type == TOKEN_OPEN_CURLY) { 11638c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d: Empty compound\n", 11648c2ecf20Sopenharmony_ci filename, cursor->line); 11658c2ecf20Sopenharmony_ci exit(1); 11668c2ecf20Sopenharmony_ci } 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci for (;;) { 11698c2ecf20Sopenharmony_ci name = NULL; 11708c2ecf20Sopenharmony_ci if (cursor->token_type == TOKEN_ELEMENT_NAME) { 11718c2ecf20Sopenharmony_ci name = cursor; 11728c2ecf20Sopenharmony_ci cursor++; 11738c2ecf20Sopenharmony_ci if (cursor >= end) 11748c2ecf20Sopenharmony_ci goto overrun_error; 11758c2ecf20Sopenharmony_ci } 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci element = parse_type(&cursor, end, name); 11788c2ecf20Sopenharmony_ci if (alternates) 11798c2ecf20Sopenharmony_ci element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci *child_p = element; 11828c2ecf20Sopenharmony_ci child_p = &element->next; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci if (cursor >= end) 11858c2ecf20Sopenharmony_ci goto overrun_error; 11868c2ecf20Sopenharmony_ci if (cursor->token_type != TOKEN_COMMA) 11878c2ecf20Sopenharmony_ci break; 11888c2ecf20Sopenharmony_ci cursor++; 11898c2ecf20Sopenharmony_ci if (cursor >= end) 11908c2ecf20Sopenharmony_ci goto overrun_error; 11918c2ecf20Sopenharmony_ci } 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci children->flags &= ~ELEMENT_CONDITIONAL; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci if (cursor->token_type != TOKEN_CLOSE_CURLY) { 11968c2ecf20Sopenharmony_ci fprintf(stderr, "%s:%d: Expected compound closure, got '%s'\n", 11978c2ecf20Sopenharmony_ci filename, cursor->line, cursor->content); 11988c2ecf20Sopenharmony_ci exit(1); 11998c2ecf20Sopenharmony_ci } 12008c2ecf20Sopenharmony_ci cursor++; 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci *_cursor = cursor; 12038c2ecf20Sopenharmony_ci return children; 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_cioverrun_error: 12068c2ecf20Sopenharmony_ci fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); 12078c2ecf20Sopenharmony_ci exit(1); 12088c2ecf20Sopenharmony_ci} 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_cistatic void dump_element(const struct element *e, int level) 12118c2ecf20Sopenharmony_ci{ 12128c2ecf20Sopenharmony_ci const struct element *c; 12138c2ecf20Sopenharmony_ci const struct type *t = e->type_def; 12148c2ecf20Sopenharmony_ci const char *name = e->name ? e->name->content : "."; 12158c2ecf20Sopenharmony_ci const char *tname = t && t->name ? t->name->content : "."; 12168c2ecf20Sopenharmony_ci char tag[32]; 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci if (e->class == 0 && e->method == 0 && e->tag == 0) 12198c2ecf20Sopenharmony_ci strcpy(tag, "<...>"); 12208c2ecf20Sopenharmony_ci else if (e->class == ASN1_UNIV) 12218c2ecf20Sopenharmony_ci sprintf(tag, "%s %s %s", 12228c2ecf20Sopenharmony_ci asn1_classes[e->class], 12238c2ecf20Sopenharmony_ci asn1_methods[e->method], 12248c2ecf20Sopenharmony_ci asn1_universal_tags[e->tag]); 12258c2ecf20Sopenharmony_ci else 12268c2ecf20Sopenharmony_ci sprintf(tag, "%s %s %u", 12278c2ecf20Sopenharmony_ci asn1_classes[e->class], 12288c2ecf20Sopenharmony_ci asn1_methods[e->method], 12298c2ecf20Sopenharmony_ci e->tag); 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci printf("%c%c%c%c%c %c %*s[*] \e[33m%s\e[m %s %s \e[35m%s\e[m\n", 12328c2ecf20Sopenharmony_ci e->flags & ELEMENT_IMPLICIT ? 'I' : '-', 12338c2ecf20Sopenharmony_ci e->flags & ELEMENT_EXPLICIT ? 'E' : '-', 12348c2ecf20Sopenharmony_ci e->flags & ELEMENT_TAG_SPECIFIED ? 'T' : '-', 12358c2ecf20Sopenharmony_ci e->flags & ELEMENT_SKIPPABLE ? 'S' : '-', 12368c2ecf20Sopenharmony_ci e->flags & ELEMENT_CONDITIONAL ? 'C' : '-', 12378c2ecf20Sopenharmony_ci "-tTqQcaro"[e->compound], 12388c2ecf20Sopenharmony_ci level, "", 12398c2ecf20Sopenharmony_ci tag, 12408c2ecf20Sopenharmony_ci tname, 12418c2ecf20Sopenharmony_ci name, 12428c2ecf20Sopenharmony_ci e->action ? e->action->name : ""); 12438c2ecf20Sopenharmony_ci if (e->compound == TYPE_REF) 12448c2ecf20Sopenharmony_ci dump_element(e->type->type->element, level + 3); 12458c2ecf20Sopenharmony_ci else 12468c2ecf20Sopenharmony_ci for (c = e->children; c; c = c->next) 12478c2ecf20Sopenharmony_ci dump_element(c, level + 3); 12488c2ecf20Sopenharmony_ci} 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_cistatic void dump_elements(void) 12518c2ecf20Sopenharmony_ci{ 12528c2ecf20Sopenharmony_ci if (debug_opt) 12538c2ecf20Sopenharmony_ci dump_element(type_list[0].element, 0); 12548c2ecf20Sopenharmony_ci} 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_cistatic void render_element(FILE *out, struct element *e, struct element *tag); 12578c2ecf20Sopenharmony_cistatic void render_out_of_line_list(FILE *out); 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_cistatic int nr_entries; 12608c2ecf20Sopenharmony_cistatic int render_depth = 1; 12618c2ecf20Sopenharmony_cistatic struct element *render_list, **render_list_p = &render_list; 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci__attribute__((format(printf, 2, 3))) 12648c2ecf20Sopenharmony_cistatic void render_opcode(FILE *out, const char *fmt, ...) 12658c2ecf20Sopenharmony_ci{ 12668c2ecf20Sopenharmony_ci va_list va; 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci if (out) { 12698c2ecf20Sopenharmony_ci fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, ""); 12708c2ecf20Sopenharmony_ci va_start(va, fmt); 12718c2ecf20Sopenharmony_ci vfprintf(out, fmt, va); 12728c2ecf20Sopenharmony_ci va_end(va); 12738c2ecf20Sopenharmony_ci } 12748c2ecf20Sopenharmony_ci nr_entries++; 12758c2ecf20Sopenharmony_ci} 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci__attribute__((format(printf, 2, 3))) 12788c2ecf20Sopenharmony_cistatic void render_more(FILE *out, const char *fmt, ...) 12798c2ecf20Sopenharmony_ci{ 12808c2ecf20Sopenharmony_ci va_list va; 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci if (out) { 12838c2ecf20Sopenharmony_ci va_start(va, fmt); 12848c2ecf20Sopenharmony_ci vfprintf(out, fmt, va); 12858c2ecf20Sopenharmony_ci va_end(va); 12868c2ecf20Sopenharmony_ci } 12878c2ecf20Sopenharmony_ci} 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci/* 12908c2ecf20Sopenharmony_ci * Render the grammar into a state machine definition. 12918c2ecf20Sopenharmony_ci */ 12928c2ecf20Sopenharmony_cistatic void render(FILE *out, FILE *hdr) 12938c2ecf20Sopenharmony_ci{ 12948c2ecf20Sopenharmony_ci struct element *e; 12958c2ecf20Sopenharmony_ci struct action *action; 12968c2ecf20Sopenharmony_ci struct type *root; 12978c2ecf20Sopenharmony_ci int index; 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci fprintf(hdr, "/*\n"); 13008c2ecf20Sopenharmony_ci fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n"); 13018c2ecf20Sopenharmony_ci fprintf(hdr, " *\n"); 13028c2ecf20Sopenharmony_ci fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name); 13038c2ecf20Sopenharmony_ci fprintf(hdr, " */\n"); 13048c2ecf20Sopenharmony_ci fprintf(hdr, "#include <linux/asn1_decoder.h>\n"); 13058c2ecf20Sopenharmony_ci fprintf(hdr, "\n"); 13068c2ecf20Sopenharmony_ci fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name); 13078c2ecf20Sopenharmony_ci if (ferror(hdr)) { 13088c2ecf20Sopenharmony_ci perror(headername); 13098c2ecf20Sopenharmony_ci exit(1); 13108c2ecf20Sopenharmony_ci } 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci fprintf(out, "/*\n"); 13138c2ecf20Sopenharmony_ci fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n"); 13148c2ecf20Sopenharmony_ci fprintf(out, " *\n"); 13158c2ecf20Sopenharmony_ci fprintf(out, " * ASN.1 parser for %s\n", grammar_name); 13168c2ecf20Sopenharmony_ci fprintf(out, " */\n"); 13178c2ecf20Sopenharmony_ci fprintf(out, "#include <linux/asn1_ber_bytecode.h>\n"); 13188c2ecf20Sopenharmony_ci fprintf(out, "#include \"%s.asn1.h\"\n", grammar_name); 13198c2ecf20Sopenharmony_ci fprintf(out, "\n"); 13208c2ecf20Sopenharmony_ci if (ferror(out)) { 13218c2ecf20Sopenharmony_ci perror(outputname); 13228c2ecf20Sopenharmony_ci exit(1); 13238c2ecf20Sopenharmony_ci } 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci /* Tabulate the action functions we might have to call */ 13268c2ecf20Sopenharmony_ci fprintf(hdr, "\n"); 13278c2ecf20Sopenharmony_ci index = 0; 13288c2ecf20Sopenharmony_ci for (action = action_list; action; action = action->next) { 13298c2ecf20Sopenharmony_ci action->index = index++; 13308c2ecf20Sopenharmony_ci fprintf(hdr, 13318c2ecf20Sopenharmony_ci "extern int %s(void *, size_t, unsigned char," 13328c2ecf20Sopenharmony_ci " const void *, size_t);\n", 13338c2ecf20Sopenharmony_ci action->name); 13348c2ecf20Sopenharmony_ci } 13358c2ecf20Sopenharmony_ci fprintf(hdr, "\n"); 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci fprintf(out, "enum %s_actions {\n", grammar_name); 13388c2ecf20Sopenharmony_ci for (action = action_list; action; action = action->next) 13398c2ecf20Sopenharmony_ci fprintf(out, "\tACT_%s = %u,\n", 13408c2ecf20Sopenharmony_ci action->name, action->index); 13418c2ecf20Sopenharmony_ci fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions); 13428c2ecf20Sopenharmony_ci fprintf(out, "};\n"); 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci fprintf(out, "\n"); 13458c2ecf20Sopenharmony_ci fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n", 13468c2ecf20Sopenharmony_ci grammar_name, grammar_name); 13478c2ecf20Sopenharmony_ci for (action = action_list; action; action = action->next) 13488c2ecf20Sopenharmony_ci fprintf(out, "\t[%4u] = %s,\n", action->index, action->name); 13498c2ecf20Sopenharmony_ci fprintf(out, "};\n"); 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci if (ferror(out)) { 13528c2ecf20Sopenharmony_ci perror(outputname); 13538c2ecf20Sopenharmony_ci exit(1); 13548c2ecf20Sopenharmony_ci } 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci /* We do two passes - the first one calculates all the offsets */ 13578c2ecf20Sopenharmony_ci verbose("Pass 1\n"); 13588c2ecf20Sopenharmony_ci nr_entries = 0; 13598c2ecf20Sopenharmony_ci root = &type_list[0]; 13608c2ecf20Sopenharmony_ci render_element(NULL, root->element, NULL); 13618c2ecf20Sopenharmony_ci render_opcode(NULL, "ASN1_OP_COMPLETE,\n"); 13628c2ecf20Sopenharmony_ci render_out_of_line_list(NULL); 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci for (e = element_list; e; e = e->list_next) 13658c2ecf20Sopenharmony_ci e->flags &= ~ELEMENT_RENDERED; 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci /* And then we actually render */ 13688c2ecf20Sopenharmony_ci verbose("Pass 2\n"); 13698c2ecf20Sopenharmony_ci fprintf(out, "\n"); 13708c2ecf20Sopenharmony_ci fprintf(out, "static const unsigned char %s_machine[] = {\n", 13718c2ecf20Sopenharmony_ci grammar_name); 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci nr_entries = 0; 13748c2ecf20Sopenharmony_ci root = &type_list[0]; 13758c2ecf20Sopenharmony_ci render_element(out, root->element, NULL); 13768c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_COMPLETE,\n"); 13778c2ecf20Sopenharmony_ci render_out_of_line_list(out); 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci fprintf(out, "};\n"); 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci fprintf(out, "\n"); 13828c2ecf20Sopenharmony_ci fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name); 13838c2ecf20Sopenharmony_ci fprintf(out, "\t.machine = %s_machine,\n", grammar_name); 13848c2ecf20Sopenharmony_ci fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name); 13858c2ecf20Sopenharmony_ci fprintf(out, "\t.actions = %s_action_table,\n", grammar_name); 13868c2ecf20Sopenharmony_ci fprintf(out, "};\n"); 13878c2ecf20Sopenharmony_ci} 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci/* 13908c2ecf20Sopenharmony_ci * Render the out-of-line elements 13918c2ecf20Sopenharmony_ci */ 13928c2ecf20Sopenharmony_cistatic void render_out_of_line_list(FILE *out) 13938c2ecf20Sopenharmony_ci{ 13948c2ecf20Sopenharmony_ci struct element *e, *ce; 13958c2ecf20Sopenharmony_ci const char *act; 13968c2ecf20Sopenharmony_ci int entry; 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci while ((e = render_list)) { 13998c2ecf20Sopenharmony_ci render_list = e->render_next; 14008c2ecf20Sopenharmony_ci if (!render_list) 14018c2ecf20Sopenharmony_ci render_list_p = &render_list; 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci render_more(out, "\n"); 14048c2ecf20Sopenharmony_ci e->entry_index = entry = nr_entries; 14058c2ecf20Sopenharmony_ci render_depth++; 14068c2ecf20Sopenharmony_ci for (ce = e->children; ce; ce = ce->next) 14078c2ecf20Sopenharmony_ci render_element(out, ce, NULL); 14088c2ecf20Sopenharmony_ci render_depth--; 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci act = e->action ? "_ACT" : ""; 14118c2ecf20Sopenharmony_ci switch (e->compound) { 14128c2ecf20Sopenharmony_ci case SEQUENCE: 14138c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); 14148c2ecf20Sopenharmony_ci break; 14158c2ecf20Sopenharmony_ci case SEQUENCE_OF: 14168c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); 14178c2ecf20Sopenharmony_ci render_opcode(out, "_jump_target(%u),\n", entry); 14188c2ecf20Sopenharmony_ci break; 14198c2ecf20Sopenharmony_ci case SET: 14208c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_END_SET%s,\n", act); 14218c2ecf20Sopenharmony_ci break; 14228c2ecf20Sopenharmony_ci case SET_OF: 14238c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); 14248c2ecf20Sopenharmony_ci render_opcode(out, "_jump_target(%u),\n", entry); 14258c2ecf20Sopenharmony_ci break; 14268c2ecf20Sopenharmony_ci default: 14278c2ecf20Sopenharmony_ci break; 14288c2ecf20Sopenharmony_ci } 14298c2ecf20Sopenharmony_ci if (e->action) 14308c2ecf20Sopenharmony_ci render_opcode(out, "_action(ACT_%s),\n", 14318c2ecf20Sopenharmony_ci e->action->name); 14328c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_RETURN,\n"); 14338c2ecf20Sopenharmony_ci } 14348c2ecf20Sopenharmony_ci} 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci/* 14378c2ecf20Sopenharmony_ci * Render an element. 14388c2ecf20Sopenharmony_ci */ 14398c2ecf20Sopenharmony_cistatic void render_element(FILE *out, struct element *e, struct element *tag) 14408c2ecf20Sopenharmony_ci{ 14418c2ecf20Sopenharmony_ci struct element *ec, *x; 14428c2ecf20Sopenharmony_ci const char *cond, *act; 14438c2ecf20Sopenharmony_ci int entry, skippable = 0, outofline = 0; 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci if (e->flags & ELEMENT_SKIPPABLE || 14468c2ecf20Sopenharmony_ci (tag && tag->flags & ELEMENT_SKIPPABLE)) 14478c2ecf20Sopenharmony_ci skippable = 1; 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci if ((e->type_def && e->type_def->ref_count > 1) || 14508c2ecf20Sopenharmony_ci skippable) 14518c2ecf20Sopenharmony_ci outofline = 1; 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci if (e->type_def && out) { 14548c2ecf20Sopenharmony_ci render_more(out, "\t// %s\n", e->type_def->name->content); 14558c2ecf20Sopenharmony_ci } 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci /* Render the operation */ 14588c2ecf20Sopenharmony_ci cond = (e->flags & ELEMENT_CONDITIONAL || 14598c2ecf20Sopenharmony_ci (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : ""; 14608c2ecf20Sopenharmony_ci act = e->action ? "_ACT" : ""; 14618c2ecf20Sopenharmony_ci switch (e->compound) { 14628c2ecf20Sopenharmony_ci case ANY: 14638c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,", 14648c2ecf20Sopenharmony_ci cond, act, skippable ? "_OR_SKIP" : ""); 14658c2ecf20Sopenharmony_ci if (e->name) 14668c2ecf20Sopenharmony_ci render_more(out, "\t\t// %s", e->name->content); 14678c2ecf20Sopenharmony_ci render_more(out, "\n"); 14688c2ecf20Sopenharmony_ci goto dont_render_tag; 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci case TAG_OVERRIDE: 14718c2ecf20Sopenharmony_ci render_element(out, e->children, e); 14728c2ecf20Sopenharmony_ci return; 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci case SEQUENCE: 14758c2ecf20Sopenharmony_ci case SEQUENCE_OF: 14768c2ecf20Sopenharmony_ci case SET: 14778c2ecf20Sopenharmony_ci case SET_OF: 14788c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_%sMATCH%s%s,", 14798c2ecf20Sopenharmony_ci cond, 14808c2ecf20Sopenharmony_ci outofline ? "_JUMP" : "", 14818c2ecf20Sopenharmony_ci skippable ? "_OR_SKIP" : ""); 14828c2ecf20Sopenharmony_ci break; 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci case CHOICE: 14858c2ecf20Sopenharmony_ci goto dont_render_tag; 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci case TYPE_REF: 14888c2ecf20Sopenharmony_ci if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0) 14898c2ecf20Sopenharmony_ci goto dont_render_tag; 14908c2ecf20Sopenharmony_ci default: 14918c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_%sMATCH%s%s,", 14928c2ecf20Sopenharmony_ci cond, act, 14938c2ecf20Sopenharmony_ci skippable ? "_OR_SKIP" : ""); 14948c2ecf20Sopenharmony_ci break; 14958c2ecf20Sopenharmony_ci } 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci x = tag ?: e; 14988c2ecf20Sopenharmony_ci if (x->name) 14998c2ecf20Sopenharmony_ci render_more(out, "\t\t// %s", x->name->content); 15008c2ecf20Sopenharmony_ci render_more(out, "\n"); 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci /* Render the tag */ 15038c2ecf20Sopenharmony_ci if (!tag || !(tag->flags & ELEMENT_TAG_SPECIFIED)) 15048c2ecf20Sopenharmony_ci tag = e; 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci if (tag->class == ASN1_UNIV && 15078c2ecf20Sopenharmony_ci tag->tag != 14 && 15088c2ecf20Sopenharmony_ci tag->tag != 15 && 15098c2ecf20Sopenharmony_ci tag->tag != 31) 15108c2ecf20Sopenharmony_ci render_opcode(out, "_tag(%s, %s, %s),\n", 15118c2ecf20Sopenharmony_ci asn1_classes[tag->class], 15128c2ecf20Sopenharmony_ci asn1_methods[tag->method | e->method], 15138c2ecf20Sopenharmony_ci asn1_universal_tags[tag->tag]); 15148c2ecf20Sopenharmony_ci else 15158c2ecf20Sopenharmony_ci render_opcode(out, "_tagn(%s, %s, %2u),\n", 15168c2ecf20Sopenharmony_ci asn1_classes[tag->class], 15178c2ecf20Sopenharmony_ci asn1_methods[tag->method | e->method], 15188c2ecf20Sopenharmony_ci tag->tag); 15198c2ecf20Sopenharmony_ci tag = NULL; 15208c2ecf20Sopenharmony_cidont_render_tag: 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci /* Deal with compound types */ 15238c2ecf20Sopenharmony_ci switch (e->compound) { 15248c2ecf20Sopenharmony_ci case TYPE_REF: 15258c2ecf20Sopenharmony_ci render_element(out, e->type->type->element, tag); 15268c2ecf20Sopenharmony_ci if (e->action) 15278c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_%sACT,\n", 15288c2ecf20Sopenharmony_ci skippable ? "MAYBE_" : ""); 15298c2ecf20Sopenharmony_ci break; 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci case SEQUENCE: 15328c2ecf20Sopenharmony_ci if (outofline) { 15338c2ecf20Sopenharmony_ci /* Render out-of-line for multiple use or 15348c2ecf20Sopenharmony_ci * skipability */ 15358c2ecf20Sopenharmony_ci render_opcode(out, "_jump_target(%u),", e->entry_index); 15368c2ecf20Sopenharmony_ci if (e->type_def && e->type_def->name) 15378c2ecf20Sopenharmony_ci render_more(out, "\t\t// --> %s", 15388c2ecf20Sopenharmony_ci e->type_def->name->content); 15398c2ecf20Sopenharmony_ci render_more(out, "\n"); 15408c2ecf20Sopenharmony_ci if (!(e->flags & ELEMENT_RENDERED)) { 15418c2ecf20Sopenharmony_ci e->flags |= ELEMENT_RENDERED; 15428c2ecf20Sopenharmony_ci *render_list_p = e; 15438c2ecf20Sopenharmony_ci render_list_p = &e->render_next; 15448c2ecf20Sopenharmony_ci } 15458c2ecf20Sopenharmony_ci return; 15468c2ecf20Sopenharmony_ci } else { 15478c2ecf20Sopenharmony_ci /* Render inline for single use */ 15488c2ecf20Sopenharmony_ci render_depth++; 15498c2ecf20Sopenharmony_ci for (ec = e->children; ec; ec = ec->next) 15508c2ecf20Sopenharmony_ci render_element(out, ec, NULL); 15518c2ecf20Sopenharmony_ci render_depth--; 15528c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); 15538c2ecf20Sopenharmony_ci } 15548c2ecf20Sopenharmony_ci break; 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci case SEQUENCE_OF: 15578c2ecf20Sopenharmony_ci case SET_OF: 15588c2ecf20Sopenharmony_ci if (outofline) { 15598c2ecf20Sopenharmony_ci /* Render out-of-line for multiple use or 15608c2ecf20Sopenharmony_ci * skipability */ 15618c2ecf20Sopenharmony_ci render_opcode(out, "_jump_target(%u),", e->entry_index); 15628c2ecf20Sopenharmony_ci if (e->type_def && e->type_def->name) 15638c2ecf20Sopenharmony_ci render_more(out, "\t\t// --> %s", 15648c2ecf20Sopenharmony_ci e->type_def->name->content); 15658c2ecf20Sopenharmony_ci render_more(out, "\n"); 15668c2ecf20Sopenharmony_ci if (!(e->flags & ELEMENT_RENDERED)) { 15678c2ecf20Sopenharmony_ci e->flags |= ELEMENT_RENDERED; 15688c2ecf20Sopenharmony_ci *render_list_p = e; 15698c2ecf20Sopenharmony_ci render_list_p = &e->render_next; 15708c2ecf20Sopenharmony_ci } 15718c2ecf20Sopenharmony_ci return; 15728c2ecf20Sopenharmony_ci } else { 15738c2ecf20Sopenharmony_ci /* Render inline for single use */ 15748c2ecf20Sopenharmony_ci entry = nr_entries; 15758c2ecf20Sopenharmony_ci render_depth++; 15768c2ecf20Sopenharmony_ci render_element(out, e->children, NULL); 15778c2ecf20Sopenharmony_ci render_depth--; 15788c2ecf20Sopenharmony_ci if (e->compound == SEQUENCE_OF) 15798c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); 15808c2ecf20Sopenharmony_ci else 15818c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); 15828c2ecf20Sopenharmony_ci render_opcode(out, "_jump_target(%u),\n", entry); 15838c2ecf20Sopenharmony_ci } 15848c2ecf20Sopenharmony_ci break; 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci case SET: 15878c2ecf20Sopenharmony_ci /* I can't think of a nice way to do SET support without having 15888c2ecf20Sopenharmony_ci * a stack of bitmasks to make sure no element is repeated. 15898c2ecf20Sopenharmony_ci * The bitmask has also to be checked that no non-optional 15908c2ecf20Sopenharmony_ci * elements are left out whilst not preventing optional 15918c2ecf20Sopenharmony_ci * elements from being left out. 15928c2ecf20Sopenharmony_ci */ 15938c2ecf20Sopenharmony_ci fprintf(stderr, "The ASN.1 SET type is not currently supported.\n"); 15948c2ecf20Sopenharmony_ci exit(1); 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci case CHOICE: 15978c2ecf20Sopenharmony_ci for (ec = e->children; ec; ec = ec->next) 15988c2ecf20Sopenharmony_ci render_element(out, ec, ec); 15998c2ecf20Sopenharmony_ci if (!skippable) 16008c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_COND_FAIL,\n"); 16018c2ecf20Sopenharmony_ci if (e->action) 16028c2ecf20Sopenharmony_ci render_opcode(out, "ASN1_OP_ACT,\n"); 16038c2ecf20Sopenharmony_ci break; 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci default: 16068c2ecf20Sopenharmony_ci break; 16078c2ecf20Sopenharmony_ci } 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci if (e->action) 16108c2ecf20Sopenharmony_ci render_opcode(out, "_action(ACT_%s),\n", e->action->name); 16118c2ecf20Sopenharmony_ci} 1612