14520c6a49af833c83de6c74525ce8e07bbe6d783David Howells/* Simplified ASN.1 notation parser
24520c6a49af833c83de6c74525ce8e07bbe6d783David Howells *
34520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
44520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * Written by David Howells (dhowells@redhat.com)
54520c6a49af833c83de6c74525ce8e07bbe6d783David Howells *
64520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * This program is free software; you can redistribute it and/or
74520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * modify it under the terms of the GNU General Public Licence
84520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * as published by the Free Software Foundation; either version
94520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * 2 of the Licence, or (at your option) any later version.
104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells */
114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#include <stdarg.h>
134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#include <stdio.h>
144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#include <stdlib.h>
154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#include <stdint.h>
164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#include <string.h>
174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#include <ctype.h>
184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#include <unistd.h>
194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#include <fcntl.h>
204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#include <sys/stat.h>
214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#include <linux/asn1_ber_bytecode.h>
224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
234520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsenum token_type {
244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_ABSENT,
254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_ALL,
264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_ANY,
274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_APPLICATION,
284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_AUTOMATIC,
294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_BEGIN,
304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_BIT,
314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_BMPString,
324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_BOOLEAN,
334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_BY,
344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_CHARACTER,
354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_CHOICE,
364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_CLASS,
374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_COMPONENT,
384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_COMPONENTS,
394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_CONSTRAINED,
404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_CONTAINING,
414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_DEFAULT,
424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_DEFINED,
434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_DEFINITIONS,
444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_EMBEDDED,
454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_ENCODED,
464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_ENCODING_CONTROL,
474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_END,
484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_ENUMERATED,
494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_EXCEPT,
504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_EXPLICIT,
514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_EXPORTS,
524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_EXTENSIBILITY,
534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_EXTERNAL,
544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_FALSE,
554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_FROM,
564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_GeneralString,
574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_GeneralizedTime,
584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_GraphicString,
594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_IA5String,
604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_IDENTIFIER,
614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_IMPLICIT,
624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_IMPLIED,
634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_IMPORTS,
644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_INCLUDES,
654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_INSTANCE,
664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_INSTRUCTIONS,
674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_INTEGER,
684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_INTERSECTION,
694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_ISO646String,
704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_MAX,
714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_MIN,
724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_MINUS_INFINITY,
734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_NULL,
744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_NumericString,
754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_OBJECT,
764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_OCTET,
774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_OF,
784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_OPTIONAL,
794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_ObjectDescriptor,
804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_PATTERN,
814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_PDV,
824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_PLUS_INFINITY,
834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_PRESENT,
844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_PRIVATE,
854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_PrintableString,
864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_REAL,
874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_RELATIVE_OID,
884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_SEQUENCE,
894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_SET,
904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_SIZE,
914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_STRING,
924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_SYNTAX,
934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_T61String,
944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_TAGS,
954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_TRUE,
964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_TeletexString,
974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_UNION,
984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_UNIQUE,
994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_UNIVERSAL,
1004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_UTCTime,
1014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_UTF8String,
1024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_UniversalString,
1034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_VideotexString,
1044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_VisibleString,
1054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	DIRECTIVE_WITH,
1064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	NR__DIRECTIVES,
1074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TOKEN_ASSIGNMENT = NR__DIRECTIVES,
1084520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TOKEN_OPEN_CURLY,
1094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TOKEN_CLOSE_CURLY,
1104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TOKEN_OPEN_SQUARE,
1114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TOKEN_CLOSE_SQUARE,
1124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TOKEN_OPEN_ACTION,
1134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TOKEN_CLOSE_ACTION,
1144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TOKEN_COMMA,
1154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TOKEN_NUMBER,
1164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TOKEN_TYPE_NAME,
1174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TOKEN_ELEMENT_NAME,
1184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	NR__TOKENS
1194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells};
1204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
1214520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic const unsigned char token_to_tag[NR__TOKENS] = {
1224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* EOC goes first */
1234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_BOOLEAN]		= ASN1_BOOL,
1244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_INTEGER]		= ASN1_INT,
1254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_BIT]			= ASN1_BTS,
1264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_OCTET]		= ASN1_OTS,
1274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_NULL]		= ASN1_NULL,
1284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_OBJECT]		= ASN1_OID,
1294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_ObjectDescriptor]	= ASN1_ODE,
1304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_EXTERNAL]		= ASN1_EXT,
1314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_REAL]		= ASN1_REAL,
1324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_ENUMERATED]		= ASN1_ENUM,
1334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_EMBEDDED]		= 0,
1344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_UTF8String]		= ASN1_UTF8STR,
1354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_RELATIVE_OID]	= ASN1_RELOID,
1364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* 14 */
1374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* 15 */
1384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_SEQUENCE]		= ASN1_SEQ,
1394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_SET]			= ASN1_SET,
1404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_NumericString]	= ASN1_NUMSTR,
1414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_PrintableString]	= ASN1_PRNSTR,
1424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_T61String]		= ASN1_TEXSTR,
1434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_TeletexString]	= ASN1_TEXSTR,
1444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_VideotexString]	= ASN1_VIDSTR,
1454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_IA5String]		= ASN1_IA5STR,
1464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_UTCTime]		= ASN1_UNITIM,
1474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_GeneralizedTime]	= ASN1_GENTIM,
1484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_GraphicString]	= ASN1_GRASTR,
1494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_VisibleString]	= ASN1_VISSTR,
1504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_GeneralString]	= ASN1_GENSTR,
1514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_UniversalString]	= ASN1_UNITIM,
1524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_CHARACTER]		= ASN1_CHRSTR,
1534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_BMPString]		= ASN1_BMPSTR,
1544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells};
1554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
1564520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic const char asn1_classes[4][5] = {
1574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[ASN1_UNIV]	= "UNIV",
1584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[ASN1_APPL]	= "APPL",
1594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[ASN1_CONT]	= "CONT",
1604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[ASN1_PRIV]	= "PRIV"
1614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells};
1624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
1634520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic const char asn1_methods[2][5] = {
1644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[ASN1_UNIV]	= "PRIM",
1654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[ASN1_APPL]	= "CONS"
1664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells};
1674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
1684520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic const char *const asn1_universal_tags[32] = {
1694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"EOC",
1704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"BOOL",
1714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"INT",
1724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"BTS",
1734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"OTS",
1744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"NULL",
1754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"OID",
1764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"ODE",
1774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"EXT",
1784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"REAL",
1794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"ENUM",
1804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"EPDV",
1814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"UTF8STR",
1824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"RELOID",
1834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	NULL,		/* 14 */
1844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	NULL,		/* 15 */
1854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"SEQ",
1864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"SET",
1874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"NUMSTR",
1884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"PRNSTR",
1894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"TEXSTR",
1904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"VIDSTR",
1914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"IA5STR",
1924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"UNITIM",
1934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"GENTIM",
1944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"GRASTR",
1954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"VISSTR",
1964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"GENSTR",
1974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"UNISTR",
1984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"CHRSTR",
1994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	"BMPSTR",
2004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	NULL		/* 31 */
2014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells};
2024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
2034520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic const char *filename;
2044520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic const char *grammar_name;
2054520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic const char *outputname;
2064520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic const char *headername;
2074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
2084520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic const char *const directives[NR__DIRECTIVES] = {
2094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#define _(X) [DIRECTIVE_##X] = #X
2104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(ABSENT),
2114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(ALL),
2124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(ANY),
2134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(APPLICATION),
2144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(AUTOMATIC),
2154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(BEGIN),
2164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(BIT),
2174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(BMPString),
2184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(BOOLEAN),
2194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(BY),
2204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(CHARACTER),
2214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(CHOICE),
2224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(CLASS),
2234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(COMPONENT),
2244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(COMPONENTS),
2254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(CONSTRAINED),
2264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(CONTAINING),
2274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(DEFAULT),
2284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(DEFINED),
2294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(DEFINITIONS),
2304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(EMBEDDED),
2314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(ENCODED),
2324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL",
2334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(END),
2344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(ENUMERATED),
2354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(EXCEPT),
2364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(EXPLICIT),
2374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(EXPORTS),
2384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(EXTENSIBILITY),
2394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(EXTERNAL),
2404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(FALSE),
2414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(FROM),
2424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(GeneralString),
2434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(GeneralizedTime),
2444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(GraphicString),
2454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(IA5String),
2464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(IDENTIFIER),
2474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(IMPLICIT),
2484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(IMPLIED),
2494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(IMPORTS),
2504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(INCLUDES),
2514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(INSTANCE),
2524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(INSTRUCTIONS),
2534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(INTEGER),
2544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(INTERSECTION),
2554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(ISO646String),
2564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(MAX),
2574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(MIN),
2584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY",
2594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_NULL] = "NULL",
2604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(NumericString),
2614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(OBJECT),
2624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(OCTET),
2634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(OF),
2644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(OPTIONAL),
2654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(ObjectDescriptor),
2664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(PATTERN),
2674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(PDV),
2684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY",
2694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(PRESENT),
2704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(PRIVATE),
2714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(PrintableString),
2724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(REAL),
2734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	[DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID",
2744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(SEQUENCE),
2754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(SET),
2764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(SIZE),
2774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(STRING),
2784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(SYNTAX),
2794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(T61String),
2804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(TAGS),
2814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(TRUE),
2824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(TeletexString),
2834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(UNION),
2844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(UNIQUE),
2854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(UNIVERSAL),
2864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(UTCTime),
2874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(UTF8String),
2884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(UniversalString),
2894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(VideotexString),
2904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(VisibleString),
2914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	_(WITH)
2924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells};
2934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
2944520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstruct action {
2954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct action	*next;
2964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	unsigned char	index;
2974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	char		name[];
2984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells};
2994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3004520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic struct action *action_list;
3014520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic unsigned nr_actions;
3024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3034520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstruct token {
3044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	unsigned short	line;
3054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	enum token_type	token_type : 8;
3064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	unsigned char	size;
3074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct action	*action;
3084520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	const char	*value;
3094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct type	*type;
3104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells};
3114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3124520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic struct token *token_list;
3134520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic unsigned nr_tokens;
3144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3154520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic int directive_compare(const void *_key, const void *_pdir)
3164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
3174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	const struct token *token = _key;
3184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	const char *const *pdir = _pdir, *dir = *pdir;
3194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	size_t dlen, clen;
3204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	int val;
3214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	dlen = strlen(dir);
3234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	clen = (dlen < token->size) ? dlen : token->size;
3244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	//printf("cmp(%*.*s,%s) = ",
3264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	//       (int)token->size, (int)token->size, token->value,
3274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	//       dir);
3284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	val = memcmp(token->value, dir, clen);
3304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (val != 0) {
3314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		//printf("%d [cmp]\n", val);
3324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		return val;
3334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
3344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (dlen == token->size) {
3364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		//printf("0\n");
3374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		return 0;
3384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
3394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	//printf("%d\n", (int)dlen - (int)token->size);
3404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	return dlen - token->size; /* shorter -> negative */
3414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
3424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells/*
3444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * Tokenise an ASN.1 grammar
3454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells */
3464520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void tokenise(char *buffer, char *end)
3474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
3484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct token *tokens;
3494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	char *line, *nl, *p, *q;
3504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	unsigned tix, lineno;
3514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* Assume we're going to have half as many tokens as we have
3534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	 * characters
3544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	 */
3554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token));
3564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (!tokens) {
3574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(NULL);
3584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
3594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
3604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	tix = 0;
3614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	lineno = 0;
3634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	while (buffer < end) {
3644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		/* First of all, break out a line */
3654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		lineno++;
3664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		line = buffer;
3674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		nl = memchr(line, '\n', end - buffer);
3684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (!nl) {
3694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			buffer = nl = end;
3704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		} else {
3714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			buffer = nl + 1;
3724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			*nl = '\0';
3734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
3744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		/* Remove "--" comments */
3764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		p = line;
3774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	next_comment:
3784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		while ((p = memchr(p, '-', nl - p))) {
3794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (p[1] == '-') {
3804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				/* Found a comment; see if there's a terminator */
3814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				q = p + 2;
3824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				while ((q = memchr(q, '-', nl - q))) {
3834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					if (q[1] == '-') {
3844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells						/* There is - excise the comment */
3854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells						q += 2;
3864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells						memmove(p, q, nl - q);
3874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells						goto next_comment;
3884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					}
3894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					q++;
3904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				}
3914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				*p = '\0';
3924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				nl = p;
3934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				break;
3944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			} else {
3954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				p++;
3964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			}
3974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
3984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
3994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		p = line;
4004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		while (p < nl) {
4014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			/* Skip white space */
4024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			while (p < nl && isspace(*p))
4034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				*(p++) = 0;
4044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (p >= nl)
4054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				break;
4064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
4074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			tokens[tix].line = lineno;
4084520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			tokens[tix].value = p;
4094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
4104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			/* Handle string tokens */
4114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (isalpha(*p)) {
4124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				const char **dir;
4134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
4144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				/* Can be a directive, type name or element
4154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				 * name.  Find the end of the name.
4164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				 */
4174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				q = p + 1;
4184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				while (q < nl && (isalnum(*q) || *q == '-' || *q == '_'))
4194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					q++;
4204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				tokens[tix].size = q - p;
4214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				p = q;
4224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
4234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				/* If it begins with a lowercase letter then
4244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				 * it's an element name
4254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				 */
4264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				if (islower(tokens[tix].value[0])) {
4274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix++].token_type = TOKEN_ELEMENT_NAME;
4284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					continue;
4294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				}
4304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
4314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				/* Otherwise we need to search the directive
4324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				 * table
4334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				 */
4344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				dir = bsearch(&tokens[tix], directives,
4354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					      sizeof(directives) / sizeof(directives[1]),
4364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					      sizeof(directives[1]),
4374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					      directive_compare);
4384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				if (dir) {
4394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix++].token_type = dir - directives;
4404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					continue;
4414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				}
4424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
4434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				tokens[tix++].token_type = TOKEN_TYPE_NAME;
4444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				continue;
4454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			}
4464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
4474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			/* Handle numbers */
4484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (isdigit(*p)) {
4494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				/* Find the end of the number */
4504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				q = p + 1;
4514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				while (q < nl && (isdigit(*q)))
4524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					q++;
4534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				tokens[tix].size = q - p;
4544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				p = q;
4554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				tokens[tix++].token_type = TOKEN_NUMBER;
4564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				continue;
4574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			}
4584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
4594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (nl - p >= 3) {
4604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				if (memcmp(p, "::=", 3) == 0) {
4614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					p += 3;
4624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix].size = 3;
4634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix++].token_type = TOKEN_ASSIGNMENT;
4644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					continue;
4654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				}
4664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			}
4674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
4684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (nl - p >= 2) {
4694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				if (memcmp(p, "({", 2) == 0) {
4704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					p += 2;
4714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix].size = 2;
4724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix++].token_type = TOKEN_OPEN_ACTION;
4734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					continue;
4744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				}
4754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				if (memcmp(p, "})", 2) == 0) {
4764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					p += 2;
4774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix].size = 2;
4784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix++].token_type = TOKEN_CLOSE_ACTION;
4794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					continue;
4804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				}
4814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			}
4824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
4834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (nl - p >= 1) {
4844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				tokens[tix].size = 1;
4854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				switch (*p) {
4864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				case '{':
4874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					p += 1;
4884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix++].token_type = TOKEN_OPEN_CURLY;
4894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					continue;
4904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				case '}':
4914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					p += 1;
4924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix++].token_type = TOKEN_CLOSE_CURLY;
4934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					continue;
4944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				case '[':
4954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					p += 1;
4964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix++].token_type = TOKEN_OPEN_SQUARE;
4974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					continue;
4984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				case ']':
4994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					p += 1;
5004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix++].token_type = TOKEN_CLOSE_SQUARE;
5014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					continue;
5024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				case ',':
5034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					p += 1;
5044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					tokens[tix++].token_type = TOKEN_COMMA;
5054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					continue;
5064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				default:
5074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					break;
5084520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				}
5094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			}
5104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n",
5124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				filename, lineno, *p);
5134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			exit(1);
5144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
5154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
5164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	nr_tokens = tix;
5184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	printf("Extracted %u tokens\n", nr_tokens);
5194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#if 0
5214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	{
5224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		int n;
5234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		for (n = 0; n < nr_tokens; n++)
5244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			printf("Token %3u: '%*.*s'\n",
5254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			       n,
5264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			       (int)token_list[n].size, (int)token_list[n].size,
5274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			       token_list[n].value);
5284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
5294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#endif
5304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
5314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5324520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void build_type_list(void);
5334520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void parse(void);
5344520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void render(FILE *out, FILE *hdr);
5354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells/*
5374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells *
5384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells */
5394520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsint main(int argc, char **argv)
5404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
5414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct stat st;
5424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	ssize_t readlen;
5434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	FILE *out, *hdr;
5444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	char *buffer, *p;
5454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	int fd;
5464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (argc != 4) {
5484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n",
5494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			argv[0]);
5504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(2);
5514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
5524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	filename = argv[1];
5544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	outputname = argv[2];
5554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	headername = argv[3];
5564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fd = open(filename, O_RDONLY);
5584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (fd < 0) {
5594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(filename);
5604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
5614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
5624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (fstat(fd, &st) < 0) {
5644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(filename);
5654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
5664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
5674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (!(buffer = malloc(st.st_size + 1))) {
5694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(NULL);
5704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
5714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
5724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if ((readlen = read(fd, buffer, st.st_size)) < 0) {
5744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(filename);
5754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
5764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
5774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (close(fd) < 0) {
5794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(filename);
5804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
5814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
5824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (readlen != st.st_size) {
5844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		fprintf(stderr, "%s: Short read\n", filename);
5854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
5864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
5874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	p = strrchr(argv[1], '/');
5894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	p = p ? p + 1 : argv[1];
5904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	grammar_name = strdup(p);
5914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (!p) {
5924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(NULL);
5934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
5944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
5954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	p = strchr(grammar_name, '.');
5964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (p)
5974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		*p = '\0';
5984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
5994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	buffer[readlen] = 0;
6004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	tokenise(buffer, buffer + readlen);
6014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	build_type_list();
6024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	parse();
6034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	out = fopen(outputname, "w");
6054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (!out) {
6064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(outputname);
6074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
6084520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
6094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	hdr = fopen(headername, "w");
6114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (!out) {
6124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(headername);
6134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
6144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
6154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	render(out, hdr);
6174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (fclose(out) < 0) {
6194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(outputname);
6204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
6214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
6224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (fclose(hdr) < 0) {
6244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(headername);
6254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
6264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
6274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	return 0;
6294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
6304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6314520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsenum compound {
6324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	NOT_COMPOUND,
6334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	SET,
6344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	SET_OF,
6354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	SEQUENCE,
6364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	SEQUENCE_OF,
6374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	CHOICE,
6384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	ANY,
6394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TYPE_REF,
6404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	TAG_OVERRIDE
6414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells};
6424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6434520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstruct element {
6444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct type	*type_def;
6454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct token	*name;
6464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct token	*type;
6474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct action	*action;
6484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct element	*children;
6494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct element	*next;
6504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct element	*render_next;
6514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct element	*list_next;
6524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	uint8_t		n_elements;
6534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	enum compound	compound : 8;
6544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	enum asn1_class	class : 8;
6554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	enum asn1_method method : 8;
6564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	uint8_t		tag;
6574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	unsigned	entry_index;
6584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	unsigned	flags;
6594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#define ELEMENT_IMPLICIT	0x0001
6604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#define ELEMENT_EXPLICIT	0x0002
6614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#define ELEMENT_MARKED		0x0004
6624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#define ELEMENT_RENDERED	0x0008
6634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#define ELEMENT_SKIPPABLE	0x0010
6644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#define ELEMENT_CONDITIONAL	0x0020
6654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells};
6664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6674520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstruct type {
6684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct token	*name;
6694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct token	*def;
6704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct element	*element;
6714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	unsigned	ref_count;
6724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	unsigned	flags;
6734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#define TYPE_STOP_MARKER	0x0001
6744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#define TYPE_BEGIN		0x0002
6754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells};
6764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6774520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic struct type *type_list;
6784520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic struct type **type_index;
6794520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic unsigned nr_types;
6804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6814520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic int type_index_compare(const void *_a, const void *_b)
6824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
6834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	const struct type *const *a = _a, *const *b = _b;
6844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if ((*a)->name->size != (*b)->name->size)
6864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		return (*a)->name->size - (*b)->name->size;
6874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	else
6884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		return memcmp((*a)->name->value, (*b)->name->value,
6894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      (*a)->name->size);
6904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
6914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6924520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic int type_finder(const void *_key, const void *_ti)
6934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
6944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	const struct token *token = _key;
6954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	const struct type *const *ti = _ti;
6964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	const struct type *type = *ti;
6974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
6984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (token->size != type->name->size)
6994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		return token->size - type->name->size;
7004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	else
7014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		return memcmp(token->value, type->name->value,
7024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      token->size);
7034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
7044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells/*
7064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * Build up a list of types and a sorted index to that list.
7074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells */
7084520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void build_type_list(void)
7094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
7104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct type *types;
7114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	unsigned nr, t, n;
7124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	nr = 0;
7144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	for (n = 0; n < nr_tokens - 1; n++)
7154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
7164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		    token_list[n + 1].token_type == TOKEN_ASSIGNMENT)
7174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			nr++;
7184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (nr == 0) {
7204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		fprintf(stderr, "%s: No defined types\n", filename);
7214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
7224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
7234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	nr_types = nr;
7254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	types = type_list = calloc(nr + 1, sizeof(type_list[0]));
7264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (!type_list) {
7274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(NULL);
7284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
7294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
7304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	type_index = calloc(nr, sizeof(type_index[0]));
7314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (!type_index) {
7324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(NULL);
7334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
7344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
7354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	t = 0;
7374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	types[t].flags |= TYPE_BEGIN;
7384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	for (n = 0; n < nr_tokens - 1; n++) {
7394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
7404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		    token_list[n + 1].token_type == TOKEN_ASSIGNMENT) {
7414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			types[t].name = &token_list[n];
7424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			type_index[t] = &types[t];
7434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			t++;
7444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
7454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
7464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	types[t].name = &token_list[n + 1];
7474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	types[t].flags |= TYPE_STOP_MARKER;
7484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	qsort(type_index, nr, sizeof(type_index[0]), type_index_compare);
7504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	printf("Extracted %u types\n", nr_types);
7524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#if 0
7534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	for (n = 0; n < nr_types; n++) {
7544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		struct type *type = type_index[n];
7554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		printf("- %*.*s\n",
7564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		       (int)type->name->size,
7574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		       (int)type->name->size,
7584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		       type->name->value);
7594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
7604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells#endif
7614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
7624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7634520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic struct element *parse_type(struct token **_cursor, struct token *stop,
7644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				  struct token *name);
7654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells/*
7674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * Parse the token stream
7684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells */
7694520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void parse(void)
7704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
7714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct token *cursor;
7724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct type *type;
7734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* Parse one type definition statement at a time */
7754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	type = type_list;
7764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	do {
7774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor = type->name;
7784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor[0].token_type != TOKEN_TYPE_NAME ||
7804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		    cursor[1].token_type != TOKEN_ASSIGNMENT)
7814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			abort();
7824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor += 2;
7834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		type->element = parse_type(&cursor, type[1].name, NULL);
7854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		type->element->type_def = type;
7864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor != type[1].name) {
7884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n",
7894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				filename, cursor->line,
7904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				(int)cursor->size, (int)cursor->size, cursor->value);
7914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			exit(1);
7924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
7934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	} while (type++, !(type->flags & TYPE_STOP_MARKER));
7954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	printf("Extracted %u actions\n", nr_actions);
7974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
7984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
7994520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic struct element *element_list;
8004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
8014520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic struct element *alloc_elem(struct token *type)
8024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
8034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct element *e = calloc(1, sizeof(*e));
8044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (!e) {
8054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(NULL);
8064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
8074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
8084520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	e->list_next = element_list;
8094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	element_list = e;
8104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	return e;
8114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
8124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
8134520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic struct element *parse_compound(struct token **_cursor, struct token *end,
8144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				      int alternates);
8154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
8164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells/*
8174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * Parse one type definition statement
8184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells */
8194520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic struct element *parse_type(struct token **_cursor, struct token *end,
8204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				  struct token *name)
8214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
8224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct element *top, *element;
8234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct action *action, **ppaction;
8244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct token *cursor = *_cursor;
8254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct type **ref;
8264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	char *p;
8274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	int labelled = 0, implicit = 0;
8284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
8294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	top = element = alloc_elem(cursor);
8304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	element->class = ASN1_UNIV;
8314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	element->method = ASN1_PRIM;
8324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	element->tag = token_to_tag[cursor->token_type];
8334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	element->name = name;
8344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
8354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* Extract the tag value if one given */
8364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (cursor->token_type == TOKEN_OPEN_SQUARE) {
8374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
8384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
8394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
8404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		switch (cursor->token_type) {
8414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		case DIRECTIVE_UNIVERSAL:
8424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			element->class = ASN1_UNIV;
8434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			cursor++;
8444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			break;
8454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		case DIRECTIVE_APPLICATION:
8464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			element->class = ASN1_APPL;
8474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			cursor++;
8484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			break;
8494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		case TOKEN_NUMBER:
8504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			element->class = ASN1_CONT;
8514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			break;
8524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		case DIRECTIVE_PRIVATE:
8534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			element->class = ASN1_PRIV;
8544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			cursor++;
8554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			break;
8564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		default:
8574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n",
8584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				filename, cursor->line,
8594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				(int)cursor->size, (int)cursor->size, cursor->value);
8604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			exit(1);
8614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
8624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
8634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
8644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
8654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor->token_type != TOKEN_NUMBER) {
8664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n",
8674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				filename, cursor->line,
8684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				(int)cursor->size, (int)cursor->size, cursor->value);
8694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			exit(1);
8704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
8714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
8724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->tag &= ~0x1f;
8734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->tag |= strtoul(cursor->value, &p, 10);
8744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (p - cursor->value != cursor->size)
8754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			abort();
8764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
8774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
8784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
8794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
8804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor->token_type != TOKEN_CLOSE_SQUARE) {
8814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n",
8824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				filename, cursor->line,
8834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				(int)cursor->size, (int)cursor->size, cursor->value);
8844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			exit(1);
8854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
8864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
8874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
8884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
8894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		labelled = 1;
8904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
8914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
8924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* Handle implicit and explicit markers */
8934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (cursor->token_type == DIRECTIVE_IMPLICIT) {
8944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->flags |= ELEMENT_IMPLICIT;
8954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		implicit = 1;
8964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
8974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
8984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
8994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	} else if (cursor->token_type == DIRECTIVE_EXPLICIT) {
9004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->flags |= ELEMENT_EXPLICIT;
9014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
9024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
9034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
9044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
9054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
9064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (labelled) {
9074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (!implicit)
9084520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			element->method |= ASN1_CONS;
9094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->compound = implicit ? TAG_OVERRIDE : SEQUENCE;
9104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->children = alloc_elem(cursor);
9114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element = element->children;
9124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->class = ASN1_UNIV;
9134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->method = ASN1_PRIM;
9144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->tag = token_to_tag[cursor->token_type];
9154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->name = name;
9164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
9174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
9184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* Extract the type we're expecting here */
9194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	element->type = cursor;
9204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	switch (cursor->token_type) {
9214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_ANY:
9224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->compound = ANY;
9234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
9244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
9254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
9264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_NULL:
9274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_BOOLEAN:
9284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_ENUMERATED:
9294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_INTEGER:
9304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->compound = NOT_COMPOUND;
9314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
9324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
9334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
9344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_EXTERNAL:
9354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->method = ASN1_CONS;
9364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
9374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_BMPString:
9384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_GeneralString:
9394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_GraphicString:
9404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_IA5String:
9414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_ISO646String:
9424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_NumericString:
9434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_PrintableString:
9444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_T61String:
9454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_TeletexString:
9464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_UniversalString:
9474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_UTF8String:
9484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_VideotexString:
9494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_VisibleString:
9504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_ObjectDescriptor:
9514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_GeneralizedTime:
9524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_UTCTime:
9534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->compound = NOT_COMPOUND;
9544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
9554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
9564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
9574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_BIT:
9584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_OCTET:
9594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->compound = NOT_COMPOUND;
9604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
9614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
9624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
9634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor->token_type != DIRECTIVE_STRING)
9644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto parse_error;
9654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
9664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
9674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
9684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_OBJECT:
9694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->compound = NOT_COMPOUND;
9704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
9714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
9724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
9734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor->token_type != DIRECTIVE_IDENTIFIER)
9744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto parse_error;
9754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
9764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
9774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
9784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case TOKEN_TYPE_NAME:
9794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->compound = TYPE_REF;
9804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]),
9814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      type_finder);
9824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (!ref) {
9834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n",
9844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				filename, cursor->line,
9854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				(int)cursor->size, (int)cursor->size, cursor->value);
9864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			exit(1);
9874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
9884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor->type = *ref;
9894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		(*ref)->ref_count++;
9904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
9914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
9924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
9934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_CHOICE:
9944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->compound = CHOICE;
9954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
9964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->children = parse_compound(&cursor, end, 1);
9974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
9984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
9994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_SEQUENCE:
10004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->compound = SEQUENCE;
10014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->method = ASN1_CONS;
10024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
10034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
10044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
10054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor->token_type == DIRECTIVE_OF) {
10064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			element->compound = SEQUENCE_OF;
10074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			cursor++;
10084520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (cursor >= end)
10094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				goto overrun_error;
10104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			element->children = parse_type(&cursor, end, NULL);
10114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		} else {
10124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			element->children = parse_compound(&cursor, end, 0);
10134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
10144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
10154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
10164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case DIRECTIVE_SET:
10174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->compound = SET;
10184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->method = ASN1_CONS;
10194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
10204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
10214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
10224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor->token_type == DIRECTIVE_OF) {
10234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			element->compound = SET_OF;
10244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			cursor++;
10254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (cursor >= end)
10264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				goto parse_error;
10274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			element->children = parse_type(&cursor, end, NULL);
10284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		} else {
10294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			element->children = parse_compound(&cursor, end, 1);
10304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
10314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
10324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
10334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	default:
10344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n",
10354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			filename, cursor->line,
10364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			(int)cursor->size, (int)cursor->size, cursor->value);
10374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
10384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
10394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
10404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* Handle elements that are optional */
10414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL ||
10424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			     cursor->token_type == DIRECTIVE_DEFAULT)
10434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	    ) {
10444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
10454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		top->flags |= ELEMENT_SKIPPABLE;
10464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
10474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
10484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) {
10494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
10504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
10514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
10524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor->token_type != TOKEN_ELEMENT_NAME) {
10534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n",
10544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				filename, cursor->line,
10554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				(int)cursor->size, (int)cursor->size, cursor->value);
10564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			exit(1);
10574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
10584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
10594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		action = malloc(sizeof(struct action) + cursor->size + 1);
10604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (!action) {
10614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			perror(NULL);
10624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			exit(1);
10634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
10644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		action->index = 0;
10654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		memcpy(action->name, cursor->value, cursor->size);
10664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		action->name[cursor->size] = 0;
10674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
10684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		for (ppaction = &action_list;
10694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		     *ppaction;
10704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		     ppaction = &(*ppaction)->next
10714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		     ) {
10724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			int cmp = strcmp(action->name, (*ppaction)->name);
10734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (cmp == 0) {
10744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				free(action);
10754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				action = *ppaction;
10764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				goto found;
10774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			}
10784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (cmp < 0) {
10794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				action->next = *ppaction;
10804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				*ppaction = action;
10814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				nr_actions++;
10824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				goto found;
10834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			}
10844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
10854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		action->next = NULL;
10864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		*ppaction = action;
10874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		nr_actions++;
10884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	found:
10894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
10904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element->action = action;
10914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor->action = action;
10924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
10934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
10944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
10954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor->token_type != TOKEN_CLOSE_ACTION) {
10964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n",
10974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				filename, cursor->line,
10984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				(int)cursor->size, (int)cursor->size, cursor->value);
10994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			exit(1);
11004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
11014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
11024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
11034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	*_cursor = cursor;
11054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	return top;
11064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11074520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsparse_error:
11084520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n",
11094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		filename, cursor->line,
11104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		(int)cursor->size, (int)cursor->size, cursor->value);
11114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	exit(1);
11124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11134520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsoverrun_error:
11144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
11154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	exit(1);
11164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
11174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells/*
11194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * Parse a compound type list
11204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells */
11214520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic struct element *parse_compound(struct token **_cursor, struct token *end,
11224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				      int alternates)
11234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
11244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct element *children, **child_p = &children, *element;
11254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct token *cursor = *_cursor, *name;
11264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (cursor->token_type != TOKEN_OPEN_CURLY) {
11284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n",
11294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			filename, cursor->line,
11304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			(int)cursor->size, (int)cursor->size, cursor->value);
11314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
11324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
11334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	cursor++;
11344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (cursor >= end)
11354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		goto overrun_error;
11364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (cursor->token_type == TOKEN_OPEN_CURLY) {
11384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		fprintf(stderr, "%s:%d: Empty compound\n",
11394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			filename, cursor->line);
11404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
11414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
11424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	for (;;) {
11444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		name = NULL;
11454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor->token_type == TOKEN_ELEMENT_NAME) {
11464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			name = cursor;
11474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			cursor++;
11484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (cursor >= end)
11494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				goto overrun_error;
11504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
11514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		element = parse_type(&cursor, end, name);
11534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (alternates)
11544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL;
11554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		*child_p = element;
11574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		child_p = &element->next;
11584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
11604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
11614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor->token_type != TOKEN_COMMA)
11624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			break;
11634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		cursor++;
11644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (cursor >= end)
11654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto overrun_error;
11664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
11674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	children->flags &= ~ELEMENT_CONDITIONAL;
11694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (cursor->token_type != TOKEN_CLOSE_CURLY) {
11714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n",
11724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			filename, cursor->line,
11734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			(int)cursor->size, (int)cursor->size, cursor->value);
11744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
11754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
11764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	cursor++;
11774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	*_cursor = cursor;
11794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	return children;
11804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11814520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsoverrun_error:
11824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
11834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	exit(1);
11844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
11854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11864520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void render_element(FILE *out, struct element *e, struct element *tag);
11874520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void render_out_of_line_list(FILE *out);
11884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11894520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic int nr_entries;
11904520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic int render_depth = 1;
11914520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic struct element *render_list, **render_list_p = &render_list;
11924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells__attribute__((format(printf, 2, 3)))
11944520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void render_opcode(FILE *out, const char *fmt, ...)
11954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
11964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	va_list va;
11974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
11984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (out) {
11994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, "");
12004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		va_start(va, fmt);
12014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		vfprintf(out, fmt, va);
12024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		va_end(va);
12034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
12044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	nr_entries++;
12054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
12064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
12074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells__attribute__((format(printf, 2, 3)))
12084520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void render_more(FILE *out, const char *fmt, ...)
12094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
12104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	va_list va;
12114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
12124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (out) {
12134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		va_start(va, fmt);
12144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		vfprintf(out, fmt, va);
12154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		va_end(va);
12164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
12174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
12184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
12194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells/*
12204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * Render the grammar into a state machine definition.
12214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells */
12224520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void render(FILE *out, FILE *hdr)
12234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
12244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct element *e;
12254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct action *action;
12264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct type *root;
12274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	int index;
12284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
12294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(hdr, "/*\n");
12304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(hdr, " * Automatically generated by asn1_compiler.  Do not edit\n");
12314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(hdr, " *\n");
12324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name);
12334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(hdr, " */\n");
12344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(hdr, "#include <linux/asn1_decoder.h>\n");
12354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(hdr, "\n");
12364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name);
12374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (ferror(hdr)) {
12384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(headername);
12394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
12404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
12414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
12424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "/*\n");
12434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, " * Automatically generated by asn1_compiler.  Do not edit\n");
12444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, " *\n");
12454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, " * ASN.1 parser for %s\n", grammar_name);
12464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, " */\n");
12474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "#include <linux/asn1_ber_bytecode.h>\n");
12484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name);
12494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "\n");
12504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (ferror(out)) {
12514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(outputname);
12524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
12534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
12544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
12554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* Tabulate the action functions we might have to call */
12564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(hdr, "\n");
12574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	index = 0;
12584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	for (action = action_list; action; action = action->next) {
12594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		action->index = index++;
12604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		fprintf(hdr,
12614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			"extern int %s(void *, size_t, unsigned char,"
12624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			" const void *, size_t);\n",
12634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			action->name);
12644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
12654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(hdr, "\n");
12664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
12674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "enum %s_actions {\n", grammar_name);
12684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	for (action = action_list; action; action = action->next)
12694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		fprintf(out, "\tACT_%s = %u,\n",
12704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			action->name, action->index);
12714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions);
12724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "};\n");
12734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
12744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "\n");
12754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n",
12764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		grammar_name, grammar_name);
12774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	for (action = action_list; action; action = action->next)
12784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		fprintf(out, "\t[%4u] = %s,\n", action->index, action->name);
12794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "};\n");
12804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
12814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (ferror(out)) {
12824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		perror(outputname);
12834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
12844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
12854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
12864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* We do two passes - the first one calculates all the offsets */
12874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	printf("Pass 1\n");
12884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	nr_entries = 0;
12894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	root = &type_list[0];
12904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	render_element(NULL, root->element, NULL);
12914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	render_opcode(NULL, "ASN1_OP_COMPLETE,\n");
12924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	render_out_of_line_list(NULL);
12934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
12944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	for (e = element_list; e; e = e->list_next)
12954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		e->flags &= ~ELEMENT_RENDERED;
12964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
12974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* And then we actually render */
12984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	printf("Pass 2\n");
12994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "\n");
13004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "static const unsigned char %s_machine[] = {\n",
13014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		grammar_name);
13024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
13034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	nr_entries = 0;
13044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	root = &type_list[0];
13054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	render_element(out, root->element, NULL);
13064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	render_opcode(out, "ASN1_OP_COMPLETE,\n");
13074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	render_out_of_line_list(out);
13084520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
13094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "};\n");
13104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
13114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "\n");
13124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name);
13134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "\t.machine = %s_machine,\n", grammar_name);
13144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name);
13154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "\t.actions = %s_action_table,\n", grammar_name);
13164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	fprintf(out, "};\n");
13174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
13184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
13194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells/*
13204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * Render the out-of-line elements
13214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells */
13224520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void render_out_of_line_list(FILE *out)
13234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
13244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct element *e, *ce;
13254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	const char *act;
13264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	int entry;
13274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
13284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	while ((e = render_list)) {
13294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_list = e->render_next;
13304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (!render_list)
13314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_list_p = &render_list;
13324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
13334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_more(out, "\n");
13344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		e->entry_index = entry = nr_entries;
13354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_depth++;
13364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		for (ce = e->children; ce; ce = ce->next)
13374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_element(out, ce, NULL);
13384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_depth--;
13394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
13404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		act = e->action ? "_ACT" : "";
13414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		switch (e->compound) {
13424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		case SEQUENCE:
13434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
13444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			break;
13454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		case SEQUENCE_OF:
13464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
13474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "_jump_target(%u),\n", entry);
13484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			break;
13494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		case SET:
13504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "ASN1_OP_END_SET%s,\n", act);
13514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			break;
13524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		case SET_OF:
13534520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
13544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "_jump_target(%u),\n", entry);
13554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			break;
1356eb8948a03704f3dbbfc7e83090e20e93c6c476d2Antonio Alecrim Jr		default:
1357eb8948a03704f3dbbfc7e83090e20e93c6c476d2Antonio Alecrim Jr			break;
13584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
13594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (e->action)
13604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "_action(ACT_%s),\n",
13614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				      e->action->name);
13624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_opcode(out, "ASN1_OP_RETURN,\n");
13634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
13644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
13654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
13664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells/*
13674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells * Render an element.
13684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells */
13694520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsstatic void render_element(FILE *out, struct element *e, struct element *tag)
13704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells{
13714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	struct element *ec;
13724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	const char *cond, *act;
13734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	int entry, skippable = 0, outofline = 0;
13744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
13754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (e->flags & ELEMENT_SKIPPABLE ||
13764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	    (tag && tag->flags & ELEMENT_SKIPPABLE))
13774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		skippable = 1;
13784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
13794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if ((e->type_def && e->type_def->ref_count > 1) ||
13804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	    skippable)
13814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		outofline = 1;
13824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
13834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (e->type_def && out) {
13844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_more(out, "\t// %*.*s\n",
13854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			    (int)e->type_def->name->size, (int)e->type_def->name->size,
13864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			    e->type_def->name->value);
13874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
13884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
13894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* Render the operation */
13904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	cond = (e->flags & ELEMENT_CONDITIONAL ||
13914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		(tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : "";
13924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	act = e->action ? "_ACT" : "";
13934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	switch (e->compound) {
13944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case ANY:
13954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act);
13964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (e->name)
13974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_more(out, "\t\t// %*.*s",
13984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				    (int)e->name->size, (int)e->name->size,
13994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				    e->name->value);
14004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_more(out, "\n");
14014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		goto dont_render_tag;
14024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
14034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case TAG_OVERRIDE:
14044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_element(out, e->children, e);
14054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		return;
14064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
14074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case SEQUENCE:
14084520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case SEQUENCE_OF:
14094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case SET:
14104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case SET_OF:
14114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
14124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      cond,
14134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      outofline ? "_JUMP" : "",
14144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      skippable ? "_OR_SKIP" : "");
14154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
14164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
14174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case CHOICE:
14184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		goto dont_render_tag;
14194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
14204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case TYPE_REF:
14214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0)
14224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			goto dont_render_tag;
14234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	default:
14244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
14254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      cond, act,
14264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      skippable ? "_OR_SKIP" : "");
14274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
14284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
14294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
14304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (e->name)
14314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_more(out, "\t\t// %*.*s",
14324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			    (int)e->name->size, (int)e->name->size,
14334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			    e->name->value);
14344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	render_more(out, "\n");
14354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
14364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* Render the tag */
14374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (!tag)
14384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		tag = e;
14394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (tag->class == ASN1_UNIV &&
14404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	    tag->tag != 14 &&
14414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	    tag->tag != 15 &&
14424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	    tag->tag != 31)
14434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_opcode(out, "_tag(%s, %s, %s),\n",
14444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      asn1_classes[tag->class],
14454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      asn1_methods[tag->method | e->method],
14464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      asn1_universal_tags[tag->tag]);
14474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	else
14484520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_opcode(out, "_tagn(%s, %s, %2u),\n",
14494520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      asn1_classes[tag->class],
14504520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      asn1_methods[tag->method | e->method],
14514520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			      tag->tag);
14524520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	tag = NULL;
14534520c6a49af833c83de6c74525ce8e07bbe6d783David Howellsdont_render_tag:
14544520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
14554520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	/* Deal with compound types */
14564520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	switch (e->compound) {
14574520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case TYPE_REF:
14584520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_element(out, e->type->type->element, tag);
14594520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (e->action)
14604520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "ASN1_OP_ACT,\n");
14614520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
14624520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
14634520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case SEQUENCE:
14644520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (outofline) {
14654520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			/* Render out-of-line for multiple use or
14664520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			 * skipability */
14674520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "_jump_target(%u),", e->entry_index);
14684520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (e->type_def && e->type_def->name)
14694520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				render_more(out, "\t\t// --> %*.*s",
14704520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					    (int)e->type_def->name->size,
14714520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					    (int)e->type_def->name->size,
14724520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					    e->type_def->name->value);
14734520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_more(out, "\n");
14744520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (!(e->flags & ELEMENT_RENDERED)) {
14754520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				e->flags |= ELEMENT_RENDERED;
14764520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				*render_list_p = e;
14774520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				render_list_p = &e->render_next;
14784520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			}
14794520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			return;
14804520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		} else {
14814520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			/* Render inline for single use */
14824520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_depth++;
14834520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			for (ec = e->children; ec; ec = ec->next)
14844520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				render_element(out, ec, NULL);
14854520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_depth--;
14864520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
14874520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
14884520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
14894520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
14904520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case SEQUENCE_OF:
14914520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case SET_OF:
14924520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (outofline) {
14934520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			/* Render out-of-line for multiple use or
14944520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			 * skipability */
14954520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "_jump_target(%u),", e->entry_index);
14964520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (e->type_def && e->type_def->name)
14974520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				render_more(out, "\t\t// --> %*.*s",
14984520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					    (int)e->type_def->name->size,
14994520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					    (int)e->type_def->name->size,
15004520c6a49af833c83de6c74525ce8e07bbe6d783David Howells					    e->type_def->name->value);
15014520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_more(out, "\n");
15024520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (!(e->flags & ELEMENT_RENDERED)) {
15034520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				e->flags |= ELEMENT_RENDERED;
15044520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				*render_list_p = e;
15054520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				render_list_p = &e->render_next;
15064520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			}
15074520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			return;
15084520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		} else {
15094520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			/* Render inline for single use */
15104520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			entry = nr_entries;
15114520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_depth++;
15124520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_element(out, e->children, NULL);
15134520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_depth--;
15144520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			if (e->compound == SEQUENCE_OF)
15154520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
15164520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			else
15174520c6a49af833c83de6c74525ce8e07bbe6d783David Howells				render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
15184520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "_jump_target(%u),\n", entry);
15194520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		}
15204520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
15214520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
15224520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case SET:
15234520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		/* I can't think of a nice way to do SET support without having
15244520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		 * a stack of bitmasks to make sure no element is repeated.
15254520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		 * The bitmask has also to be checked that no non-optional
15264520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		 * elements are left out whilst not preventing optional
15274520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		 * elements from being left out.
15284520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		 */
15294520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		fprintf(stderr, "The ASN.1 SET type is not currently supported.\n");
15304520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		exit(1);
15314520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
15324520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	case CHOICE:
15334520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		for (ec = e->children; ec; ec = ec->next)
15344520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_element(out, ec, NULL);
15354520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (!skippable)
15364520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "ASN1_OP_COND_FAIL,\n");
15374520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		if (e->action)
15384520c6a49af833c83de6c74525ce8e07bbe6d783David Howells			render_opcode(out, "ASN1_OP_ACT,\n");
15394520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
15404520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
15414520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	default:
15424520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		break;
15434520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	}
15444520c6a49af833c83de6c74525ce8e07bbe6d783David Howells
15454520c6a49af833c83de6c74525ce8e07bbe6d783David Howells	if (e->action)
15464520c6a49af833c83de6c74525ce8e07bbe6d783David Howells		render_opcode(out, "_action(ACT_%s),\n", e->action->name);
15474520c6a49af833c83de6c74525ce8e07bbe6d783David Howells}
1548