diff options
Diffstat (limited to 'source4/build/pasn1/asn1.yp')
-rw-r--r-- | source4/build/pasn1/asn1.yp | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/source4/build/pasn1/asn1.yp b/source4/build/pasn1/asn1.yp new file mode 100644 index 0000000000..5fa6460d7e --- /dev/null +++ b/source4/build/pasn1/asn1.yp @@ -0,0 +1,271 @@ +######################## +# ASN.1 Parse::Yapp parser +# Copyright (C) Stefan (metze) Metzmacher <metze@samba.org> +# released under the GNU GPL version 2 or later + + + +# the precedence actually doesn't matter at all for this grammer, but +# by providing a precedence we reduce the number of conflicts +# enormously +%left '-' '+' '&' '|' '*' '>' '.' '/' '(' ')' '[' ']' ':' ',' ';' + + +################ +# grammer +%% + +asn1: + asn1_def + { [ $_[1] ] } + | asn1 asn1_def + { push(@{$_[1]}, $_[2]); $_[1] } +; + +asn1_def: + asn1_target asn1_delim asn1_application asn1_type + {{ + "OBJECT" => "ASN1_DEF", + "IDENTIFIER" => $_[1], + "APPLICATION" => $_[3], + "STRUCTURE" => $_[4] + }} +; + +asn1_target: + identifier +; + +asn1_delim: + ':' ':' '=' +; + +asn1_application: + #empty + | '[' 'APPLICATION' constant ']' + { $_[3] } +; + +asn1_type: + asn1_boolean + | asn1_integer + | asn1_bit_string + | asn1_octet_string + | asn1_null + | asn1_object_identifier + | asn1_real + | asn1_enumerated + | asn1_sequence +; + +asn1_boolean: + 'BOOLEAN' + {{ + "TYPE" => "BOOLEAN", + "TAG" => 1 + }} +; + +asn1_integer: + 'INTEGER' + {{ + "TYPE" => "INTEGER", + "TAG" => 2 + }} + | 'INTEGER' '(' constant '.' '.' constant ')' + {{ + "TYPE" => "INTEGER", + "TAG" => 2, + "RANGE_LOW" => $_[3], + "RENAGE_HIGH" => $_[6] + }} +; + +asn1_bit_string: + 'BIT' 'STRING' + {{ + "TYPE" => "BIT STRING", + "TAG" => 3 + }} +; + +asn1_octet_string: + 'OCTET' 'STRING' + {{ + "TYPE" => "OCTET STRING", + "TAG" => 4 + }} +; + +asn1_null: + 'NULL' + {{ + "TYPE" => "NULL", + "TAG" => 5 + }} +; + +asn1_object_identifier: + 'OBJECT' 'IDENTIFIER' + {{ + "TYPE" => "OBJECT IDENTIFIER", + "TAG" => 6 + }} +; + +asn1_real: + 'REAL' + {{ + "TYPE" => "REAL", + "TAG" => 9 + }} +; + +asn1_enumerated: + 'ENUMERATED' + {{ + "TYPE" => "ENUMERATED", + "TAG" => 10 + }} +; + +asn1_sequence: + 'SEQUENCE' '{' asn1_var_dec_list '}' + {{ + "TYPE" => "SEQUENCE", + "TAG" => 16, + "STRUCTURE" => $_[3] + }} +; + +asn1_var_dec_list: + asn1_var_dec + { [ $_[1] ] } + | asn1_var_dec_list ',' asn1_var_dec + { push(@{$_[1]}, $_[3]); $_[1] } +; + +asn1_var_dec: + identifier asn1_type + {{ + "NAME" => $_[1], + "TYPE" => $_[2] + }} +; + +anytext: #empty { "" } + | identifier | constant | text + | anytext '-' anytext { "$_[1]$_[2]$_[3]" } + | anytext '.' anytext { "$_[1]$_[2]$_[3]" } + | anytext '*' anytext { "$_[1]$_[2]$_[3]" } + | anytext '>' anytext { "$_[1]$_[2]$_[3]" } + | anytext '|' anytext { "$_[1]$_[2]$_[3]" } + | anytext '&' anytext { "$_[1]$_[2]$_[3]" } + | anytext '/' anytext { "$_[1]$_[2]$_[3]" } + | anytext '+' anytext { "$_[1]$_[2]$_[3]" } + | anytext '(' anytext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" } +; + +identifier: IDENTIFIER +; + +constant: CONSTANT +; + +text: TEXT { "\"$_[1]\"" } +; + +##################################### +# start code +%% + +use util; + +sub _ASN1_Error { + if (exists $_[0]->YYData->{ERRMSG}) { + print $_[0]->YYData->{ERRMSG}; + delete $_[0]->YYData->{ERRMSG}; + return; + }; + my $line = $_[0]->YYData->{LINE}; + my $last_token = $_[0]->YYData->{LAST_TOKEN}; + my $file = $_[0]->YYData->{INPUT_FILENAME}; + + print "$file:$line: Syntax error near '$last_token'\n"; +} + +sub _ASN1_Lexer($) +{ + my($parser)=shift; + + $parser->YYData->{INPUT} + or return('',undef); + +again: + $parser->YYData->{INPUT} =~ s/^[ \t]*//; + + for ($parser->YYData->{INPUT}) { + if (/^\#/) { + if (s/^\# (\d+) \"(.*?)\"( \d+|)//) { + $parser->YYData->{LINE} = $1-1; + $parser->YYData->{INPUT_FILENAME} = $2; + goto again; + } + if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) { + $parser->YYData->{LINE} = $1-1; + $parser->YYData->{INPUT_FILENAME} = $2; + goto again; + } + if (s/^(\#.*)$//m) { + goto again; + } + } + if (s/^(\n)//) { + $parser->YYData->{LINE}++; + goto again; + } + if (s/^\"(.*?)\"//) { + $parser->YYData->{LAST_TOKEN} = $1; + return('TEXT',$1); + } + if (s/^(\d+)(\W|$)/$2/) { + $parser->YYData->{LAST_TOKEN} = $1; + return('CONSTANT',$1); + } + if (s/^([\w_]+)//) { + $parser->YYData->{LAST_TOKEN} = $1; + if ($1 =~ + /^(SEQUENCE|INTEGER|OCTET|STRING| + APPLICATION|OPTIONAL|NULL|COMPONENTS|OF| + BOOLEAN|ENUMERATED|CHOISE|REAL|BIT|OBJECT|IDENTIFIER + DEFAULT|FALSE|TRUE|SET)$/x) { + return $1; + } + return('IDENTIFIER',$1); + } + if (s/^(.)//s) { + $parser->YYData->{LAST_TOKEN} = $1; + return($1,$1); + } + } +} + +sub parse_asn1($$) +{ + my $self = shift; + my $filename = shift; + + my $saved_delim = $/; + undef $/; + my $cpp = $ENV{CPP}; + if (! defined $cpp) { + $cpp = "cpp" + } + my $data = `$cpp -xc $filename`; + $/ = $saved_delim; + + $self->YYData->{INPUT} = $data; + $self->YYData->{LINE} = 0; + $self->YYData->{LAST_TOKEN} = "NONE"; + return $self->YYParse( yylex => \&_ASN1_Lexer, yyerror => \&_ASN1_Error ); +} |