asn1c/libasn1parser/asn1p_y.y

2285 lines
48 KiB
Plaintext

%{
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "asn1parser.h"
#define YYPARSE_PARAM param
#define YYPARSE_PARAM_TYPE void **
#define YYERROR_VERBOSE
int yylex(void);
int yyerror(const char *msg);
#ifdef YYBYACC
int yyparse(void **param); /* byacc does not produce a prototype */
#endif
void asn1p_lexer_hack_push_opaque_state(void);
void asn1p_lexer_hack_enable_with_syntax(void);
void asn1p_lexer_hack_push_encoding_control(void);
#define yylineno asn1p_lineno
extern int asn1p_lineno;
/*
* Process directives as <ASN1C:RepresentAsPointer>
*/
extern int asn1p_as_pointer;
/*
* This temporary variable is used to solve the shortcomings of 1-lookahead
* parser.
*/
static struct AssignedIdentifier *saved_aid;
static asn1p_value_t *_convert_bitstring2binary(char *str, int base);
static void _fixup_anonymous_identifier(asn1p_expr_t *expr);
#define checkmem(ptr) do { \
if(!(ptr)) \
return yyerror("Memory failure"); \
} while(0)
#define CONSTRAINT_INSERT(root, constr_type, arg1, arg2) do { \
if(arg1->type != constr_type) { \
int __ret; \
root = asn1p_constraint_new(yylineno); \
checkmem(root); \
root->type = constr_type; \
__ret = asn1p_constraint_insert(root, \
arg1); \
checkmem(__ret == 0); \
} else { \
root = arg1; \
} \
if(arg2) { \
int __ret \
= asn1p_constraint_insert(root, arg2); \
checkmem(__ret == 0); \
} \
} while(0)
%}
/*
* Token value definition.
* a_*: ASN-specific types.
* tv_*: Locally meaningful types.
*/
%union {
asn1p_t *a_grammar;
asn1p_module_flags_e a_module_flags;
asn1p_module_t *a_module;
asn1p_expr_type_e a_type; /* ASN.1 Type */
asn1p_expr_t *a_expr; /* Constructed collection */
asn1p_constraint_t *a_constr; /* Constraint */
enum asn1p_constraint_type_e a_ctype;/* Constraint type */
asn1p_xports_t *a_xports; /* IMports/EXports */
struct AssignedIdentifier a_aid; /* Assigned Identifier */
asn1p_oid_t *a_oid; /* Object Identifier */
asn1p_oid_arc_t a_oid_arc; /* Single OID's arc */
struct asn1p_type_tag_s a_tag; /* A tag */
asn1p_ref_t *a_ref; /* Reference to custom type */
asn1p_wsyntx_t *a_wsynt; /* WITH SYNTAX contents */
asn1p_wsyntx_chunk_t *a_wchunk; /* WITH SYNTAX chunk */
struct asn1p_ref_component_s a_refcomp; /* Component of a reference */
asn1p_value_t *a_value; /* Number, DefinedValue, etc */
struct asn1p_param_s a_parg; /* A parameter argument */
asn1p_paramlist_t *a_plist; /* A pargs list */
struct asn1p_expr_marker_s a_marker; /* OPTIONAL/DEFAULT */
enum asn1p_constr_pres_e a_pres; /* PRESENT/ABSENT/OPTIONAL */
asn1c_integer_t a_int;
char *tv_str;
struct {
char *buf;
int len;
} tv_opaque;
struct {
char *name;
struct asn1p_type_tag_s tag;
} tv_nametag;
};
/*
* Token types returned by scanner.
*/
%token TOK_PPEQ /* "::=", Pseudo Pascal EQuality */
%token <tv_opaque> TOK_opaque /* opaque data (driven from .y) */
%token <tv_str> TOK_bstring
%token <tv_opaque> TOK_cstring
%token <tv_str> TOK_hstring
%token <tv_str> TOK_identifier
%token <a_int> TOK_number
%token <a_int> TOK_tuple
%token <a_int> TOK_quadruple
%token <a_int> TOK_number_negative
%token <tv_str> TOK_typereference
%token <tv_str> TOK_capitalreference /* "CLASS1" */
%token <tv_str> TOK_typefieldreference /* "&Pork" */
%token <tv_str> TOK_valuefieldreference /* "&id" */
/*
* Token types representing ASN.1 standard keywords.
*/
%token TOK_ABSENT
%token TOK_ABSTRACT_SYNTAX
%token TOK_ALL
%token TOK_ANY
%token TOK_APPLICATION
%token TOK_AUTOMATIC
%token TOK_BEGIN
%token TOK_BIT
%token TOK_BMPString
%token TOK_BOOLEAN
%token TOK_BY
%token TOK_CHARACTER
%token TOK_CHOICE
%token TOK_CLASS
%token TOK_COMPONENT
%token TOK_COMPONENTS
%token TOK_CONSTRAINED
%token TOK_CONTAINING
%token TOK_DEFAULT
%token TOK_DEFINITIONS
%token TOK_DEFINED
%token TOK_EMBEDDED
%token TOK_ENCODED
%token TOK_ENCODING_CONTROL
%token TOK_END
%token TOK_ENUMERATED
%token TOK_EXPLICIT
%token TOK_EXPORTS
%token TOK_EXTENSIBILITY
%token TOK_EXTERNAL
%token TOK_FALSE
%token TOK_FROM
%token TOK_GeneralizedTime
%token TOK_GeneralString
%token TOK_GraphicString
%token TOK_IA5String
%token TOK_IDENTIFIER
%token TOK_IMPLICIT
%token TOK_IMPLIED
%token TOK_IMPORTS
%token TOK_INCLUDES
%token TOK_INSTANCE
%token TOK_INSTRUCTIONS
%token TOK_INTEGER
%token TOK_ISO646String
%token TOK_MAX
%token TOK_MIN
%token TOK_MINUS_INFINITY
%token TOK_NULL
%token TOK_NumericString
%token TOK_OBJECT
%token TOK_ObjectDescriptor
%token TOK_OCTET
%token TOK_OF
%token TOK_OPTIONAL
%token TOK_PATTERN
%token TOK_PDV
%token TOK_PLUS_INFINITY
%token TOK_PRESENT
%token TOK_PrintableString
%token TOK_PRIVATE
%token TOK_REAL
%token TOK_RELATIVE_OID
%token TOK_SEQUENCE
%token TOK_SET
%token TOK_SIZE
%token TOK_STRING
%token TOK_SYNTAX
%token TOK_T61String
%token TOK_TAGS
%token TOK_TeletexString
%token TOK_TRUE
%token TOK_TYPE_IDENTIFIER
%token TOK_UNIQUE
%token TOK_UNIVERSAL
%token TOK_UniversalString
%token TOK_UTCTime
%token TOK_UTF8String
%token TOK_VideotexString
%token TOK_VisibleString
%token TOK_WITH
%left TOK_EXCEPT
%left '^' TOK_INTERSECTION
%left '|' TOK_UNION
/* Misc tags */
%token TOK_TwoDots /* .. */
%token TOK_ThreeDots /* ... */
/*
* Types defined herein.
*/
%type <a_grammar> ModuleList
%type <a_module> ModuleSpecification
%type <a_module> ModuleSpecificationBody
%type <a_module> ModuleSpecificationElement
%type <a_module> optModuleSpecificationBody /* Optional */
%type <a_module_flags> optModuleSpecificationFlags
%type <a_module_flags> ModuleSpecificationFlags /* Set of FL */
%type <a_module_flags> ModuleSpecificationFlag /* Single FL */
%type <a_module> ImportsDefinition
%type <a_module> ImportsBundleSet
%type <a_xports> ImportsBundle
%type <a_xports> ImportsList
%type <a_xports> ExportsDefinition
%type <a_xports> ExportsBody
%type <a_expr> ImportsElement
%type <a_expr> ExportsElement
%type <a_expr> ExtensionAndException
%type <a_expr> TypeDeclaration
%type <a_expr> TypeDeclarationSet
%type <a_ref> ComplexTypeReference
%type <a_ref> ComplexTypeReferenceAmpList
%type <a_refcomp> ComplexTypeReferenceElement
%type <a_refcomp> ClassFieldIdentifier
%type <a_refcomp> ClassFieldName
%type <a_expr> ClassFieldList
%type <a_expr> ClassField
%type <a_expr> ClassDeclaration
%type <a_expr> Type
%type <a_expr> DataTypeReference /* Type1 ::= Type2 */
%type <a_expr> DefinedTypeRef
%type <a_expr> ValueSetDefinition /* Val INTEGER ::= {1|2} */
%type <a_expr> ValueDefinition /* val INTEGER ::= 1*/
%type <a_value> Value
%type <a_value> DefinedValue
%type <a_value> SignedNumber
%type <a_expr> optComponentTypeLists
%type <a_expr> ComponentTypeLists
%type <a_expr> ComponentType
%type <a_expr> AlternativeTypeLists
%type <a_expr> AlternativeType
//%type <a_expr> optUniverationDefinition
%type <a_expr> UniverationDefinition
%type <a_expr> UniverationList
%type <a_expr> UniverationElement
%type <tv_str> TypeRefName
%type <tv_str> ObjectClassReference
%type <tv_str> Identifier
%type <tv_str> optIdentifier
%type <a_parg> ParameterArgumentName
%type <a_plist> ParameterArgumentList
%type <a_expr> ActualParameter
%type <a_expr> ActualParameterList
%type <a_aid> AssignedIdentifier /* OID/DefinedValue */
%type <a_oid> ObjectIdentifier /* OID */
%type <a_oid> optObjectIdentifier /* Optional OID */
%type <a_oid> ObjectIdentifierBody
%type <a_oid_arc> ObjectIdentifierElement
%type <a_expr> BasicType
%type <a_type> BasicTypeId
%type <a_type> BasicTypeId_UniverationCompatible
%type <a_type> BasicString
%type <tv_opaque> Opaque
//%type <tv_opaque> StringValue
%type <a_tag> Tag /* [UNIVERSAL 0] IMPLICIT */
%type <a_tag> TagClass TagTypeValue TagPlicit
%type <a_tag> optTag /* [UNIVERSAL 0] IMPLICIT */
%type <a_constr> optConstraints
%type <a_constr> Constraints
%type <a_constr> SetOfConstraints
%type <a_constr> ElementSetSpecs /* 1..2,...,3 */
%type <a_constr> ElementSetSpec /* 1..2,...,3 */
%type <a_constr> ConstraintSubtypeElement /* 1..2 */
%type <a_constr> SimpleTableConstraint
%type <a_constr> TableConstraint
%type <a_constr> InnerTypeConstraint
%type <a_constr> WithComponentsList
%type <a_constr> WithComponentsElement
%type <a_constr> ComponentRelationConstraint
%type <a_constr> AtNotationList
%type <a_ref> AtNotationElement
%type <a_value> SingleValue
%type <a_value> ContainedSubtype
%type <a_ctype> ConstraintSpec
%type <a_ctype> ConstraintRangeSpec
%type <a_value> RestrictedCharacterStringValue
%type <a_wsynt> optWithSyntax
%type <a_wsynt> WithSyntax
%type <a_wsynt> WithSyntaxFormat
%type <a_wchunk> WithSyntaxFormatToken
%type <a_marker> optMarker Marker
%type <a_int> optUnique
%type <a_pres> optPresenceConstraint PresenceConstraint
%type <tv_str> ComponentIdList
%type <a_int> NSTD_IndirectMarker
%%
ParsedGrammar:
ModuleList {
*(void **)param = $1;
}
;
ModuleList:
ModuleSpecification {
$$ = asn1p_new();
checkmem($$);
TQ_ADD(&($$->modules), $1, mod_next);
}
| ModuleList ModuleSpecification {
$$ = $1;
TQ_ADD(&($$->modules), $2, mod_next);
}
;
/*
* ASN module definition.
* === EXAMPLE ===
* MySyntax DEFINITIONS AUTOMATIC TAGS ::=
* BEGIN
* ...
* END
* === EOF ===
*/
ModuleSpecification:
TypeRefName optObjectIdentifier TOK_DEFINITIONS
optModuleSpecificationFlags
TOK_PPEQ TOK_BEGIN
optModuleSpecificationBody
TOK_END {
if($7) {
$$ = $7;
} else {
/* There's a chance that a module is just plain empty */
$$ = asn1p_module_new();
}
checkmem($$);
$$->ModuleName = $1;
$$->module_oid = $2;
$$->module_flags = $4;
}
;
/*
* Object Identifier Definition
* { iso member-body(2) 3 }
*/
optObjectIdentifier:
{ $$ = 0; }
| ObjectIdentifier { $$ = $1; }
;
ObjectIdentifier:
'{' ObjectIdentifierBody '}' {
$$ = $2;
}
| '{' '}' {
$$ = 0;
}
;
ObjectIdentifierBody:
ObjectIdentifierElement {
$$ = asn1p_oid_new();
asn1p_oid_add_arc($$, &$1);
if($1.name)
free($1.name);
}
| ObjectIdentifierBody ObjectIdentifierElement {
$$ = $1;
asn1p_oid_add_arc($$, &$2);
if($2.name)
free($2.name);
}
;
ObjectIdentifierElement:
Identifier { /* iso */
$$.name = $1;
$$.number = -1;
}
| Identifier '(' TOK_number ')' { /* iso(1) */
$$.name = $1;
$$.number = $3;
}
| TOK_number { /* 1 */
$$.name = 0;
$$.number = $1;
}
;
/*
* Optional module flags.
*/
optModuleSpecificationFlags:
{ $$ = MSF_NOFLAGS; }
| ModuleSpecificationFlags {
$$ = $1;
}
;
/*
* Module flags.
*/
ModuleSpecificationFlags:
ModuleSpecificationFlag {
$$ = $1;
}
| ModuleSpecificationFlags ModuleSpecificationFlag {
$$ = $1 | $2;
}
;
/*
* Single module flag.
*/
ModuleSpecificationFlag:
TOK_EXPLICIT TOK_TAGS {
$$ = MSF_EXPLICIT_TAGS;
}
| TOK_IMPLICIT TOK_TAGS {
$$ = MSF_IMPLICIT_TAGS;
}
| TOK_AUTOMATIC TOK_TAGS {
$$ = MSF_AUTOMATIC_TAGS;
}
| TOK_EXTENSIBILITY TOK_IMPLIED {
$$ = MSF_EXTENSIBILITY_IMPLIED;
}
/* EncodingReferenceDefault */
| TOK_capitalreference TOK_INSTRUCTIONS {
/* X.680Amd1 specifies TAG and XER */
if(strcmp($1, "TAG") == 0) {
$$ = MSF_TAG_INSTRUCTIONS;
} else if(strcmp($1, "XER") == 0) {
$$ = MSF_XER_INSTRUCTIONS;
} else {
fprintf(stderr,
"WARNING: %s INSTRUCTIONS at line %d: "
"Unrecognized encoding reference\n",
$1, yylineno);
$$ = MSF_unk_INSTRUCTIONS;
}
free($1);
}
;
/*
* Optional module body.
*/
optModuleSpecificationBody:
{ $$ = 0; }
| ModuleSpecificationBody {
$$ = $1;
}
;
/*
* ASN.1 Module body.
*/
ModuleSpecificationBody:
ModuleSpecificationElement {
$$ = $1;
}
| ModuleSpecificationBody ModuleSpecificationElement {
$$ = $1;
/* Behave well when one of them is skipped. */
if(!($1)) {
if($2) $$ = $2;
break;
}
#ifdef MY_IMPORT
#error MY_IMPORT DEFINED ELSEWHERE!
#endif
#define MY_IMPORT(foo,field) do { \
while(TQ_FIRST(&($2->foo))) { \
TQ_ADD(&($$->foo), \
TQ_REMOVE(&($2->foo), field), \
field); \
} \
assert(TQ_FIRST(&($2->foo)) == 0); \
} while(0)
MY_IMPORT(imports, xp_next);
MY_IMPORT(exports, xp_next);
MY_IMPORT(members, next);
#undef MY_IMPORT
}
;
/*
* One of the elements of ASN.1 module specification.
*/
ModuleSpecificationElement:
ImportsDefinition {
$$ = $1;
}
| ExportsDefinition {
$$ = asn1p_module_new();
checkmem($$);
if($1) {
TQ_ADD(&($$->exports), $1, xp_next);
} else {
/* "EXPORTS ALL;" ? */
}
}
| DataTypeReference {
$$ = asn1p_module_new();
checkmem($$);
assert($1->expr_type != A1TC_INVALID);
assert($1->meta_type != AMT_INVALID);
TQ_ADD(&($$->members), $1, next);
}
| ValueDefinition {
$$ = asn1p_module_new();
checkmem($$);
assert($1->expr_type != A1TC_INVALID);
assert($1->meta_type != AMT_INVALID);
TQ_ADD(&($$->members), $1, next);
}
/*
* Value set definition
* === EXAMPLE ===
* EvenNumbers INTEGER ::= { 2 | 4 | 6 | 8 }
* === EOF ===
*/
| ValueSetDefinition {
$$ = asn1p_module_new();
checkmem($$);
assert($1->expr_type != A1TC_INVALID);
assert($1->meta_type != AMT_INVALID);
TQ_ADD(&($$->members), $1, next);
}
| TOK_ENCODING_CONTROL TOK_capitalreference
{ asn1p_lexer_hack_push_encoding_control(); }
{
fprintf(stderr,
"WARNING: ENCODING-CONTROL %s "
"specification at line %d ignored\n",
$2, yylineno);
free($2);
$$ = 0;
}
/*
* Erroneous attemps
*/
| BasicString {
return yyerror(
"Attempt to redefine a standard basic type, "
"use -ftypesXY to switch back "
"to older version of ASN.1 standard");
}
;
/*
* === EXAMPLE ===
* IMPORTS Type1, value FROM Module { iso standard(0) } ;
* === EOF ===
*/
ImportsDefinition:
TOK_IMPORTS ImportsBundleSet ';' {
if(!saved_aid && 0)
return yyerror("Unterminated IMPORTS FROM, "
"expected semicolon ';'");
saved_aid = 0;
$$ = $2;
}
/*
* Some error cases.
*/
| TOK_IMPORTS TOK_FROM /* ... */ {
return yyerror("Empty IMPORTS list");
}
;
ImportsBundleSet:
ImportsBundle {
$$ = asn1p_module_new();
checkmem($$);
TQ_ADD(&($$->imports), $1, xp_next);
}
| ImportsBundleSet ImportsBundle {
$$ = $1;
TQ_ADD(&($$->imports), $2, xp_next);
}
;
AssignedIdentifier:
{ memset(&$$, 0, sizeof($$)); }
| ObjectIdentifier { $$.oid = $1; };
/* | DefinedValue { $$.value = $1; }; // Handled through saved_aid */
ImportsBundle:
ImportsList TOK_FROM TypeRefName AssignedIdentifier {
$$ = $1;
$$->fromModuleName = $3;
$$->identifier = $4;
/* This stupid thing is used for look-back hack. */
saved_aid = $$->identifier.oid ? 0 : &($$->identifier);
checkmem($$);
}
;
ImportsList:
ImportsElement {
$$ = asn1p_xports_new();
checkmem($$);
TQ_ADD(&($$->members), $1, next);
}
| ImportsList ',' ImportsElement {
$$ = $1;
TQ_ADD(&($$->members), $3, next);
}
;
ImportsElement:
TypeRefName {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = $1;
$$->expr_type = A1TC_REFERENCE;
}
| TypeRefName '{' '}' { /* Completely equivalent to above */
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = $1;
$$->expr_type = A1TC_REFERENCE;
}
| Identifier {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = $1;
$$->expr_type = A1TC_REFERENCE;
}
;
ExportsDefinition:
TOK_EXPORTS ExportsBody ';' {
$$ = $2;
}
| TOK_EXPORTS TOK_ALL ';' {
$$ = 0;
}
| TOK_EXPORTS ';' {
/* Empty EXPORTS clause effectively prohibits export. */
$$ = asn1p_xports_new();
checkmem($$);
}
;
ExportsBody:
ExportsElement {
$$ = asn1p_xports_new();
assert($$);
TQ_ADD(&($$->members), $1, next);
}
| ExportsBody ',' ExportsElement {
$$ = $1;
TQ_ADD(&($$->members), $3, next);
}
;
ExportsElement:
TypeRefName {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = $1;
$$->expr_type = A1TC_EXPORTVAR;
}
| TypeRefName '{' '}' {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = $1;
$$->expr_type = A1TC_EXPORTVAR;
}
| Identifier {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = $1;
$$->expr_type = A1TC_EXPORTVAR;
}
;
ValueSetDefinition:
TypeRefName DefinedTypeRef TOK_PPEQ
'{' { asn1p_lexer_hack_push_opaque_state(); } Opaque /* '}' */ {
$$ = $2;
assert($$->Identifier == 0);
$$->Identifier = $1;
$$->meta_type = AMT_VALUESET;
// take care of ValueSet body
}
;
DefinedTypeRef:
ComplexTypeReference {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->reference = $1;
$$->expr_type = A1TC_REFERENCE;
$$->meta_type = AMT_TYPEREF;
}
| BasicTypeId {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->expr_type = $1;
$$->meta_type = AMT_TYPE;
}
;
/*
* Data Type Reference.
* === EXAMPLE ===
* Type3 ::= CHOICE { a Type1, b Type 2 }
* === EOF ===
*/
DataTypeReference:
/*
* Optionally tagged type definition.
*/
TypeRefName TOK_PPEQ optTag TOK_TYPE_IDENTIFIER {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = $1;
$$->tag = $3;
$$->expr_type = A1TC_TYPEID;
$$->meta_type = AMT_TYPE;
}
| TypeRefName TOK_PPEQ Type {
$$ = $3;
$$->Identifier = $1;
assert($$->expr_type);
assert($$->meta_type);
}
| TypeRefName TOK_PPEQ ClassDeclaration {
$$ = $3;
$$->Identifier = $1;
assert($$->expr_type == A1TC_CLASSDEF);
assert($$->meta_type == AMT_OBJECT);
}
/*
* Parametrized <Type> declaration:
* === EXAMPLE ===
* SIGNED { ToBeSigned } ::= SEQUENCE {
* toBeSigned ToBeSigned,
* algorithm AlgorithmIdentifier,
* signature BIT STRING
* }
* === EOF ===
*/
| TypeRefName '{' ParameterArgumentList '}' TOK_PPEQ Type {
$$ = $6;
assert($$->Identifier == 0);
$$->Identifier = $1;
$$->params = $3;
$$->meta_type = AMT_PARAMTYPE;
}
;
ParameterArgumentList:
ParameterArgumentName {
int ret;
$$ = asn1p_paramlist_new(yylineno);
checkmem($$);
ret = asn1p_paramlist_add_param($$, $1.governor, $1.argument);
checkmem(ret == 0);
if($1.governor) asn1p_ref_free($1.governor);
if($1.argument) free($1.argument);
}
| ParameterArgumentList ',' ParameterArgumentName {
int ret;
$$ = $1;
ret = asn1p_paramlist_add_param($$, $3.governor, $3.argument);
checkmem(ret == 0);
if($3.governor) asn1p_ref_free($3.governor);
if($3.argument) free($3.argument);
}
;
ParameterArgumentName:
TypeRefName {
$$.governor = NULL;
$$.argument = $1;
}
| TypeRefName ':' Identifier {
int ret;
$$.governor = asn1p_ref_new(yylineno);
ret = asn1p_ref_add_component($$.governor, $1, 0);
checkmem(ret == 0);
$$.argument = $3;
}
| TypeRefName ':' TypeRefName {
int ret;
$$.governor = asn1p_ref_new(yylineno);
ret = asn1p_ref_add_component($$.governor, $1, 0);
checkmem(ret == 0);
$$.argument = $3;
}
| BasicTypeId ':' Identifier {
int ret;
$$.governor = asn1p_ref_new(yylineno);
ret = asn1p_ref_add_component($$.governor,
ASN_EXPR_TYPE2STR($1), 1);
checkmem(ret == 0);
$$.argument = $3;
}
;
ActualParameterList:
ActualParameter {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
asn1p_expr_add($$, $1);
}
| ActualParameterList ',' ActualParameter {
$$ = $1;
asn1p_expr_add($$, $3);
}
;
ActualParameter:
Type {
$$ = $1;
}
| Identifier {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = $1;
$$->expr_type = A1TC_REFERENCE;
$$->meta_type = AMT_VALUE;
}
;
/*
| '{' ActualParameter '}' {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
asn1p_expr_add($$, $2);
$$->expr_type = A1TC_PARAMETRIZED;
$$->meta_type = AMT_TYPE;
}
;
*/
/*
* A collection of constructed data type members.
*/
optComponentTypeLists:
{ $$ = asn1p_expr_new(yylineno); }
| ComponentTypeLists { $$ = $1; };
ComponentTypeLists:
ComponentType {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
asn1p_expr_add($$, $1);
}
| ComponentTypeLists ',' ComponentType {
$$ = $1;
asn1p_expr_add($$, $3);
}
;
ComponentType:
Identifier Type optMarker {
$$ = $2;
assert($$->Identifier == 0);
$$->Identifier = $1;
$3.flags |= $$->marker.flags;
$$->marker = $3;
}
| Type optMarker {
$$ = $1;
$2.flags |= $$->marker.flags;
$$->marker = $2;
_fixup_anonymous_identifier($$);
}
| TOK_COMPONENTS TOK_OF Type {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->meta_type = $3->meta_type;
$$->expr_type = A1TC_COMPONENTS_OF;
asn1p_expr_add($$, $3);
}
| ExtensionAndException {
$$ = $1;
}
;
AlternativeTypeLists:
AlternativeType {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
asn1p_expr_add($$, $1);
}
| AlternativeTypeLists ',' AlternativeType {
$$ = $1;
asn1p_expr_add($$, $3);
}
;
AlternativeType:
Identifier Type {
$$ = $2;
assert($$->Identifier == 0);
$$->Identifier = $1;
}
| ExtensionAndException {
$$ = $1;
}
| Type {
$$ = $1;
_fixup_anonymous_identifier($$);
}
;
ClassDeclaration:
TOK_CLASS '{' ClassFieldList '}' optWithSyntax {
$$ = $3;
checkmem($$);
$$->with_syntax = $5;
assert($$->expr_type == A1TC_CLASSDEF);
assert($$->meta_type == AMT_OBJECT);
}
;
optUnique:
{ $$ = 0; }
| TOK_UNIQUE { $$ = 1; }
;
ClassFieldList:
ClassField {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->expr_type = A1TC_CLASSDEF;
$$->meta_type = AMT_OBJECT;
asn1p_expr_add($$, $1);
}
| ClassFieldList ',' ClassField {
$$ = $1;
asn1p_expr_add($$, $3);
}
;
ClassField:
ClassFieldIdentifier optMarker {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = $1.name;
$$->expr_type = A1TC_CLASSFIELD;
$$->meta_type = AMT_OBJECTFIELD;
$$->marker = $2;
}
| ClassFieldIdentifier Type optUnique optMarker {
$$ = $2;
$$->Identifier = $1.name;
$$->marker = $4;
$$->unique = $3;
}
| ClassFieldIdentifier ClassFieldIdentifier optUnique optMarker {
int ret;
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = $1.name;
$$->reference = asn1p_ref_new(yylineno);
checkmem($$->reference);
ret = asn1p_ref_add_component($$->reference,
$2.name, $2.lex_type);
checkmem(ret == 0);
$$->expr_type = A1TC_CLASSFIELD;
$$->meta_type = AMT_OBJECTFIELD;
$$->marker = $4;
$$->unique = $3;
}
;
optWithSyntax:
{ $$ = 0; }
| WithSyntax {
$$ = $1;
}
;
WithSyntax:
TOK_WITH TOK_SYNTAX '{'
{ asn1p_lexer_hack_enable_with_syntax(); }
WithSyntaxFormat
'}' {
$$ = $5;
}
;
WithSyntaxFormat:
WithSyntaxFormatToken {
$$ = asn1p_wsyntx_new();
TQ_ADD(&($$->chunks), $1, next);
}
| WithSyntaxFormat WithSyntaxFormatToken {
$$ = $1;
TQ_ADD(&($$->chunks), $2, next);
}
;
WithSyntaxFormatToken:
TOK_opaque {
$$ = asn1p_wsyntx_chunk_frombuf($1.buf, $1.len, 0);
}
| ClassFieldIdentifier {
asn1p_ref_t *ref;
int ret;
ref = asn1p_ref_new(yylineno);
checkmem(ref);
ret = asn1p_ref_add_component(ref, $1.name, $1.lex_type);
checkmem(ret == 0);
$$ = asn1p_wsyntx_chunk_fromref(ref, 0);
}
;
ExtensionAndException:
TOK_ThreeDots {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = strdup("...");
checkmem($$->Identifier);
$$->expr_type = A1TC_EXTENSIBLE;
$$->meta_type = AMT_TYPE;
}
| TOK_ThreeDots '!' DefinedValue {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = strdup("...");
checkmem($$->Identifier);
$$->value = $3;
$$->expr_type = A1TC_EXTENSIBLE;
$$->meta_type = AMT_TYPE;
}
| TOK_ThreeDots '!' SignedNumber {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = strdup("...");
$$->value = $3;
checkmem($$->Identifier);
$$->expr_type = A1TC_EXTENSIBLE;
$$->meta_type = AMT_TYPE;
}
;
Type:
optTag TypeDeclaration optConstraints {
$$ = $2;
$$->tag = $1;
/*
* Outer constraint for SEQUENCE OF and SET OF applies
* to the inner type.
*/
if($$->expr_type == ASN_CONSTR_SEQUENCE_OF
|| $$->expr_type == ASN_CONSTR_SET_OF) {
assert(!TQ_FIRST(&($$->members))->constraints);
TQ_FIRST(&($$->members))->constraints = $3;
} else {
if($$->constraints) {
assert(!$2);
} else {
$$->constraints = $3;
}
}
}
;
NSTD_IndirectMarker:
{
$$ = asn1p_as_pointer ? EM_INDIRECT : 0;
asn1p_as_pointer = 0;
}
;
TypeDeclaration:
NSTD_IndirectMarker TypeDeclarationSet {
$$ = $2;
$$->marker.flags |= $1;
if(($$->marker.flags & EM_INDIRECT)
&& ($$->marker.flags & EM_OPTIONAL) != EM_OPTIONAL) {
fprintf(stderr,
"INFO: Directive <ASN1C:RepresentAsPointer> "
"applied to %s at line %d\n",
ASN_EXPR_TYPE2STR($$->expr_type)
? ASN_EXPR_TYPE2STR($$->expr_type)
: "member",
$$->_lineno
);
}
}
;
TypeDeclarationSet:
BasicType {
$$ = $1;
}
| TOK_CHOICE '{' AlternativeTypeLists '}' {
$$ = $3;
assert($$->expr_type == A1TC_INVALID);
$$->expr_type = ASN_CONSTR_CHOICE;
$$->meta_type = AMT_TYPE;
}
| TOK_SEQUENCE '{' optComponentTypeLists '}' {
$$ = $3;
assert($$->expr_type == A1TC_INVALID);
$$->expr_type = ASN_CONSTR_SEQUENCE;
$$->meta_type = AMT_TYPE;
}
| TOK_SET '{' optComponentTypeLists '}' {
$$ = $3;
assert($$->expr_type == A1TC_INVALID);
$$->expr_type = ASN_CONSTR_SET;
$$->meta_type = AMT_TYPE;
}
| TOK_SEQUENCE optConstraints TOK_OF optIdentifier optTag TypeDeclaration {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->constraints = $2;
$$->expr_type = ASN_CONSTR_SEQUENCE_OF;
$$->meta_type = AMT_TYPE;
$6->Identifier = $4;
$6->tag = $5;
asn1p_expr_add($$, $6);
}
| TOK_SET optConstraints TOK_OF optIdentifier optTag TypeDeclaration {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->constraints = $2;
$$->expr_type = ASN_CONSTR_SET_OF;
$$->meta_type = AMT_TYPE;
$6->Identifier = $4;
$6->tag = $5;
asn1p_expr_add($$, $6);
}
| TOK_ANY {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->expr_type = ASN_TYPE_ANY;
$$->meta_type = AMT_TYPE;
}
| TOK_ANY TOK_DEFINED TOK_BY Identifier {
int ret;
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->reference = asn1p_ref_new(yylineno);
ret = asn1p_ref_add_component($$->reference,
$4, RLT_lowercase);
checkmem(ret == 0);
$$->expr_type = ASN_TYPE_ANY;
$$->meta_type = AMT_TYPE;
}
/*
* A parametrized assignment.
*/
| TypeRefName '{' ActualParameterList '}' {
int ret;
$$ = $3;
assert($$->expr_type == 0);
assert($$->meta_type == 0);
assert($$->reference == 0);
$$->reference = asn1p_ref_new(yylineno);
checkmem($$->reference);
ret = asn1p_ref_add_component($$->reference, $1, RLT_UNKNOWN);
checkmem(ret == 0);
free($1);
$$->expr_type = A1TC_PARAMETRIZED;
$$->meta_type = AMT_TYPE;
}
/*
* A DefinedType reference.
* "CLASS1.&id.&id2"
* or
* "Module.Type"
* or
* "Module.identifier"
* or
* "Type"
*/
| ComplexTypeReference {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->reference = $1;
$$->expr_type = A1TC_REFERENCE;
$$->meta_type = AMT_TYPEREF;
}
| TOK_INSTANCE TOK_OF ComplexTypeReference {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->reference = $3;
$$->expr_type = A1TC_INSTANCE;
$$->meta_type = AMT_TYPE;
}
;
/*
* A type name consisting of several components.
* === EXAMPLE ===
* === EOF ===
*/
ComplexTypeReference:
TOK_typereference {
int ret;
$$ = asn1p_ref_new(yylineno);
checkmem($$);
ret = asn1p_ref_add_component($$, $1, RLT_UNKNOWN);
checkmem(ret == 0);
free($1);
}
| TOK_typereference '.' TypeRefName {
int ret;
$$ = asn1p_ref_new(yylineno);
checkmem($$);
ret = asn1p_ref_add_component($$, $1, RLT_UNKNOWN);
checkmem(ret == 0);
ret = asn1p_ref_add_component($$, $3, RLT_UNKNOWN);
checkmem(ret == 0);
free($1);
}
| ObjectClassReference '.' TypeRefName {
int ret;
$$ = asn1p_ref_new(yylineno);
checkmem($$);
ret = asn1p_ref_add_component($$, $1, RLT_UNKNOWN);
checkmem(ret == 0);
ret = asn1p_ref_add_component($$, $3, RLT_UNKNOWN);
checkmem(ret == 0);
free($1);
}
| TOK_typereference '.' Identifier {
int ret;
$$ = asn1p_ref_new(yylineno);
checkmem($$);
ret = asn1p_ref_add_component($$, $1, RLT_UNKNOWN);
checkmem(ret == 0);
ret = asn1p_ref_add_component($$, $3, RLT_lowercase);
checkmem(ret == 0);
free($1);
}
| ObjectClassReference {
int ret;
$$ = asn1p_ref_new(yylineno);
checkmem($$);
ret = asn1p_ref_add_component($$, $1, RLT_CAPITALS);
free($1);
checkmem(ret == 0);
}
| ObjectClassReference '.' ComplexTypeReferenceAmpList {
int ret;
$$ = $3;
ret = asn1p_ref_add_component($$, $1, RLT_CAPITALS);
free($1);
checkmem(ret == 0);
/*
* Move the last element infront.
*/
{
struct asn1p_ref_component_s tmp_comp;
tmp_comp = $$->components[$$->comp_count-1];
memmove(&$$->components[1],
&$$->components[0],
sizeof($$->components[0])
* ($$->comp_count - 1));
$$->components[0] = tmp_comp;
}
}
;
ComplexTypeReferenceAmpList:
ComplexTypeReferenceElement {
int ret;
$$ = asn1p_ref_new(yylineno);
checkmem($$);
ret = asn1p_ref_add_component($$, $1.name, $1.lex_type);
free($1.name);
checkmem(ret == 0);
}
| ComplexTypeReferenceAmpList '.' ComplexTypeReferenceElement {
int ret;
$$ = $1;
ret = asn1p_ref_add_component($$, $3.name, $3.lex_type);
free($3.name);
checkmem(ret == 0);
}
;
ComplexTypeReferenceElement: ClassFieldName;
ClassFieldIdentifier: ClassFieldName;
ClassFieldName:
/* "&Type1" */
TOK_typefieldreference {
$$.lex_type = RLT_AmpUppercase;
$$.name = $1;
}
/* "&id" */
| TOK_valuefieldreference {
$$.lex_type = RLT_Amplowercase;
$$.name = $1;
}
;
/*
* === EXAMPLE ===
* value INTEGER ::= 1
* === EOF ===
*/
ValueDefinition:
Identifier DefinedTypeRef TOK_PPEQ Value {
$$ = $2;
assert($$->Identifier == NULL);
$$->Identifier = $1;
$$->meta_type = AMT_VALUE;
$$->value = $4;
}
;
Value:
Identifier ':' Value {
$$ = asn1p_value_fromint(0);
checkmem($$);
$$->type = ATV_CHOICE_IDENTIFIER;
$$->value.choice_identifier.identifier = $1;
$$->value.choice_identifier.value = $3;
}
| '{' { asn1p_lexer_hack_push_opaque_state(); } Opaque /* '}' */ {
$$ = asn1p_value_frombuf($3.buf, $3.len, 0);
checkmem($$);
$$->type = ATV_UNPARSED;
}
| TOK_NULL {
$$ = asn1p_value_fromint(0);
checkmem($$);
$$->type = ATV_NULL;
}
| TOK_FALSE {
$$ = asn1p_value_fromint(0);
checkmem($$);
$$->type = ATV_FALSE;
}
| TOK_TRUE {
$$ = asn1p_value_fromint(0);
checkmem($$);
$$->type = ATV_TRUE;
}
| TOK_bstring {
$$ = _convert_bitstring2binary($1, 'B');
checkmem($$);
}
| TOK_hstring {
$$ = _convert_bitstring2binary($1, 'H');
checkmem($$);
}
| RestrictedCharacterStringValue {
$$ = $$;
}
| SignedNumber {
$$ = $1;
}
| DefinedValue {
$$ = $1;
}
;
DefinedValue:
Identifier {
asn1p_ref_t *ref;
int ret;
ref = asn1p_ref_new(yylineno);
checkmem(ref);
ret = asn1p_ref_add_component(ref, $1, RLT_lowercase);
checkmem(ret == 0);
$$ = asn1p_value_fromref(ref, 0);
checkmem($$);
free($1);
}
| TypeRefName '.' Identifier {
asn1p_ref_t *ref;
int ret;
ref = asn1p_ref_new(yylineno);
checkmem(ref);
ret = asn1p_ref_add_component(ref, $1, RLT_UNKNOWN);
checkmem(ret == 0);
ret = asn1p_ref_add_component(ref, $3, RLT_lowercase);
checkmem(ret == 0);
$$ = asn1p_value_fromref(ref, 0);
checkmem($$);
free($1);
free($3);
}
;
RestrictedCharacterStringValue:
TOK_cstring {
$$ = asn1p_value_frombuf($1.buf, $1.len, 0);
checkmem($$);
}
| TOK_tuple {
$$ = asn1p_value_fromint($1);
checkmem($$);
$$->type = ATV_TUPLE;
}
| TOK_quadruple {
$$ = asn1p_value_fromint($1);
checkmem($$);
$$->type = ATV_QUADRUPLE;
}
/*
| '{' TOK_number ',' TOK_number '}' {
asn1c_integer_t v = ($2 << 4) + $4;
if($2 > 7) return yyerror("X.680:2003, #37.14 "
"mandates 0..7 range for Tuple's TableColumn");
if($4 > 15) return yyerror("X.680:2003, #37.14 "
"mandates 0..15 range for Tuple's TableRow");
$$ = asn1p_value_fromint(v);
checkmem($$);
$$->type = ATV_TUPLE;
}
| '{' TOK_number ',' TOK_number ',' TOK_number ',' TOK_number '}' {
asn1c_integer_t v = ($2 << 24) | ($4 << 16) | ($6 << 8) | $8;
if($2 > 127) return yyerror("X.680:2003, #37.12 "
"mandates 0..127 range for Quadruple's Group");
if($4 > 255) return yyerror("X.680:2003, #37.12 "
"mandates 0..255 range for Quadruple's Plane");
if($6 > 255) return yyerror("X.680:2003, #37.12 "
"mandates 0..255 range for Quadruple's Row");
if($8 > 255) return yyerror("X.680:2003, #37.12 "
"mandates 0..255 range for Quadruple's Cell");
$$ = asn1p_value_fromint(v);
checkmem($$);
$$->type = ATV_QUADRUPLE;
}
*/
;
Opaque:
TOK_opaque {
$$.len = $1.len + 1;
$$.buf = malloc($$.len + 1);
checkmem($$.buf);
$$.buf[0] = '{';
memcpy($$.buf + 1, $1.buf, $1.len);
$$.buf[$$.len] = '\0';
free($1.buf);
}
| Opaque TOK_opaque {
int newsize = $1.len + $2.len;
char *p = malloc(newsize + 1);
checkmem(p);
memcpy(p , $1.buf, $1.len);
memcpy(p + $1.len, $2.buf, $2.len);
p[newsize] = '\0';
free($1.buf);
free($2.buf);
$$.buf = p;
$$.len = newsize;
}
;
BasicTypeId:
TOK_BOOLEAN { $$ = ASN_BASIC_BOOLEAN; }
| TOK_NULL { $$ = ASN_BASIC_NULL; }
| TOK_REAL { $$ = ASN_BASIC_REAL; }
| BasicTypeId_UniverationCompatible { $$ = $1; }
| TOK_OCTET TOK_STRING { $$ = ASN_BASIC_OCTET_STRING; }
| TOK_OBJECT TOK_IDENTIFIER { $$ = ASN_BASIC_OBJECT_IDENTIFIER; }
| TOK_RELATIVE_OID { $$ = ASN_BASIC_RELATIVE_OID; }
| TOK_EXTERNAL { $$ = ASN_BASIC_EXTERNAL; }
| TOK_EMBEDDED TOK_PDV { $$ = ASN_BASIC_EMBEDDED_PDV; }
| TOK_CHARACTER TOK_STRING { $$ = ASN_BASIC_CHARACTER_STRING; }
| TOK_UTCTime { $$ = ASN_BASIC_UTCTime; }
| TOK_GeneralizedTime { $$ = ASN_BASIC_GeneralizedTime; }
| BasicString { $$ = $1; }
;
/*
* A type identifier which may be used with "{ a(1), b(2) }" clause.
*/
BasicTypeId_UniverationCompatible:
TOK_INTEGER { $$ = ASN_BASIC_INTEGER; }
| TOK_ENUMERATED { $$ = ASN_BASIC_ENUMERATED; }
| TOK_BIT TOK_STRING { $$ = ASN_BASIC_BIT_STRING; }
;
BasicType:
BasicTypeId {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->expr_type = $1;
$$->meta_type = AMT_TYPE;
}
| BasicTypeId_UniverationCompatible UniverationDefinition {
if($2) {
$$ = $2;
} else {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
}
$$->expr_type = $1;
$$->meta_type = AMT_TYPE;
}
;
BasicString:
TOK_BMPString { $$ = ASN_STRING_BMPString; }
| TOK_GeneralString {
$$ = ASN_STRING_GeneralString;
fprintf(stderr, "WARNING: GeneralString is not fully supported\n");
}
| TOK_GraphicString {
$$ = ASN_STRING_GraphicString;
fprintf(stderr, "WARNING: GraphicString is not fully supported\n");
}
| TOK_IA5String { $$ = ASN_STRING_IA5String; }
| TOK_ISO646String { $$ = ASN_STRING_ISO646String; }
| TOK_NumericString { $$ = ASN_STRING_NumericString; }
| TOK_PrintableString { $$ = ASN_STRING_PrintableString; }
| TOK_T61String {
$$ = ASN_STRING_T61String;
fprintf(stderr, "WARNING: T61String is not fully supported\n");
}
| TOK_TeletexString { $$ = ASN_STRING_TeletexString; }
| TOK_UniversalString { $$ = ASN_STRING_UniversalString; }
| TOK_UTF8String { $$ = ASN_STRING_UTF8String; }
| TOK_VideotexString {
$$ = ASN_STRING_VideotexString;
fprintf(stderr, "WARNING: VideotexString is not fully supported\n");
}
| TOK_VisibleString { $$ = ASN_STRING_VisibleString; }
| TOK_ObjectDescriptor { $$ = ASN_STRING_ObjectDescriptor; }
;
/*
* Data type constraints.
*/
Union: '|' | TOK_UNION;
Intersection: '^' | TOK_INTERSECTION;
Except: TOK_EXCEPT;
optConstraints:
{ $$ = 0; }
| Constraints {
$$ = $1;
}
;
Constraints:
SetOfConstraints {
CONSTRAINT_INSERT($$, ACT_CA_SET, $1, 0);
}
| TOK_SIZE '(' ElementSetSpecs ')' {
/*
* This is a special case, for compatibility purposes.
* It goes without parentheses.
*/
CONSTRAINT_INSERT($$, ACT_CT_SIZE, $3, 0);
}
;
SetOfConstraints:
'(' ElementSetSpecs ')' {
$$ = $2;
}
| SetOfConstraints '(' ElementSetSpecs ')' {
CONSTRAINT_INSERT($$, ACT_CA_SET, $1, $3);
}
;
ElementSetSpecs:
ElementSetSpec {
$$ = $1;
}
| ElementSetSpec ',' TOK_ThreeDots {
asn1p_constraint_t *ct;
ct = asn1p_constraint_new(yylineno);
ct->type = ACT_EL_EXT;
CONSTRAINT_INSERT($$, ACT_CA_CSV, $1, ct);
}
| ElementSetSpec ',' TOK_ThreeDots ',' ElementSetSpec {
asn1p_constraint_t *ct;
ct = asn1p_constraint_new(yylineno);
ct->type = ACT_EL_EXT;
CONSTRAINT_INSERT($$, ACT_CA_CSV, $1, ct);
ct = $$;
CONSTRAINT_INSERT($$, ACT_CA_CSV, ct, $5);
}
;
ElementSetSpec:
ConstraintSubtypeElement {
$$ = $1;
}
| TOK_ALL TOK_EXCEPT ConstraintSubtypeElement {
CONSTRAINT_INSERT($$, ACT_CA_AEX, $3, 0);
}
| ElementSetSpec Union ConstraintSubtypeElement {
CONSTRAINT_INSERT($$, ACT_CA_UNI, $1, $3);
}
| ElementSetSpec Intersection ConstraintSubtypeElement {
CONSTRAINT_INSERT($$, ACT_CA_INT, $1, $3);
}
| ConstraintSubtypeElement Except ConstraintSubtypeElement {
CONSTRAINT_INSERT($$, ACT_CA_EXC, $1, $3);
}
;
ConstraintSubtypeElement:
ConstraintSpec '(' ElementSetSpecs ')' {
int ret;
$$ = asn1p_constraint_new(yylineno);
checkmem($$);
$$->type = $1;
ret = asn1p_constraint_insert($$, $3);
checkmem(ret == 0);
}
| '(' ElementSetSpecs ')' {
int ret;
$$ = asn1p_constraint_new(yylineno);
checkmem($$);
$$->type = ACT_CA_SET;
ret = asn1p_constraint_insert($$, $2);
checkmem(ret == 0);
}
| SingleValue {
$$ = asn1p_constraint_new(yylineno);
checkmem($$);
$$->type = ACT_EL_VALUE;
$$->value = $1;
}
| ContainedSubtype {
$$ = asn1p_constraint_new(yylineno);
checkmem($$);
$$->type = ACT_EL_TYPE;
$$->containedSubtype = $1;
}
| SingleValue ConstraintRangeSpec SingleValue {
$$ = asn1p_constraint_new(yylineno);
checkmem($$);
$$->type = $2;
$$->range_start = $1;
$$->range_stop = $3;
}
| TOK_MIN ConstraintRangeSpec SingleValue {
$$ = asn1p_constraint_new(yylineno);
checkmem($$);
$$->type = $2;
$$->range_start = asn1p_value_fromint(-123);
$$->range_stop = $3;
$$->range_start->type = ATV_MIN;
}
| SingleValue ConstraintRangeSpec TOK_MAX {
$$ = asn1p_constraint_new(yylineno);
checkmem($$);
$$->type = $2;
$$->range_start = $1;
$$->range_stop = asn1p_value_fromint(321);
$$->range_stop->type = ATV_MAX;
}
| TOK_MIN ConstraintRangeSpec TOK_MAX {
$$ = asn1p_constraint_new(yylineno);
checkmem($$);
$$->type = $2;
$$->range_start = asn1p_value_fromint(-123);
$$->range_stop = asn1p_value_fromint(321);
$$->range_start->type = ATV_MIN;
$$->range_stop->type = ATV_MAX;
}
| TableConstraint {
$$ = $1;
}
| InnerTypeConstraint {
$$ = $1;
}
| TOK_CONSTRAINED TOK_BY '{'
{ asn1p_lexer_hack_push_opaque_state(); } Opaque /* '}' */ {
$$ = asn1p_constraint_new(yylineno);
checkmem($$);
$$->type = ACT_CT_CTDBY;
$$->value = asn1p_value_frombuf($5.buf, $5.len, 0);
checkmem($$->value);
$$->value->type = ATV_UNPARSED;
}
;
ConstraintRangeSpec:
TOK_TwoDots { $$ = ACT_EL_RANGE; }
| TOK_TwoDots '<' { $$ = ACT_EL_RLRANGE; }
| '<' TOK_TwoDots { $$ = ACT_EL_LLRANGE; }
| '<' TOK_TwoDots '<' { $$ = ACT_EL_ULRANGE; }
;
ConstraintSpec:
TOK_SIZE {
$$ = ACT_CT_SIZE;
}
| TOK_FROM {
$$ = ACT_CT_FROM;
}
;
SingleValue:
TOK_FALSE {
$$ = asn1p_value_fromint(0);
checkmem($$);
$$->type = ATV_FALSE;
}
| TOK_TRUE {
$$ = asn1p_value_fromint(1);
checkmem($$);
$$->type = ATV_TRUE;
}
| SignedNumber {
$$ = $1;
}
| RestrictedCharacterStringValue {
$$ = $1;
}
| Identifier {
asn1p_ref_t *ref;
int ret;
ref = asn1p_ref_new(yylineno);
checkmem(ref);
ret = asn1p_ref_add_component(ref, $1, RLT_lowercase);
checkmem(ret == 0);
$$ = asn1p_value_fromref(ref, 0);
checkmem($$);
free($1);
}
;
ContainedSubtype:
TypeRefName {
asn1p_ref_t *ref;
int ret;
ref = asn1p_ref_new(yylineno);
checkmem(ref);
ret = asn1p_ref_add_component(ref, $1, RLT_UNKNOWN);
checkmem(ret == 0);
$$ = asn1p_value_fromref(ref, 0);
checkmem($$);
free($1);
}
;
InnerTypeConstraint:
TOK_WITH TOK_COMPONENT SetOfConstraints {
CONSTRAINT_INSERT($$, ACT_CT_WCOMP, $3, 0);
}
| TOK_WITH TOK_COMPONENTS '{' WithComponentsList '}' {
CONSTRAINT_INSERT($$, ACT_CT_WCOMPS, $4, 0);
}
;
WithComponentsList:
WithComponentsElement {
$$ = $1;
}
| WithComponentsList ',' WithComponentsElement {
CONSTRAINT_INSERT($$, ACT_CT_WCOMPS, $1, $3);
}
;
WithComponentsElement:
TOK_ThreeDots {
$$ = asn1p_constraint_new(yylineno);
checkmem($$);
$$->type = ACT_EL_EXT;
$$->value = asn1p_value_frombuf("...", 3, 0);
}
| Identifier optConstraints optPresenceConstraint {
$$ = asn1p_constraint_new(yylineno);
checkmem($$);
$$->type = ACT_EL_VALUE;
$$->value = asn1p_value_frombuf($1, strlen($1), 0);
$$->presence = $3;
if($2) asn1p_constraint_insert($$, $2);
}
;
/*
* presence constraint for WithComponents
*/
optPresenceConstraint:
{ $$ = ACPRES_DEFAULT; }
| PresenceConstraint { $$ = $1; }
;
PresenceConstraint:
TOK_PRESENT {
$$ = ACPRES_PRESENT;
}
| TOK_ABSENT {
$$ = ACPRES_ABSENT;
}
| TOK_OPTIONAL {
$$ = ACPRES_OPTIONAL;
}
;
TableConstraint:
SimpleTableConstraint {
$$ = $1;
}
| ComponentRelationConstraint {
$$ = $1;
}
;
/*
* "{ExtensionSet}"
*/
SimpleTableConstraint:
'{' TypeRefName '}' {
asn1p_ref_t *ref = asn1p_ref_new(yylineno);
asn1p_constraint_t *ct;
int ret;
ret = asn1p_ref_add_component(ref, $2, 0);
checkmem(ret == 0);
ct = asn1p_constraint_new(yylineno);
checkmem($$);
ct->type = ACT_EL_VALUE;
ct->value = asn1p_value_fromref(ref, 0);
CONSTRAINT_INSERT($$, ACT_CA_CRC, ct, 0);
}
;
ComponentRelationConstraint:
SimpleTableConstraint '{' AtNotationList '}' {
CONSTRAINT_INSERT($$, ACT_CA_CRC, $1, $3);
}
;
AtNotationList:
AtNotationElement {
$$ = asn1p_constraint_new(yylineno);
checkmem($$);
$$->type = ACT_EL_VALUE;
$$->value = asn1p_value_fromref($1, 0);
}
| AtNotationList ',' AtNotationElement {
asn1p_constraint_t *ct;
ct = asn1p_constraint_new(yylineno);
checkmem(ct);
ct->type = ACT_EL_VALUE;
ct->value = asn1p_value_fromref($3, 0);
CONSTRAINT_INSERT($$, ACT_CA_CSV, $1, ct);
}
;
/*
* @blah
*/
AtNotationElement:
'@' ComponentIdList {
char *p = malloc(strlen($2) + 2);
int ret;
*p = '@';
strcpy(p + 1, $2);
$$ = asn1p_ref_new(yylineno);
ret = asn1p_ref_add_component($$, p, 0);
checkmem(ret == 0);
free(p);
free($2);
}
| '@' '.' ComponentIdList {
char *p = malloc(strlen($3) + 3);
int ret;
p[0] = '@';
p[1] = '.';
strcpy(p + 2, $3);
$$ = asn1p_ref_new(yylineno);
ret = asn1p_ref_add_component($$, p, 0);
checkmem(ret == 0);
free(p);
free($3);
}
;
/* identifier "." ... */
ComponentIdList:
Identifier {
$$ = $1;
}
| ComponentIdList '.' Identifier {
int l1 = strlen($1);
int l3 = strlen($3);
$$ = malloc(l1 + 1 + l3 + 1);
memcpy($$, $1, l1);
$$[l1] = '.';
memcpy($$ + l1 + 1, $3, l3);
$$[l1 + 1 + l3] = '\0';
}
;
/*
* MARKERS
*/
optMarker:
{
$$.flags = EM_NOMARK;
$$.default_value = 0;
}
| Marker { $$ = $1; }
;
Marker:
TOK_OPTIONAL {
$$.flags = EM_OPTIONAL;
$$.default_value = 0;
}
| TOK_DEFAULT Value {
$$.flags = EM_DEFAULT;
$$.default_value = $2;
}
;
/*
* Universal enumeration definition to use in INTEGER and ENUMERATED.
* === EXAMPLE ===
* Gender ::= ENUMERATED { unknown(0), male(1), female(2) }
* Temperature ::= INTEGER { absolute-zero(-273), freezing(0), boiling(100) }
* === EOF ===
*/
/*
optUniverationDefinition:
{ $$ = 0; }
| UniverationDefinition {
$$ = $1;
}
;
*/
UniverationDefinition:
'{' '}' {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
}
| '{' UniverationList '}' {
$$ = $2;
}
;
UniverationList:
UniverationElement {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
asn1p_expr_add($$, $1);
}
| UniverationList ',' UniverationElement {
$$ = $1;
asn1p_expr_add($$, $3);
}
;
UniverationElement:
Identifier {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->expr_type = A1TC_UNIVERVAL;
$$->meta_type = AMT_VALUE;
$$->Identifier = $1;
}
| Identifier '(' SignedNumber ')' {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->expr_type = A1TC_UNIVERVAL;
$$->meta_type = AMT_VALUE;
$$->Identifier = $1;
$$->value = $3;
}
| Identifier '(' DefinedValue ')' {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->expr_type = A1TC_UNIVERVAL;
$$->meta_type = AMT_VALUE;
$$->Identifier = $1;
$$->value = $3;
}
| SignedNumber {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->expr_type = A1TC_UNIVERVAL;
$$->meta_type = AMT_VALUE;
$$->value = $1;
}
| TOK_ThreeDots {
$$ = asn1p_expr_new(yylineno);
checkmem($$);
$$->Identifier = strdup("...");
checkmem($$->Identifier);
$$->expr_type = A1TC_EXTENSIBLE;
$$->meta_type = AMT_VALUE;
}
;
SignedNumber:
TOK_number {
$$ = asn1p_value_fromint($1);
checkmem($$);
}
| TOK_number_negative {
$$ = asn1p_value_fromint($1);
checkmem($$);
}
;
/*
* SEQUENCE definition.
* === EXAMPLE ===
* Struct1 ::= SEQUENCE {
* memb1 Struct2,
* memb2 SEQUENCE OF {
* memb2-1 Struct 3
* }
* }
* === EOF ===
*/
/*
* SET definition.
* === EXAMPLE ===
* Person ::= SET {
* name [0] PrintableString (SIZE(1..20)),
* country [1] PrintableString (SIZE(1..20)) DEFAULT default-country,
* }
* === EOF ===
*/
optTag:
{ memset(&$$, 0, sizeof($$)); }
| Tag { $$ = $1; }
;
Tag:
TagTypeValue TagPlicit {
$$ = $1;
$$.tag_mode = $2.tag_mode;
}
;
TagTypeValue:
'[' TagClass TOK_number ']' {
$$ = $2;
$$.tag_value = $3;
};
TagClass:
{ $$.tag_class = TC_CONTEXT_SPECIFIC; }
| TOK_UNIVERSAL { $$.tag_class = TC_UNIVERSAL; }
| TOK_APPLICATION { $$.tag_class = TC_APPLICATION; }
| TOK_PRIVATE { $$.tag_class = TC_PRIVATE; }
;
TagPlicit:
{ $$.tag_mode = TM_DEFAULT; }
| TOK_IMPLICIT { $$.tag_mode = TM_IMPLICIT; }
| TOK_EXPLICIT { $$.tag_mode = TM_EXPLICIT; }
;
TypeRefName:
TOK_typereference {
checkmem($1);
$$ = $1;
}
| TOK_capitalreference {
checkmem($1);
$$ = $1;
}
;
ObjectClassReference:
TOK_capitalreference {
checkmem($1);
$$ = $1;
}
;
optIdentifier:
{ $$ = 0; }
| Identifier {
$$ = $1;
}
;
Identifier:
TOK_identifier {
checkmem($1);
$$ = $1;
}
;
%%
/*
* Convert Xstring ('0101'B or '5'H) to the binary vector.
*/
static asn1p_value_t *
_convert_bitstring2binary(char *str, int base) {
asn1p_value_t *val;
int slen;
int memlen;
int baselen;
int bits;
uint8_t *binary_vector;
uint8_t *bv_ptr;
uint8_t cur_val;
assert(str);
assert(str[0] == '\'');
switch(base) {
case 'B':
baselen = 1;
break;
case 'H':
baselen = 4;
break;
default:
assert(base == 'B' || base == 'H');
errno = EINVAL;
return NULL;
}
slen = strlen(str);
assert(str[slen - 1] == base);
assert(str[slen - 2] == '\'');
memlen = slen / (8 / baselen); /* Conservative estimate */
bv_ptr = binary_vector = malloc(memlen + 1);
if(bv_ptr == NULL)
/* ENOMEM */
return NULL;
cur_val = 0;
bits = 0;
while(*(++str) != '\'') {
switch(baselen) {
case 1:
switch(*str) {
case '1':
cur_val |= 1 << (7 - (bits % 8));
case '0':
break;
default:
assert(!"_y UNREACH1");
case ' ': case '\r': case '\n':
continue;
}
break;
case 4:
switch(*str) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
cur_val |= (*str - '0') << (4 - (bits % 8));
break;
case 'A': case 'B': case 'C':
case 'D': case 'E': case 'F':
cur_val |= ((*str - 'A') + 10)
<< (4 - (bits % 8));
break;
default:
assert(!"_y UNREACH2");
case ' ': case '\r': case '\n':
continue;
}
break;
}
bits += baselen;
if((bits % 8) == 0) {
*bv_ptr++ = cur_val;
cur_val = 0;
}
}
*bv_ptr = cur_val;
assert((bv_ptr - binary_vector) <= memlen);
val = asn1p_value_frombits(binary_vector, bits, 0);
if(val == NULL) {
free(binary_vector);
}
return val;
}
/*
* For unnamed types (used in old X.208 compliant modules)
* generate some sort of interim names, to not to force human being to fix
* the specification's compliance to modern ASN.1 standards.
*/
static void
_fixup_anonymous_identifier(asn1p_expr_t *expr) {
char *p;
assert(expr->Identifier == 0);
/*
* Try to figure out the type name
* without going too much into details
*/
expr->Identifier = ASN_EXPR_TYPE2STR(expr->expr_type);
if(expr->reference && expr->reference->comp_count > 0)
expr->Identifier = expr->reference->components[0].name;
fprintf(stderr,
"WARNING: Line %d: expected lower-case member identifier, "
"found an unnamed %s.\n"
"WARNING: Obsolete X.208 syntax detected, "
"please give the member a name.\n",
yylineno, expr->Identifier ? expr->Identifier : "type");
if(!expr->Identifier)
expr->Identifier = "unnamed";
expr->Identifier = strdup(expr->Identifier);
assert(expr->Identifier);
/* Make a lowercase identifier from the type name */
for(p = expr->Identifier; *p; p++) {
switch(*p) {
case 'A' ... 'Z': *p += 32; break;
case ' ': *p = '_'; break;
case '-': *p = '_'; break;
}
}
fprintf(stderr, "NOTE: Assigning temporary identifier \"%s\". "
"Name clash may occur later.\n",
expr->Identifier);
}
extern char *asn1p_text;
int
yyerror(const char *msg) {
fprintf(stderr,
"ASN.1 grammar parse error "
"near line %d (token \"%s\"): %s\n",
yylineno, asn1p_text, msg);
return -1;
}