git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@19539 ec53bebd-3082-4978-b11e-865c3cabbd6b
		
			
				
	
	
		
			978 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			978 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
 | 
						|
 * (Royal Institute of Technology, Stockholm, Sweden). 
 | 
						|
 * All rights reserved. 
 | 
						|
 *
 | 
						|
 * Redistribution and use in source and binary forms, with or without 
 | 
						|
 * modification, are permitted provided that the following conditions 
 | 
						|
 * are met: 
 | 
						|
 *
 | 
						|
 * 1. Redistributions of source code must retain the above copyright 
 | 
						|
 *    notice, this list of conditions and the following disclaimer. 
 | 
						|
 *
 | 
						|
 * 2. Redistributions in binary form must reproduce the above copyright 
 | 
						|
 *    notice, this list of conditions and the following disclaimer in the 
 | 
						|
 *    documentation and/or other materials provided with the distribution. 
 | 
						|
 *
 | 
						|
 * 3. Neither the name of the Institute nor the names of its contributors 
 | 
						|
 *    may be used to endorse or promote products derived from this software 
 | 
						|
 *    without specific prior written permission. 
 | 
						|
 *
 | 
						|
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
 | 
						|
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 | 
						|
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 | 
						|
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
 | 
						|
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 | 
						|
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
 | 
						|
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 | 
						|
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 | 
						|
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
 | 
						|
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 | 
						|
 * SUCH DAMAGE. 
 | 
						|
 */
 | 
						|
 | 
						|
/* $Id$ */
 | 
						|
 | 
						|
%{
 | 
						|
#ifdef HAVE_CONFIG_H
 | 
						|
#include <config.h>
 | 
						|
#endif
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include "symbol.h"
 | 
						|
#include "lex.h"
 | 
						|
#include "gen_locl.h"
 | 
						|
#include "der.h"
 | 
						|
 | 
						|
RCSID("$Id$");
 | 
						|
 | 
						|
static Type *new_type (Typetype t);
 | 
						|
static struct constraint_spec *new_constraint_spec(enum ctype);
 | 
						|
static Type *new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype);
 | 
						|
void yyerror (const char *);
 | 
						|
static struct objid *new_objid(const char *label, int value);
 | 
						|
static void add_oid_to_tail(struct objid *, struct objid *);
 | 
						|
static void fix_labels(Symbol *s);
 | 
						|
 | 
						|
struct string_list {
 | 
						|
    char *string;
 | 
						|
    struct string_list *next;
 | 
						|
};
 | 
						|
 | 
						|
%}
 | 
						|
 | 
						|
%union {
 | 
						|
    int constant;
 | 
						|
    struct value *value;
 | 
						|
    struct range range;
 | 
						|
    char *name;
 | 
						|
    Type *type;
 | 
						|
    Member *member;
 | 
						|
    struct objid *objid;
 | 
						|
    char *defval;
 | 
						|
    struct string_list *sl;
 | 
						|
    struct tagtype tag;
 | 
						|
    struct memhead *members;
 | 
						|
    struct constraint_spec *constraint_spec;
 | 
						|
}
 | 
						|
 | 
						|
%token kw_ABSENT
 | 
						|
%token kw_ABSTRACT_SYNTAX
 | 
						|
%token kw_ALL
 | 
						|
%token kw_APPLICATION
 | 
						|
%token kw_AUTOMATIC
 | 
						|
%token kw_BEGIN
 | 
						|
%token kw_BIT
 | 
						|
%token kw_BMPString
 | 
						|
%token kw_BOOLEAN
 | 
						|
%token kw_BY
 | 
						|
%token kw_CHARACTER
 | 
						|
%token kw_CHOICE
 | 
						|
%token kw_CLASS
 | 
						|
%token kw_COMPONENT
 | 
						|
%token kw_COMPONENTS
 | 
						|
%token kw_CONSTRAINED
 | 
						|
%token kw_CONTAINING
 | 
						|
%token kw_DEFAULT
 | 
						|
%token kw_DEFINITIONS
 | 
						|
%token kw_EMBEDDED
 | 
						|
%token kw_ENCODED
 | 
						|
%token kw_END
 | 
						|
%token kw_ENUMERATED
 | 
						|
%token kw_EXCEPT
 | 
						|
%token kw_EXPLICIT
 | 
						|
%token kw_EXPORTS
 | 
						|
%token kw_EXTENSIBILITY
 | 
						|
%token kw_EXTERNAL
 | 
						|
%token kw_FALSE
 | 
						|
%token kw_FROM
 | 
						|
%token kw_GeneralString
 | 
						|
%token kw_GeneralizedTime
 | 
						|
%token kw_GraphicString
 | 
						|
%token kw_IA5String
 | 
						|
%token kw_IDENTIFIER
 | 
						|
%token kw_IMPLICIT
 | 
						|
%token kw_IMPLIED
 | 
						|
%token kw_IMPORTS
 | 
						|
%token kw_INCLUDES
 | 
						|
%token kw_INSTANCE
 | 
						|
%token kw_INTEGER
 | 
						|
%token kw_INTERSECTION
 | 
						|
%token kw_ISO646String
 | 
						|
%token kw_MAX
 | 
						|
%token kw_MIN
 | 
						|
%token kw_MINUS_INFINITY
 | 
						|
%token kw_NULL
 | 
						|
%token kw_NumericString
 | 
						|
%token kw_OBJECT
 | 
						|
%token kw_OCTET
 | 
						|
%token kw_OF
 | 
						|
%token kw_OPTIONAL
 | 
						|
%token kw_ObjectDescriptor
 | 
						|
%token kw_PATTERN
 | 
						|
%token kw_PDV
 | 
						|
%token kw_PLUS_INFINITY
 | 
						|
%token kw_PRESENT
 | 
						|
%token kw_PRIVATE
 | 
						|
%token kw_PrintableString
 | 
						|
%token kw_REAL
 | 
						|
%token kw_RELATIVE_OID
 | 
						|
%token kw_SEQUENCE
 | 
						|
%token kw_SET
 | 
						|
%token kw_SIZE
 | 
						|
%token kw_STRING
 | 
						|
%token kw_SYNTAX
 | 
						|
%token kw_T61String
 | 
						|
%token kw_TAGS
 | 
						|
%token kw_TRUE
 | 
						|
%token kw_TYPE_IDENTIFIER
 | 
						|
%token kw_TeletexString
 | 
						|
%token kw_UNION
 | 
						|
%token kw_UNIQUE
 | 
						|
%token kw_UNIVERSAL
 | 
						|
%token kw_UTCTime
 | 
						|
%token kw_UTF8String
 | 
						|
%token kw_UniversalString
 | 
						|
%token kw_VideotexString
 | 
						|
%token kw_VisibleString
 | 
						|
%token kw_WITH
 | 
						|
 | 
						|
%token RANGE
 | 
						|
%token EEQUAL
 | 
						|
%token ELLIPSIS
 | 
						|
 | 
						|
%token <name> IDENTIFIER  referencename
 | 
						|
%token <name> STRING
 | 
						|
 | 
						|
%token <constant> NUMBER
 | 
						|
%type <constant> SignedNumber
 | 
						|
%type <constant> Class tagenv
 | 
						|
 | 
						|
%type <value> Value
 | 
						|
%type <value> BuiltinValue
 | 
						|
%type <value> IntegerValue
 | 
						|
%type <value> BooleanValue
 | 
						|
%type <value> ObjectIdentifierValue
 | 
						|
%type <value> CharacterStringValue
 | 
						|
%type <value> NullValue
 | 
						|
%type <value> DefinedValue
 | 
						|
%type <value> ReferencedValue
 | 
						|
%type <value> Valuereference
 | 
						|
 | 
						|
%type <type> Type
 | 
						|
%type <type> BuiltinType
 | 
						|
%type <type> BitStringType
 | 
						|
%type <type> BooleanType
 | 
						|
%type <type> ChoiceType
 | 
						|
%type <type> ConstrainedType
 | 
						|
%type <type> EnumeratedType
 | 
						|
%type <type> IntegerType
 | 
						|
%type <type> NullType
 | 
						|
%type <type> OctetStringType
 | 
						|
%type <type> SequenceType
 | 
						|
%type <type> SequenceOfType
 | 
						|
%type <type> SetType
 | 
						|
%type <type> SetOfType
 | 
						|
%type <type> TaggedType
 | 
						|
%type <type> ReferencedType
 | 
						|
%type <type> DefinedType
 | 
						|
%type <type> UsefulType
 | 
						|
%type <type> ObjectIdentifierType
 | 
						|
%type <type> CharacterStringType
 | 
						|
%type <type> RestrictedCharactedStringType
 | 
						|
 | 
						|
%type <tag> Tag
 | 
						|
 | 
						|
%type <member> ComponentType
 | 
						|
%type <member> NamedBit
 | 
						|
%type <member> NamedNumber
 | 
						|
%type <member> NamedType
 | 
						|
%type <members> ComponentTypeList 
 | 
						|
%type <members> Enumerations
 | 
						|
%type <members> NamedBitList
 | 
						|
%type <members> NamedNumberList
 | 
						|
 | 
						|
%type <objid> objid objid_list objid_element objid_opt
 | 
						|
%type <range> range
 | 
						|
 | 
						|
%type <sl> referencenames
 | 
						|
 | 
						|
%type <constraint_spec> Constraint
 | 
						|
%type <constraint_spec> ConstraintSpec
 | 
						|
%type <constraint_spec> GeneralConstraint
 | 
						|
%type <constraint_spec> ContentsConstraint
 | 
						|
%type <constraint_spec> UserDefinedConstraint
 | 
						|
 | 
						|
%start ModuleDefinition
 | 
						|
 | 
						|
%%
 | 
						|
 | 
						|
ModuleDefinition: IDENTIFIER kw_DEFINITIONS TagDefault ExtensionDefault
 | 
						|
			EEQUAL kw_BEGIN ModuleBody kw_END
 | 
						|
		{
 | 
						|
			checkundefined();
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
TagDefault	: kw_EXPLICIT kw_TAGS
 | 
						|
		| kw_IMPLICIT kw_TAGS
 | 
						|
		      { error_message("implicit tagging is not supported"); }
 | 
						|
		| kw_AUTOMATIC kw_TAGS
 | 
						|
		      { error_message("automatic tagging is not supported"); }
 | 
						|
		| /* empty */
 | 
						|
		;
 | 
						|
 | 
						|
ExtensionDefault: kw_EXTENSIBILITY kw_IMPLIED
 | 
						|
		      { error_message("no extensibility options supported"); }
 | 
						|
		| /* empty */
 | 
						|
		;
 | 
						|
 | 
						|
ModuleBody	: /* Exports */ Imports AssignmentList
 | 
						|
		| /* empty */
 | 
						|
		;
 | 
						|
 | 
						|
Imports		: kw_IMPORTS SymbolsImported ';'
 | 
						|
		| /* empty */
 | 
						|
		;
 | 
						|
 | 
						|
SymbolsImported	: SymbolsFromModuleList
 | 
						|
		| /* empty */
 | 
						|
		;
 | 
						|
 | 
						|
SymbolsFromModuleList: SymbolsFromModule
 | 
						|
		| SymbolsFromModuleList SymbolsFromModule
 | 
						|
		;
 | 
						|
 | 
						|
SymbolsFromModule: referencenames kw_FROM IDENTIFIER objid_opt
 | 
						|
		{ 
 | 
						|
		    struct string_list *sl;
 | 
						|
		    for(sl = $1; sl != NULL; sl = sl->next) {
 | 
						|
			Symbol *s = addsym(sl->string);
 | 
						|
			s->stype = Stype;
 | 
						|
		    }
 | 
						|
		    add_import($3);
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
AssignmentList	: Assignment
 | 
						|
		| Assignment AssignmentList
 | 
						|
		;
 | 
						|
 | 
						|
Assignment	: TypeAssignment
 | 
						|
		| ValueAssignment
 | 
						|
		;
 | 
						|
 | 
						|
referencenames	: IDENTIFIER ',' referencenames
 | 
						|
		{
 | 
						|
		    $$ = emalloc(sizeof(*$$));
 | 
						|
		    $$->string = $1;
 | 
						|
		    $$->next = $3;
 | 
						|
		}
 | 
						|
		| IDENTIFIER
 | 
						|
		{
 | 
						|
		    $$ = emalloc(sizeof(*$$));
 | 
						|
		    $$->string = $1;
 | 
						|
		    $$->next = NULL;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
TypeAssignment	: IDENTIFIER EEQUAL Type
 | 
						|
		{
 | 
						|
		    Symbol *s = addsym ($1);
 | 
						|
		    s->stype = Stype;
 | 
						|
		    s->type = $3;
 | 
						|
		    fix_labels(s);
 | 
						|
		    generate_type (s);
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
Type		: BuiltinType
 | 
						|
		| ReferencedType
 | 
						|
		| ConstrainedType
 | 
						|
		;
 | 
						|
 | 
						|
BuiltinType	: BitStringType
 | 
						|
		| BooleanType
 | 
						|
		| CharacterStringType
 | 
						|
		| ChoiceType
 | 
						|
		| EnumeratedType
 | 
						|
		| IntegerType
 | 
						|
		| NullType
 | 
						|
		| ObjectIdentifierType
 | 
						|
		| OctetStringType
 | 
						|
		| SequenceType
 | 
						|
		| SequenceOfType
 | 
						|
		| SetType
 | 
						|
		| SetOfType
 | 
						|
		| TaggedType
 | 
						|
		;
 | 
						|
 | 
						|
BooleanType	: kw_BOOLEAN
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_Boolean, 
 | 
						|
				     TE_EXPLICIT, new_type(TBoolean));
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
range		: '(' Value RANGE Value ')'
 | 
						|
		{
 | 
						|
			if($2->type != integervalue || 
 | 
						|
			   $4->type != integervalue)
 | 
						|
				error_message("Non-integer value used in range");
 | 
						|
			$$.min = $2->u.integervalue;
 | 
						|
			$$.max = $4->u.integervalue;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
IntegerType	: kw_INTEGER
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_Integer, 
 | 
						|
				     TE_EXPLICIT, new_type(TInteger));
 | 
						|
		}
 | 
						|
		| kw_INTEGER range
 | 
						|
		{
 | 
						|
			$$ = new_type(TInteger);
 | 
						|
			$$->range = emalloc(sizeof(*$$->range));
 | 
						|
			*($$->range) = $2;
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$);
 | 
						|
		}
 | 
						|
		| kw_INTEGER '{' NamedNumberList '}'
 | 
						|
		{
 | 
						|
		  $$ = new_type(TInteger);
 | 
						|
		  $$->members = $3;
 | 
						|
		  $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$);
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
NamedNumberList	: NamedNumber
 | 
						|
		{
 | 
						|
			$$ = emalloc(sizeof(*$$));
 | 
						|
			ASN1_TAILQ_INIT($$);
 | 
						|
			ASN1_TAILQ_INSERT_HEAD($$, $1, members);
 | 
						|
		}
 | 
						|
		| NamedNumberList ',' NamedNumber
 | 
						|
		{
 | 
						|
			ASN1_TAILQ_INSERT_TAIL($1, $3, members);
 | 
						|
			$$ = $1;
 | 
						|
		}
 | 
						|
		| NamedNumberList ',' ELLIPSIS
 | 
						|
			{ $$ = $1; } /* XXX used for Enumerations */
 | 
						|
		;
 | 
						|
 | 
						|
NamedNumber	: IDENTIFIER '(' SignedNumber ')'
 | 
						|
		{
 | 
						|
			$$ = emalloc(sizeof(*$$));
 | 
						|
			$$->name = $1;
 | 
						|
			$$->gen_name = estrdup($1);
 | 
						|
			output_name ($$->gen_name);
 | 
						|
			$$->val = $3;
 | 
						|
			$$->optional = 0;
 | 
						|
			$$->ellipsis = 0;
 | 
						|
			$$->type = NULL;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
EnumeratedType	: kw_ENUMERATED '{' Enumerations '}'
 | 
						|
		{
 | 
						|
		  $$ = new_type(TInteger);
 | 
						|
		  $$->members = $3;
 | 
						|
		  $$ = new_tag(ASN1_C_UNIV, UT_Enumerated, TE_EXPLICIT, $$);
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
Enumerations	: NamedNumberList /* XXX */
 | 
						|
		;
 | 
						|
 | 
						|
BitStringType	: kw_BIT kw_STRING
 | 
						|
		{
 | 
						|
		  $$ = new_type(TBitString);
 | 
						|
		  $$->members = emalloc(sizeof(*$$->members));
 | 
						|
		  ASN1_TAILQ_INIT($$->members);
 | 
						|
		  $$ = new_tag(ASN1_C_UNIV, UT_BitString, TE_EXPLICIT, $$);
 | 
						|
		}
 | 
						|
		| kw_BIT kw_STRING '{' NamedBitList '}'
 | 
						|
		{
 | 
						|
		  $$ = new_type(TBitString);
 | 
						|
		  $$->members = $4;
 | 
						|
		  $$ = new_tag(ASN1_C_UNIV, UT_BitString, TE_EXPLICIT, $$);
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
ObjectIdentifierType: kw_OBJECT kw_IDENTIFIER
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_OID, 
 | 
						|
				     TE_EXPLICIT, new_type(TOID));
 | 
						|
		}
 | 
						|
		;
 | 
						|
OctetStringType	: kw_OCTET kw_STRING
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_OctetString, 
 | 
						|
				     TE_EXPLICIT, new_type(TOctetString));
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
NullType	: kw_NULL
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_Null, 
 | 
						|
				     TE_EXPLICIT, new_type(TNull));
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
SequenceType	: kw_SEQUENCE '{' /* ComponentTypeLists */ ComponentTypeList '}'
 | 
						|
		{
 | 
						|
		  $$ = new_type(TSequence);
 | 
						|
		  $$->members = $3;
 | 
						|
		  $$ = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, $$);
 | 
						|
		}
 | 
						|
		| kw_SEQUENCE '{' '}'
 | 
						|
		{
 | 
						|
		  $$ = new_type(TSequence);
 | 
						|
		  $$->members = NULL;
 | 
						|
		  $$ = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, $$);
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
SequenceOfType	: kw_SEQUENCE kw_OF Type
 | 
						|
		{
 | 
						|
		  $$ = new_type(TSequenceOf);
 | 
						|
		  $$->subtype = $3;
 | 
						|
		  $$ = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, $$);
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
SetType		: kw_SET '{' /* ComponentTypeLists */ ComponentTypeList '}'
 | 
						|
		{
 | 
						|
		  $$ = new_type(TSet);
 | 
						|
		  $$->members = $3;
 | 
						|
		  $$ = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, $$);
 | 
						|
		}
 | 
						|
		| kw_SET '{' '}'
 | 
						|
		{
 | 
						|
		  $$ = new_type(TSet);
 | 
						|
		  $$->members = NULL;
 | 
						|
		  $$ = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, $$);
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
SetOfType	: kw_SET kw_OF Type
 | 
						|
		{
 | 
						|
		  $$ = new_type(TSetOf);
 | 
						|
		  $$->subtype = $3;
 | 
						|
		  $$ = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, $$);
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
ChoiceType	: kw_CHOICE '{' /* AlternativeTypeLists */ ComponentTypeList '}'
 | 
						|
		{
 | 
						|
		  $$ = new_type(TChoice);
 | 
						|
		  $$->members = $3;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
ReferencedType	: DefinedType
 | 
						|
		| UsefulType
 | 
						|
		;
 | 
						|
 | 
						|
DefinedType	: IDENTIFIER
 | 
						|
		{
 | 
						|
		  Symbol *s = addsym($1);
 | 
						|
		  $$ = new_type(TType);
 | 
						|
		  if(s->stype != Stype && s->stype != SUndefined)
 | 
						|
		    error_message ("%s is not a type\n", $1);
 | 
						|
		  else
 | 
						|
		    $$->symbol = s;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
UsefulType	: kw_GeneralizedTime
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_GeneralizedTime, 
 | 
						|
				     TE_EXPLICIT, new_type(TGeneralizedTime));
 | 
						|
		}
 | 
						|
		| kw_UTCTime
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_UTCTime, 
 | 
						|
				     TE_EXPLICIT, new_type(TUTCTime));
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
ConstrainedType	: Type Constraint
 | 
						|
		{
 | 
						|
		    /* if (Constraint.type == contentConstrant) {
 | 
						|
		       assert(Constraint.u.constraint.type == octetstring|bitstring-w/o-NamedBitList); // remember to check type reference too
 | 
						|
		       if (Constraint.u.constraint.type) {
 | 
						|
		         assert((Constraint.u.constraint.type.length % 8) == 0);
 | 
						|
		       }
 | 
						|
		      }
 | 
						|
		      if (Constraint.u.constraint.encoding) {
 | 
						|
		        type == der-oid|ber-oid
 | 
						|
		      }
 | 
						|
		    */
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
 | 
						|
Constraint	: '(' ConstraintSpec ')'
 | 
						|
		{
 | 
						|
		    $$ = $2;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
ConstraintSpec	: GeneralConstraint
 | 
						|
		;
 | 
						|
 | 
						|
GeneralConstraint: ContentsConstraint
 | 
						|
		| UserDefinedConstraint
 | 
						|
		;
 | 
						|
 | 
						|
ContentsConstraint: kw_CONTAINING Type
 | 
						|
		{
 | 
						|
		    $$ = new_constraint_spec(CT_CONTENTS);
 | 
						|
		    $$->u.content.type = $2;
 | 
						|
		    $$->u.content.encoding = NULL;
 | 
						|
		}
 | 
						|
		| kw_ENCODED kw_BY Value
 | 
						|
		{
 | 
						|
		    if ($3->type != objectidentifiervalue)
 | 
						|
			error_message("Non-OID used in ENCODED BY constraint");
 | 
						|
		    $$ = new_constraint_spec(CT_CONTENTS);
 | 
						|
		    $$->u.content.type = NULL;
 | 
						|
		    $$->u.content.encoding = $3;
 | 
						|
		}
 | 
						|
		| kw_CONTAINING Type kw_ENCODED kw_BY Value
 | 
						|
		{
 | 
						|
		    if ($5->type != objectidentifiervalue)
 | 
						|
			error_message("Non-OID used in ENCODED BY constraint");
 | 
						|
		    $$ = new_constraint_spec(CT_CONTENTS);
 | 
						|
		    $$->u.content.type = $2;
 | 
						|
		    $$->u.content.encoding = $5;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
UserDefinedConstraint: kw_CONSTRAINED kw_BY '{' '}'
 | 
						|
		{
 | 
						|
		    $$ = new_constraint_spec(CT_USER);
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
TaggedType	: Tag tagenv Type
 | 
						|
		{
 | 
						|
			$$ = new_type(TTag);
 | 
						|
			$$->tag = $1;
 | 
						|
			$$->tag.tagenv = $2;
 | 
						|
			if($3->type == TTag && $2 == TE_IMPLICIT) {
 | 
						|
				$$->subtype = $3->subtype;
 | 
						|
				free($3);
 | 
						|
			} else
 | 
						|
				$$->subtype = $3;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
Tag		: '[' Class NUMBER ']'
 | 
						|
		{
 | 
						|
			$$.tagclass = $2;
 | 
						|
			$$.tagvalue = $3;
 | 
						|
			$$.tagenv = TE_EXPLICIT;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
Class		: /* */
 | 
						|
		{
 | 
						|
			$$ = ASN1_C_CONTEXT;
 | 
						|
		}
 | 
						|
		| kw_UNIVERSAL
 | 
						|
		{
 | 
						|
			$$ = ASN1_C_UNIV;
 | 
						|
		}
 | 
						|
		| kw_APPLICATION
 | 
						|
		{
 | 
						|
			$$ = ASN1_C_APPL;
 | 
						|
		}
 | 
						|
		| kw_PRIVATE
 | 
						|
		{
 | 
						|
			$$ = ASN1_C_PRIVATE;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
tagenv		: /* */
 | 
						|
		{
 | 
						|
			$$ = TE_EXPLICIT;
 | 
						|
		}
 | 
						|
		| kw_EXPLICIT
 | 
						|
		{
 | 
						|
			$$ = TE_EXPLICIT;
 | 
						|
		}
 | 
						|
		| kw_IMPLICIT
 | 
						|
		{
 | 
						|
			$$ = TE_IMPLICIT;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
 | 
						|
ValueAssignment	: IDENTIFIER Type EEQUAL Value
 | 
						|
		{
 | 
						|
			Symbol *s;
 | 
						|
			s = addsym ($1);
 | 
						|
 | 
						|
			s->stype = SValue;
 | 
						|
			s->value = $4;
 | 
						|
			generate_constant (s);
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
CharacterStringType: RestrictedCharactedStringType
 | 
						|
		;
 | 
						|
 | 
						|
RestrictedCharactedStringType: kw_GeneralString
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_GeneralString, 
 | 
						|
				     TE_EXPLICIT, new_type(TGeneralString));
 | 
						|
		}
 | 
						|
		| kw_UTF8String
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_UTF8String, 
 | 
						|
				     TE_EXPLICIT, new_type(TUTF8String));
 | 
						|
		}
 | 
						|
		| kw_PrintableString
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_PrintableString, 
 | 
						|
				     TE_EXPLICIT, new_type(TPrintableString));
 | 
						|
		}
 | 
						|
		| kw_VisibleString
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_VisibleString, 
 | 
						|
				     TE_EXPLICIT, new_type(TVisibleString));
 | 
						|
		}
 | 
						|
		| kw_IA5String
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_IA5String, 
 | 
						|
				     TE_EXPLICIT, new_type(TIA5String));
 | 
						|
		}
 | 
						|
		| kw_BMPString
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_BMPString, 
 | 
						|
				     TE_EXPLICIT, new_type(TBMPString));
 | 
						|
		}
 | 
						|
		| kw_UniversalString
 | 
						|
		{
 | 
						|
			$$ = new_tag(ASN1_C_UNIV, UT_UniversalString, 
 | 
						|
				     TE_EXPLICIT, new_type(TUniversalString));
 | 
						|
		}
 | 
						|
 | 
						|
		;
 | 
						|
 | 
						|
ComponentTypeList: ComponentType
 | 
						|
		{
 | 
						|
			$$ = emalloc(sizeof(*$$));
 | 
						|
			ASN1_TAILQ_INIT($$);
 | 
						|
			ASN1_TAILQ_INSERT_HEAD($$, $1, members);
 | 
						|
		}
 | 
						|
		| ComponentTypeList ',' ComponentType
 | 
						|
		{
 | 
						|
			ASN1_TAILQ_INSERT_TAIL($1, $3, members);
 | 
						|
			$$ = $1;
 | 
						|
		}
 | 
						|
		| ComponentTypeList ',' ELLIPSIS
 | 
						|
		{
 | 
						|
		        struct member *m = ecalloc(1, sizeof(*m));
 | 
						|
			m->name = estrdup("...");
 | 
						|
			m->gen_name = estrdup("asn1_ellipsis");
 | 
						|
			m->ellipsis = 1;
 | 
						|
			ASN1_TAILQ_INSERT_TAIL($1, m, members);
 | 
						|
			$$ = $1;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
NamedType	: IDENTIFIER Type
 | 
						|
		{
 | 
						|
		  $$ = emalloc(sizeof(*$$));
 | 
						|
		  $$->name = $1;
 | 
						|
		  $$->gen_name = estrdup($1);
 | 
						|
		  output_name ($$->gen_name);
 | 
						|
		  $$->type = $2;
 | 
						|
		  $$->ellipsis = 0;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
ComponentType	: NamedType
 | 
						|
		{
 | 
						|
			$$ = $1;
 | 
						|
			$$->optional = 0;
 | 
						|
			$$->defval = NULL;
 | 
						|
		}
 | 
						|
		| NamedType kw_OPTIONAL
 | 
						|
		{
 | 
						|
			$$ = $1;
 | 
						|
			$$->optional = 1;
 | 
						|
			$$->defval = NULL;
 | 
						|
		}
 | 
						|
		| NamedType kw_DEFAULT Value
 | 
						|
		{
 | 
						|
			$$ = $1;
 | 
						|
			$$->optional = 0;
 | 
						|
			$$->defval = $3;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
NamedBitList	: NamedBit
 | 
						|
		{
 | 
						|
			$$ = emalloc(sizeof(*$$));
 | 
						|
			ASN1_TAILQ_INIT($$);
 | 
						|
			ASN1_TAILQ_INSERT_HEAD($$, $1, members);
 | 
						|
		}
 | 
						|
		| NamedBitList ',' NamedBit
 | 
						|
		{
 | 
						|
			ASN1_TAILQ_INSERT_TAIL($1, $3, members);
 | 
						|
			$$ = $1;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
NamedBit	: IDENTIFIER '(' NUMBER ')'
 | 
						|
		{
 | 
						|
		  $$ = emalloc(sizeof(*$$));
 | 
						|
		  $$->name = $1;
 | 
						|
		  $$->gen_name = estrdup($1);
 | 
						|
		  output_name ($$->gen_name);
 | 
						|
		  $$->val = $3;
 | 
						|
		  $$->optional = 0;
 | 
						|
		  $$->ellipsis = 0;
 | 
						|
		  $$->type = NULL;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
objid_opt	: objid
 | 
						|
		| /* empty */ { $$ = NULL; }
 | 
						|
		;
 | 
						|
 | 
						|
objid		: '{' objid_list '}'
 | 
						|
		{
 | 
						|
			$$ = $2;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
objid_list	:  /* empty */
 | 
						|
		{
 | 
						|
			$$ = NULL;
 | 
						|
		}
 | 
						|
		| objid_element objid_list
 | 
						|
		{
 | 
						|
		        if ($2) {
 | 
						|
				$$ = $2;
 | 
						|
				add_oid_to_tail($2, $1);
 | 
						|
			} else {
 | 
						|
				$$ = $1;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
objid_element	: IDENTIFIER '(' NUMBER ')'
 | 
						|
		{
 | 
						|
			$$ = new_objid($1, $3);
 | 
						|
		}
 | 
						|
		| IDENTIFIER
 | 
						|
		{
 | 
						|
		    Symbol *s = addsym($1);
 | 
						|
		    if(s->stype != SValue ||
 | 
						|
		       s->value->type != objectidentifiervalue) {
 | 
						|
			error_message("%s is not an object identifier\n", 
 | 
						|
				      s->name);
 | 
						|
			exit(1);
 | 
						|
		    }
 | 
						|
		    $$ = s->value->u.objectidentifiervalue;
 | 
						|
		}
 | 
						|
		| NUMBER
 | 
						|
		{
 | 
						|
		    $$ = new_objid(NULL, $1);
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
Value		: BuiltinValue
 | 
						|
		| ReferencedValue
 | 
						|
		;
 | 
						|
 | 
						|
BuiltinValue	: BooleanValue
 | 
						|
		| CharacterStringValue
 | 
						|
		| IntegerValue
 | 
						|
		| ObjectIdentifierValue
 | 
						|
		| NullValue
 | 
						|
		;
 | 
						|
 | 
						|
ReferencedValue	: DefinedValue
 | 
						|
		;
 | 
						|
 | 
						|
DefinedValue	: Valuereference
 | 
						|
		;
 | 
						|
 | 
						|
Valuereference	: IDENTIFIER
 | 
						|
		{
 | 
						|
			Symbol *s = addsym($1);
 | 
						|
			if(s->stype != SValue)
 | 
						|
				error_message ("%s is not a value\n",
 | 
						|
						s->name);
 | 
						|
			else
 | 
						|
				$$ = s->value;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
CharacterStringValue: STRING
 | 
						|
		{
 | 
						|
			$$ = emalloc(sizeof(*$$));
 | 
						|
			$$->type = stringvalue;
 | 
						|
			$$->u.stringvalue = $1;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
BooleanValue	: kw_TRUE
 | 
						|
		{
 | 
						|
			$$ = emalloc(sizeof(*$$));
 | 
						|
			$$->type = booleanvalue;
 | 
						|
			$$->u.booleanvalue = 0;
 | 
						|
		}
 | 
						|
		| kw_FALSE
 | 
						|
		{
 | 
						|
			$$ = emalloc(sizeof(*$$));
 | 
						|
			$$->type = booleanvalue;
 | 
						|
			$$->u.booleanvalue = 0;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
IntegerValue	: SignedNumber
 | 
						|
		{
 | 
						|
			$$ = emalloc(sizeof(*$$));
 | 
						|
			$$->type = integervalue;
 | 
						|
			$$->u.integervalue = $1;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
SignedNumber	: NUMBER
 | 
						|
		;
 | 
						|
 | 
						|
NullValue	: kw_NULL
 | 
						|
		{
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
ObjectIdentifierValue: objid
 | 
						|
		{
 | 
						|
			$$ = emalloc(sizeof(*$$));
 | 
						|
			$$->type = objectidentifiervalue;
 | 
						|
			$$->u.objectidentifiervalue = $1;
 | 
						|
		}
 | 
						|
		;
 | 
						|
 | 
						|
%%
 | 
						|
 | 
						|
void
 | 
						|
yyerror (const char *s)
 | 
						|
{
 | 
						|
     error_message ("%s\n", s);
 | 
						|
}
 | 
						|
 | 
						|
static Type *
 | 
						|
new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype)
 | 
						|
{
 | 
						|
    Type *t;
 | 
						|
    if(oldtype->type == TTag && oldtype->tag.tagenv == TE_IMPLICIT) {
 | 
						|
	t = oldtype;
 | 
						|
	oldtype = oldtype->subtype; /* XXX */
 | 
						|
    } else
 | 
						|
	t = new_type (TTag);
 | 
						|
    
 | 
						|
    t->tag.tagclass = tagclass;
 | 
						|
    t->tag.tagvalue = tagvalue;
 | 
						|
    t->tag.tagenv = tagenv;
 | 
						|
    t->subtype = oldtype;
 | 
						|
    return t;
 | 
						|
}
 | 
						|
 | 
						|
static struct objid *
 | 
						|
new_objid(const char *label, int value)
 | 
						|
{
 | 
						|
    struct objid *s;
 | 
						|
    s = emalloc(sizeof(*s));
 | 
						|
    s->label = label;
 | 
						|
    s->value = value;
 | 
						|
    s->next = NULL;
 | 
						|
    return s;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
add_oid_to_tail(struct objid *head, struct objid *tail)
 | 
						|
{
 | 
						|
    struct objid *o;
 | 
						|
    o = head;
 | 
						|
    while (o->next)
 | 
						|
	o = o->next;
 | 
						|
    o->next = tail;
 | 
						|
}
 | 
						|
 | 
						|
static Type *
 | 
						|
new_type (Typetype tt)
 | 
						|
{
 | 
						|
    Type *t = ecalloc(1, sizeof(*t));
 | 
						|
    t->type = tt;
 | 
						|
    return t;
 | 
						|
}
 | 
						|
 | 
						|
static struct constraint_spec *
 | 
						|
new_constraint_spec(enum ctype ct)
 | 
						|
{
 | 
						|
    struct constraint_spec *c = ecalloc(1, sizeof(*c));
 | 
						|
    c->ctype = ct;
 | 
						|
    return c;
 | 
						|
}
 | 
						|
 | 
						|
static void fix_labels2(Type *t, const char *prefix);
 | 
						|
static void fix_labels1(struct memhead *members, const char *prefix)
 | 
						|
{
 | 
						|
    Member *m;
 | 
						|
 | 
						|
    if(members == NULL)
 | 
						|
	return;
 | 
						|
    ASN1_TAILQ_FOREACH(m, members, members) {
 | 
						|
	asprintf(&m->label, "%s_%s", prefix, m->gen_name);
 | 
						|
	if (m->label == NULL)
 | 
						|
	    errx(1, "malloc");
 | 
						|
	if(m->type != NULL)
 | 
						|
	    fix_labels2(m->type, m->label);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void fix_labels2(Type *t, const char *prefix)
 | 
						|
{
 | 
						|
    for(; t; t = t->subtype)
 | 
						|
	fix_labels1(t->members, prefix);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
fix_labels(Symbol *s)
 | 
						|
{
 | 
						|
    char *p;
 | 
						|
    asprintf(&p, "choice_%s", s->gen_name);
 | 
						|
    if (p == NULL)
 | 
						|
	errx(1, "malloc");
 | 
						|
    fix_labels2(s->type, p);
 | 
						|
    free(p);
 | 
						|
}
 |