blob: c63b40f24d4585be60ca561871eb8de310337272 [file] [log] [blame]
%{
/*
* Copyright (C) 2001-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
* The LIBTASN1 library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
/*****************************************************/
/* File: x509_ASN.y */
/* Description: input file for 'bison' program. */
/* The output file is a parser (in C language) for */
/* ASN.1 syntax */
/*****************************************************/
#include <int.h>
#include <parser_aux.h>
#include <structure.h>
#include <libtasn1.h>
#include "c-ctype.h"
static list_type *e_list = NULL;
static FILE *file_asn1; /* Pointer to file to parse */
static int result_parse = 0; /* result of the parser
algorithm */
static asn1_node p_tree; /* pointer to the root of the
structure created by the
parser*/
static unsigned int line_number; /* line number describing the
parser position inside the
file */
static char last_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = "";
static char last_error_token[ASN1_MAX_ERROR_DESCRIPTION_SIZE+1] = ""; /* used when expected errors occur */
static char last_token[ASN1_MAX_NAME_SIZE+1] = ""; /* last token find in the file
to parse before the 'parse
error' */
extern char _asn1_identifierMissing[];
static const char *file_name; /* file to parse */
static void _asn1_yyerror (const char *);
static int _asn1_yylex(void);
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
#define SAFE_COPY(dst, dst_size, fmt, ...) { snprintf(dst, dst_size, fmt, __VA_ARGS__); }
#else
#define SAFE_COPY(dst, dst_size, fmt, ...) { \
int _ret = snprintf(dst, dst_size, fmt, __VA_ARGS__); \
if (_ret != (int)strlen(dst)) \
{ \
fprintf(stderr, "%s:%u: Oversize value\n", \
file_name, line_number); \
exit(1); \
} \
}
#endif
%}
/* Prefix symbols and functions with _asn1_ */
/* %define parse.lac full */
%define parse.error verbose
%define api.prefix {_asn1_yy}
%union {
unsigned int constant;
char str[ASN1_MAX_NAME_SIZE+1];
asn1_node node;
}
%token ASSIG "::="
%token <str> NUM
%token <str> IDENTIFIER
%token OPTIONAL
%token INTEGER
%token SIZE
%token OCTET
%token STRING
%token SEQUENCE
%token BIT
%token UNIVERSAL
%token PRIVATE
%token APPLICATION
%token DEFAULT
%token CHOICE
%token OF
%token OBJECT
%token STR_IDENTIFIER
%token BOOLEAN
%token ASN1_TRUE
%token ASN1_FALSE
%token TOKEN_NULL
%token ANY
%token DEFINED
%token BY
%token SET
%token EXPLICIT
%token IMPLICIT
%token DEFINITIONS
%token TAGS
%token BEGIN
%token END
%token UTCTime
%token GeneralizedTime
%token GeneralString
%token NumericString
%token IA5String
%token TeletexString
%token PrintableString
%token UniversalString
%token BMPString
%token UTF8String
%token VisibleString
%token FROM
%token IMPORTS
%token ENUMERATED
%type <node> octet_string_def constant constant_list type_assig_right
%type <node> integer_def type_assig type_assig_list sequence_def type_def
%type <node> bit_string_def default size_def choise_def object_def
%type <node> boolean_def any_def size_def2 obj_constant obj_constant_list
%type <node> constant_def type_constant type_constant_list definitions
%type <node> definitions_id Time bit_element bit_element_list set_def
%type <node> tag_type tag type_assig_right_tag generalstring_def
%type <node> numericstring_def ia5string_def printablestring_def universalstring_def
%type <node> bmpstring_def utf8string_def visiblestring_def teletexstring_def
%type <node> type_assig_right_tag_default enumerated_def
%type <str> pos_num neg_num pos_neg_num pos_neg_identifier pos_neg_list
%type <str> num_identifier
%type <str> int_identifier
%type <constant> class explicit_implicit
%type <str> known_string
%%
definitions: definitions_id
DEFINITIONS explicit_implicit TAGS "::=" BEGIN /* imports_def */
type_constant_list END
{$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_DEFINITIONS|$3);
_asn1_set_name($$,_asn1_get_name($1));
_asn1_set_name($1,"");
_asn1_set_right($1,$7);
_asn1_set_down($$,$1);
p_tree=$$;
}
;
pos_num : NUM {snprintf($$,sizeof($$),"%s",$1);}
| '+' NUM {snprintf($$,sizeof($$),"%s",$2);}
;
neg_num : '-' NUM {SAFE_COPY($$,sizeof($$),"-%s",$2);}
;
pos_neg_num : pos_num {snprintf($$,sizeof($$),"%s",$1);}
| neg_num {snprintf($$,sizeof($$),"%s",$1);}
;
num_identifier : NUM {snprintf($$,sizeof($$),"%s",$1);}
| IDENTIFIER {snprintf($$,sizeof($$),"%s",$1);}
;
int_identifier : NUM {snprintf($$,sizeof($$),"%s",$1);}
| '-' NUM {SAFE_COPY($$,sizeof($$),"-%s",$2);}
| IDENTIFIER {snprintf($$,sizeof($$),"%s",$1);}
;
pos_neg_identifier : pos_neg_num {snprintf($$,sizeof($$),"%s",$1);}
| IDENTIFIER {snprintf($$,sizeof($$),"%s",$1);}
;
constant: '(' pos_neg_num ')' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_CONSTANT);
_asn1_set_value($$,$2,strlen($2)+1);}
| IDENTIFIER'('pos_neg_num')' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_CONSTANT);
_asn1_set_name($$,$1);
_asn1_set_value($$,$3,strlen($3)+1);}
;
constant_list: constant {$$=$1;}
| constant_list ',' constant {$$=$1;
_asn1_set_right(_asn1_get_last_right($1),$3);}
;
obj_constant: num_identifier {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_CONSTANT);
_asn1_set_value($$,$1,strlen($1)+1);}
| IDENTIFIER'('NUM')' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_CONSTANT);
_asn1_set_name($$,$1);
_asn1_set_value($$,$3,strlen($3)+1);}
;
obj_constant_list: obj_constant {$$=$1;}
| obj_constant_list obj_constant {$$=$1;
_asn1_set_right(_asn1_get_last_right($1),$2);}
;
class : UNIVERSAL {$$=CONST_UNIVERSAL;}
| PRIVATE {$$=CONST_PRIVATE;}
| APPLICATION {$$=CONST_APPLICATION;}
;
tag_type : '[' NUM ']' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_TAG);
_asn1_set_value($$,$2,strlen($2)+1);}
| '[' class NUM ']' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_TAG | $2);
_asn1_set_value($$,$3,strlen($3)+1);}
;
tag : tag_type {$$=$1;}
| tag_type EXPLICIT {$$=_asn1_mod_type($1,CONST_EXPLICIT);}
| tag_type IMPLICIT {$$=_asn1_mod_type($1,CONST_IMPLICIT);}
;
default : DEFAULT pos_neg_identifier {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_DEFAULT);
_asn1_set_value($$,$2,strlen($2)+1);}
| DEFAULT ASN1_TRUE {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_DEFAULT|CONST_TRUE);}
| DEFAULT ASN1_FALSE {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_DEFAULT|CONST_FALSE);}
;
pos_neg_list: pos_neg_num
| pos_neg_list '|' pos_neg_num
;
integer_def: INTEGER {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_INTEGER);}
| INTEGER'{'constant_list'}' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_INTEGER|CONST_LIST);
_asn1_set_down($$,$3);}
| integer_def'(' pos_neg_list ')' {$$=$1;}
| integer_def'('int_identifier'.''.'int_identifier')'
{$$=$1;}
;
boolean_def: BOOLEAN {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_BOOLEAN);}
;
Time: UTCTime {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_UTC_TIME);}
| GeneralizedTime {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_GENERALIZED_TIME);}
;
size_def2: SIZE'('num_identifier')' { }
| SIZE'('num_identifier'.''.'num_identifier')'
{ }
;
size_def: size_def2 {$$=$1;}
| '(' size_def2 ')' {$$=$2;}
;
generalstring_def: GeneralString {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_GENERALSTRING);}
| GeneralString size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_GENERALSTRING|CONST_SIZE);}
;
numericstring_def: NumericString {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_NUMERIC_STRING|CONST_UNIVERSAL);}
| NumericString size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_NUMERIC_STRING|CONST_SIZE);}
;
ia5string_def: IA5String {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_IA5_STRING);}
| IA5String size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_IA5_STRING|CONST_SIZE);}
;
teletexstring_def: TeletexString {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_TELETEX_STRING);}
| TeletexString size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_TELETEX_STRING|CONST_SIZE);}
;
printablestring_def: PrintableString {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_PRINTABLE_STRING);}
| PrintableString size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_PRINTABLE_STRING|CONST_SIZE);}
;
universalstring_def: UniversalString {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_UNIVERSAL_STRING);}
| UniversalString size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_UNIVERSAL_STRING|CONST_SIZE);}
;
bmpstring_def: BMPString {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_BMP_STRING);}
| BMPString size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_BMP_STRING|CONST_SIZE);}
;
utf8string_def: UTF8String {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_UTF8_STRING);}
| UTF8String size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_UTF8_STRING|CONST_SIZE);}
;
visiblestring_def: VisibleString {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_VISIBLE_STRING);}
| VisibleString size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_VISIBLE_STRING|CONST_SIZE);}
;
octet_string_def : OCTET STRING {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_OCTET_STRING);}
| OCTET STRING size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_OCTET_STRING|CONST_SIZE);}
;
bit_element : IDENTIFIER'('NUM')' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_CONSTANT);
_asn1_set_name($$,$1);
_asn1_set_value($$,$3,strlen($3)+1);}
;
bit_element_list : bit_element {$$=$1;}
| bit_element_list ',' bit_element {$$=$1;
_asn1_set_right(_asn1_get_last_right($1),$3);}
;
bit_string_def : BIT STRING {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_BIT_STRING);}
| BIT STRING size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_BIT_STRING|CONST_SIZE);}
| BIT STRING'{'bit_element_list'}'
{$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_BIT_STRING|CONST_LIST);
_asn1_set_down($$,$4);}
;
enumerated_def : ENUMERATED'{'bit_element_list'}'
{$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_ENUMERATED|CONST_LIST);
_asn1_set_down($$,$3);}
;
object_def : OBJECT STR_IDENTIFIER {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_OBJECT_ID);}
;
type_assig_right: IDENTIFIER {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_IDENTIFIER);
_asn1_set_value($$,$1,strlen($1)+1);}
| IDENTIFIER size_def {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_IDENTIFIER|CONST_SIZE);
_asn1_set_value($$,$1,strlen($1)+1);}
| integer_def {$$=$1;}
| enumerated_def {$$=$1;}
| boolean_def {$$=$1;}
| Time
| octet_string_def {$$=$1;}
| bit_string_def {$$=$1;}
| generalstring_def {$$=$1;}
| numericstring_def {$$=$1;}
| ia5string_def {$$=$1;}
| teletexstring_def {$$=$1;}
| printablestring_def {$$=$1;}
| universalstring_def {$$=$1;}
| bmpstring_def {$$=$1;}
| utf8string_def {$$=$1;}
| visiblestring_def {$$=$1;}
| sequence_def {$$=$1;}
| object_def {$$=$1;}
| choise_def {$$=$1;}
| any_def {$$=$1;}
| set_def {$$=$1;}
| TOKEN_NULL {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_NULL);}
;
type_assig_right_tag : type_assig_right {$$=$1;}
| tag type_assig_right {$$=_asn1_mod_type($2,CONST_TAG);
_asn1_set_right($1,_asn1_get_down($$));
_asn1_set_down($$,$1);}
;
type_assig_right_tag_default : type_assig_right_tag {$$=$1;}
| type_assig_right_tag default {$$=_asn1_mod_type($1,CONST_DEFAULT);
_asn1_set_right($2,_asn1_get_down($$));
_asn1_set_down($$,$2);}
| type_assig_right_tag OPTIONAL {$$=_asn1_mod_type($1,CONST_OPTION);}
;
type_assig : IDENTIFIER type_assig_right_tag_default {$$=_asn1_set_name($2,$1);}
;
type_assig_list : type_assig {$$=$1;}
| type_assig_list','type_assig {$$=$1;
_asn1_set_right(_asn1_get_last_right($1),$3);}
;
sequence_def : SEQUENCE'{'type_assig_list'}' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_SEQUENCE);
_asn1_set_down($$,$3);}
| SEQUENCE OF type_assig_right {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_SEQUENCE_OF);
_asn1_set_down($$,$3);}
| SEQUENCE size_def OF type_assig_right {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_SEQUENCE_OF|CONST_SIZE);
_asn1_set_down($$,$4);}
;
set_def : SET'{'type_assig_list'}' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_SET);
_asn1_set_down($$,$3);}
| SET OF type_assig_right {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_SET_OF);
_asn1_set_down($$,$3);}
| SET size_def OF type_assig_right {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_SET_OF|CONST_SIZE);
_asn1_set_down($$,$4);}
;
choise_def : CHOICE'{'type_assig_list'}' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_CHOICE);
_asn1_set_down($$,$3);}
;
any_def : ANY {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_ANY);}
| ANY DEFINED BY IDENTIFIER {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_ANY|CONST_DEFINED_BY);
_asn1_set_down($$,_asn1_add_static_node(&e_list, ASN1_ETYPE_CONSTANT));
_asn1_set_name(_asn1_get_down($$),$4);}
;
known_string: UTF8String { SAFE_COPY($$,sizeof($$),"%s",last_token); }
| VisibleString { SAFE_COPY($$,sizeof($$),"%s",last_token); }
| PrintableString { SAFE_COPY($$,sizeof($$),"%s",last_token); }
| UniversalString { SAFE_COPY($$,sizeof($$),"%s",last_token); }
| IA5String { SAFE_COPY($$,sizeof($$),"%s",last_token); }
| NumericString { SAFE_COPY($$,sizeof($$),"%s",last_token); }
| TeletexString { SAFE_COPY($$,sizeof($$),"%s",last_token); }
| BMPString { SAFE_COPY($$,sizeof($$),"%s",last_token); }
/* This matches build-in types which are redefined */
type_invalid : known_string "::=" '[' class NUM ']' IMPLICIT OCTET STRING {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
fprintf(stderr, "%s:%u: Warning: %s is a built-in ASN.1 type.\n", file_name, line_number, $1);
#endif
}
;
type_def : IDENTIFIER "::=" type_assig_right_tag { $$=_asn1_set_name($3,$1);}
;
constant_def : IDENTIFIER OBJECT STR_IDENTIFIER "::=" '{'obj_constant_list'}'
{$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_OBJECT_ID|CONST_ASSIGN);
_asn1_set_name($$,$1);
_asn1_set_down($$,$6);}
| IDENTIFIER IDENTIFIER "::=" '{' obj_constant_list '}'
{$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_OBJECT_ID|CONST_ASSIGN|CONST_1_PARAM);
_asn1_set_name($$,$1);
_asn1_set_value($$,$2,strlen($2)+1);
_asn1_set_down($$,$5);}
| IDENTIFIER INTEGER "::=" pos_neg_num
{$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_INTEGER|CONST_ASSIGN);
_asn1_set_name($$,$1);
_asn1_set_value($$,$4,strlen($4)+1);}
;
type_constant: type_def {$$=$1;}
| type_invalid {$$=NULL;}
| constant_def {$$=$1;}
;
type_constant_list : type_constant {$$=$1;}
| type_constant_list type_constant {if (!$1)
{
$$ = $2;
}
else
{
$$=$1;
if ($2) _asn1_set_right(_asn1_get_last_right($1),$2);
}}
;
definitions_id : IDENTIFIER '{' obj_constant_list '}' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_OBJECT_ID);
_asn1_set_down($$,$3);
_asn1_set_name($$,$1);}
| IDENTIFIER '{' '}' {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_OBJECT_ID);
_asn1_set_name($$,$1);}
| IDENTIFIER {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_OBJECT_ID);
_asn1_set_name($$,$1);}
;
/*
identifier_list : IDENTIFIER {$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_IDENTIFIER);
_asn1_set_name($$,$1);}
| identifier_list IDENTIFIER
{$$=$1;
_asn1_set_right(_asn1_get_last_right($$),_asn1_add_static_node(&e_list, ASN1_ETYPE_IDENTIFIER));
_asn1_set_name(_asn1_get_last_right($$),$2);}
;
imports_def : empty {$$=NULL;}
| IMPORTS identifier_list FROM IDENTIFIER obj_constant_list
{$$=_asn1_add_static_node(&e_list, ASN1_ETYPE_IMPORTS);
_asn1_set_down($$,_asn1_add_static_node(&e_list, ASN1_ETYPE_OBJECT_ID));
_asn1_set_name(_asn1_get_down($$),$4);
_asn1_set_down(_asn1_get_down($$),$5);
_asn1_set_right($$,$2);}
;
*/
explicit_implicit : EXPLICIT {$$=CONST_EXPLICIT;}
| IMPLICIT {$$=CONST_IMPLICIT;}
;
%%
static const char *key_word[] = {
"::=","OPTIONAL","INTEGER","SIZE","OCTET","STRING",
"SEQUENCE","BIT","UNIVERSAL","PRIVATE","OPTIONAL",
"DEFAULT","CHOICE","OF","OBJECT","IDENTIFIER",
"BOOLEAN","TRUE","FALSE","APPLICATION","ANY","DEFINED",
"SET","BY","EXPLICIT","IMPLICIT","DEFINITIONS","TAGS",
"BEGIN","END","UTCTime","GeneralizedTime",
"GeneralString","FROM","IMPORTS","NULL","ENUMERATED",
"NumericString", "IA5String", "TeletexString", "PrintableString",
"UniversalString", "BMPString", "UTF8String", "VisibleString"};
static const int key_word_token[] = {
ASSIG, OPTIONAL, INTEGER, SIZE, OCTET, STRING, SEQUENCE, BIT, UNIVERSAL,
PRIVATE, OPTIONAL, DEFAULT, CHOICE, OF, OBJECT, STR_IDENTIFIER,
BOOLEAN, ASN1_TRUE, ASN1_FALSE, APPLICATION, ANY, DEFINED, SET, BY,
EXPLICIT, IMPLICIT, DEFINITIONS, TAGS, BEGIN, END, UTCTime,
GeneralizedTime, GeneralString, FROM, IMPORTS, TOKEN_NULL,
ENUMERATED, NumericString, IA5String, TeletexString, PrintableString,
UniversalString, BMPString, UTF8String, VisibleString
};
/*************************************************************/
/* Function: _asn1_yylex */
/* Description: looks for tokens in file_asn1 pointer file. */
/* Return: int */
/* Token identifier or ASCII code or 0(zero: End Of File) */
/*************************************************************/
static int
_asn1_yylex (void)
{
int c, counter = 0, k, lastc;
char string[ASN1_MAX_NAME_SIZE + 1]; /* will contain the next token */
size_t i;
while (1)
{
while ((c = fgetc (file_asn1)) == ' ' || c == '\t' || c == '\n')
if (c == '\n')
line_number++;
if (c == EOF)
{
snprintf (last_token, sizeof(last_token), "End Of File");
return 0;
}
if (c == '(' || c == ')' || c == '[' || c == ']' ||
c == '{' || c == '}' || c == ',' || c == '.' ||
c == '+' || c == '|')
{
last_token[0] = c;
last_token[1] = 0;
return c;
}
if (c == '-')
{ /* Maybe the first '-' of a comment */
if ((c = fgetc (file_asn1)) != '-')
{
ungetc (c, file_asn1);
last_token[0] = '-';
last_token[1] = 0;
return '-';
}
else
{ /* Comments */
lastc = 0;
counter = 0;
/* A comment finishes at the next double hypen or the end of line */
while ((c = fgetc (file_asn1)) != EOF && c != '\n' &&
(lastc != '-' || (lastc == '-' && c != '-')))
lastc = c;
if (c == EOF)
{
snprintf (last_token, sizeof(last_token), "End Of File");
return 0;
}
else
{
if (c == '\n')
line_number++;
continue; /* next char, please! (repeat the search) */
}
}
}
string[counter++] = (char) c;
/* Till the end of the token */
while (!
((c = fgetc (file_asn1)) == EOF || c == ' ' || c == '\t'
|| c == '\n' || c == '(' || c == ')' || c == '[' || c == ']'
|| c == '{' || c == '}' || c == ',' || c == '.'))
{
if (counter >= ASN1_MAX_NAME_SIZE)
{
result_parse = ASN1_NAME_TOO_LONG;
return 0;
}
string[counter++] = (char) c;
}
ungetc (c, file_asn1);
string[counter] = 0;
snprintf (last_token, sizeof(last_token), "%s", string);
/* Is STRING a number? */
for (k = 0; k < counter; k++)
if (!c_isdigit ((int)string[k]))
break;
if (k >= counter)
{
snprintf (yylval.str, sizeof(yylval.str), "%s", string);
return NUM; /* return the number */
}
/* Is STRING a keyword? */
for (i = 0; i < (sizeof (key_word) / sizeof (char *)); i++)
if (!strcmp (string, key_word[i]))
return key_word_token[i];
/* STRING is an IDENTIFIER */
snprintf (yylval.str, sizeof(yylval.str), "%s", string);
return IDENTIFIER;
}
}
/*************************************************************/
/* Function: _asn1_create_errorDescription */
/* Description: creates a string with the description of the*/
/* error. */
/* Parameters: */
/* error : error to describe. */
/* error_desc: string that will contain the */
/* description. */
/*************************************************************/
static void
_asn1_create_errorDescription (int error, char *error_desc)
{
if (error_desc == NULL)
return;
switch (error)
{
case ASN1_FILE_NOT_FOUND:
snprintf(error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE, "%s file was not found", file_name);
break;
case ASN1_SYNTAX_ERROR:
snprintf(error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE, "%s", last_error);
break;
case ASN1_NAME_TOO_LONG:
snprintf (error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE,
"%s:%u: name too long (more than %u characters)", file_name,
line_number, (unsigned)ASN1_MAX_NAME_SIZE);
break;
case ASN1_IDENTIFIER_NOT_FOUND:
snprintf (error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE,
"%s:: identifier '%s' not found", file_name,
_asn1_identifierMissing);
break;
default:
error_desc[0] = 0;
break;
}
}
/**
* asn1_parser2tree:
* @file: specify the path and the name of file that contains
* ASN.1 declarations.
* @definitions: return the pointer to the structure created from
* "file" ASN.1 declarations.
* @error_desc: return the error description or an empty
* string if success.
*
* Function used to start the parse algorithm. Creates the structures
* needed to manage the definitions included in @file file.
*
* Returns: %ASN1_SUCCESS if the file has a correct syntax and every
* identifier is known, %ASN1_ELEMENT_NOT_EMPTY if @definitions not
* %NULL, %ASN1_FILE_NOT_FOUND if an error occurred while
* opening @file, %ASN1_SYNTAX_ERROR if the syntax is not
* correct, %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an
* identifier that is not defined, %ASN1_NAME_TOO_LONG if in the
* file there is an identifier with more than %ASN1_MAX_NAME_SIZE
* characters.
**/
int
asn1_parser2tree (const char *file, asn1_node * definitions,
char *error_desc)
{
if (*definitions != NULL)
{
result_parse = ASN1_ELEMENT_NOT_EMPTY;
goto error;
}
file_name = file;
/* open the file to parse */
file_asn1 = fopen (file, "r");
if (file_asn1 == NULL)
{
result_parse = ASN1_FILE_NOT_FOUND;
goto error;
}
result_parse = ASN1_SUCCESS;
line_number = 1;
yyparse ();
fclose (file_asn1);
if (result_parse != ASN1_SUCCESS)
goto error;
/* set IMPLICIT or EXPLICIT property */
_asn1_set_default_tag (p_tree);
/* set CONST_SET and CONST_NOT_USED */
_asn1_type_set_config (p_tree);
/* check the identifier definitions */
result_parse = _asn1_check_identifier (p_tree);
if (result_parse != ASN1_SUCCESS)
goto error;
/* Convert into DER coding the value assign to INTEGER constants */
_asn1_change_integer_value (p_tree);
/* Expand the IDs of OBJECT IDENTIFIER constants */
result_parse = _asn1_expand_object_id (&e_list, p_tree);
if (result_parse != ASN1_SUCCESS)
goto error;
/* success */
*definitions = p_tree;
_asn1_delete_list (e_list);
e_list = NULL;
p_tree = NULL;
*error_desc = 0;
return result_parse;
error:
_asn1_delete_list_and_nodes (e_list);
e_list = NULL;
p_tree = NULL;
_asn1_create_errorDescription (result_parse, error_desc);
return result_parse;
}
/**
* asn1_parser2array:
* @inputFileName: specify the path and the name of file that
* contains ASN.1 declarations.
* @outputFileName: specify the path and the name of file that will
* contain the C vector definition.
* @vectorName: specify the name of the C vector.
* @error_desc: return the error description or an empty
* string if success.
*
* Function that generates a C structure from an ASN1 file. Creates a
* file containing a C vector to use to manage the definitions
* included in @inputFileName file. If @inputFileName is
* "/aa/bb/xx.yy" and @outputFileName is %NULL, the file created is
* "/aa/bb/xx_asn1_tab.c". If @vectorName is %NULL the vector name
* will be "xx_asn1_tab".
*
* Returns: %ASN1_SUCCESS if the file has a correct syntax and every
* identifier is known, %ASN1_FILE_NOT_FOUND if an error occurred
* while opening @inputFileName, %ASN1_SYNTAX_ERROR if the syntax is
* not correct, %ASN1_IDENTIFIER_NOT_FOUND if in the file there is
* an identifier that is not defined, %ASN1_NAME_TOO_LONG if in the
* file there is an identifier with more than %ASN1_MAX_NAME_SIZE
* characters.
**/
int
asn1_parser2array (const char *inputFileName, const char *outputFileName,
const char *vectorName, char *error_desc)
{
char *file_out_name = NULL;
char *vector_name = NULL;
const char *char_p, *slash_p, *dot_p;
p_tree = NULL;
file_name = inputFileName;
/* open the file to parse */
file_asn1 = fopen (inputFileName, "r");
if (file_asn1 == NULL)
{
result_parse = ASN1_FILE_NOT_FOUND;
goto error2;
}
result_parse = ASN1_SUCCESS;
line_number = 1;
yyparse ();
fclose (file_asn1);
if (result_parse != ASN1_SUCCESS)
goto error1;
/* set IMPLICIT or EXPLICIT property */
_asn1_set_default_tag (p_tree);
/* set CONST_SET and CONST_NOT_USED */
_asn1_type_set_config (p_tree);
/* check the identifier definitions */
result_parse = _asn1_check_identifier (p_tree);
if (result_parse != ASN1_SUCCESS)
goto error2;
/* all identifier defined */
/* searching the last '/' and '.' in inputFileName */
char_p = inputFileName;
slash_p = inputFileName;
while ((char_p = strchr (char_p, '/')))
{
char_p++;
slash_p = char_p;
}
char_p = slash_p;
dot_p = inputFileName + strlen (inputFileName);
while ((char_p = strchr (char_p, '.')))
{
dot_p = char_p;
char_p++;
}
if (outputFileName == NULL)
{
/* file_out_name = inputFileName + _asn1_tab.c */
file_out_name = malloc (dot_p - inputFileName + 1 +
sizeof ("_asn1_tab.c")-1);
memcpy (file_out_name, inputFileName,
dot_p - inputFileName);
file_out_name[dot_p - inputFileName] = 0;
strcat (file_out_name, "_asn1_tab.c");
}
else
{
/* file_out_name = inputFileName */
file_out_name = strdup(outputFileName);
}
if (vectorName == NULL)
{
unsigned len, i;
/* vector_name = file name + _asn1_tab */
vector_name = malloc (dot_p - slash_p + 1 +
sizeof("_asn1_tab") - 1);
memcpy (vector_name, slash_p, dot_p - slash_p);
vector_name[dot_p - slash_p] = 0;
strcat (vector_name, "_asn1_tab");
len = strlen(vector_name);
for (i=0;i<len;i++)
{
if (vector_name[i] == '-')
vector_name[i] = '_';
}
}
else
{
/* vector_name = vectorName */
vector_name = strdup(vectorName);
}
/* Save structure in a file */
_asn1_create_static_structure (p_tree,
file_out_name, vector_name);
free (file_out_name);
free (vector_name);
error1:
_asn1_delete_list_and_nodes (e_list);
e_list = NULL;
error2:
_asn1_create_errorDescription (result_parse, error_desc);
return result_parse;
}
/*************************************************************/
/* Function: _asn1_yyerror */
/* Description: function called when there are syntax errors*/
/* Parameters: */
/* char *s : error description */
/* Return: int */
/* */
/*************************************************************/
static void
_asn1_yyerror (const char *s)
{
/* Sends the error description to the std_out */
last_error_token[0] = 0;
if (result_parse != ASN1_NAME_TOO_LONG)
{
snprintf (last_error, sizeof(last_error),
"%s:%u: Error: %s near '%s'", file_name,
line_number, s, last_token);
result_parse = ASN1_SYNTAX_ERROR;
}
return;
}