| 1 | ########################
|
|---|
| 2 | # ASN.1 Parse::Yapp parser
|
|---|
| 3 | # Copyright (C) Stefan (metze) Metzmacher <metze@samba.org>
|
|---|
| 4 | # released under the GNU GPL version 3 or later
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 | # the precedence actually doesn't matter at all for this grammer, but
|
|---|
| 9 | # by providing a precedence we reduce the number of conflicts
|
|---|
| 10 | # enormously
|
|---|
| 11 | %left '-' '+' '&' '|' '*' '>' '.' '/' '(' ')' '[' ']' ':' ',' ';'
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 | ################
|
|---|
| 15 | # grammer
|
|---|
| 16 | %%
|
|---|
| 17 |
|
|---|
| 18 | asn1:
|
|---|
| 19 | identifier asn1_definitions asn1_delimitter asn1_begin asn1_decls asn1_end
|
|---|
| 20 | {{
|
|---|
| 21 | "OBJECT" => "ASN1_DEFINITION",
|
|---|
| 22 | "IDENTIFIER" => $_[1],
|
|---|
| 23 | "DATA" => $_[5]
|
|---|
| 24 | }}
|
|---|
| 25 | ;
|
|---|
| 26 |
|
|---|
| 27 | asn1_delimitter:
|
|---|
| 28 | delimitter
|
|---|
| 29 | ;
|
|---|
| 30 |
|
|---|
| 31 | asn1_definitions:
|
|---|
| 32 | 'DEFINITIONS'
|
|---|
| 33 | ;
|
|---|
| 34 |
|
|---|
| 35 | asn1_begin:
|
|---|
| 36 | 'BEGIN'
|
|---|
| 37 | ;
|
|---|
| 38 |
|
|---|
| 39 | asn1_end:
|
|---|
| 40 | 'END'
|
|---|
| 41 | ;
|
|---|
| 42 |
|
|---|
| 43 | asn1_decls:
|
|---|
| 44 | asn1_def
|
|---|
| 45 | { [ $_[1] ] }
|
|---|
| 46 | | asn1_decls asn1_def
|
|---|
| 47 | { push(@{$_[1]}, $_[2]); $_[1] }
|
|---|
| 48 | ;
|
|---|
| 49 |
|
|---|
| 50 |
|
|---|
| 51 |
|
|---|
| 52 | asn1_def:
|
|---|
| 53 | asn1_target asn1_delimitter asn1_application asn1_type
|
|---|
| 54 | {{
|
|---|
| 55 | "OBJECT" => "ASN1_DEF",
|
|---|
| 56 | "IDENTIFIER" => $_[1],
|
|---|
| 57 | "APPLICATION" => $_[3],
|
|---|
| 58 | "STRUCTURE" => $_[4]
|
|---|
| 59 | }}
|
|---|
| 60 | ;
|
|---|
| 61 |
|
|---|
| 62 | asn1_target:
|
|---|
| 63 | identifier
|
|---|
| 64 | ;
|
|---|
| 65 |
|
|---|
| 66 | asn1_application:
|
|---|
| 67 | #empty
|
|---|
| 68 | | '[' 'APPLICATION' constant ']'
|
|---|
| 69 | { $_[3] }
|
|---|
| 70 | ;
|
|---|
| 71 |
|
|---|
| 72 | asn1_type:
|
|---|
| 73 | asn1_boolean
|
|---|
| 74 | | asn1_integer
|
|---|
| 75 | | asn1_bit_string
|
|---|
| 76 | | asn1_octet_string
|
|---|
| 77 | | asn1_null
|
|---|
| 78 | | asn1_object_identifier
|
|---|
| 79 | | asn1_real
|
|---|
| 80 | | asn1_enumerated
|
|---|
| 81 | | asn1_sequence
|
|---|
| 82 | | identifier
|
|---|
| 83 | ;
|
|---|
| 84 |
|
|---|
| 85 | asn1_boolean:
|
|---|
| 86 | 'BOOLEAN'
|
|---|
| 87 | {{
|
|---|
| 88 | "TYPE" => "BOOLEAN",
|
|---|
| 89 | "TAG" => 1
|
|---|
| 90 | }}
|
|---|
| 91 | ;
|
|---|
| 92 |
|
|---|
| 93 | asn1_integer:
|
|---|
| 94 | 'INTEGER'
|
|---|
| 95 | {{
|
|---|
| 96 | "TYPE" => "INTEGER",
|
|---|
| 97 | "TAG" => 2
|
|---|
| 98 | }}
|
|---|
| 99 | | 'INTEGER' '(' constant '.' '.' constant ')'
|
|---|
| 100 | {{
|
|---|
| 101 | "TYPE" => "INTEGER",
|
|---|
| 102 | "TAG" => 2,
|
|---|
| 103 | "RANGE_LOW" => $_[3],
|
|---|
| 104 | "RENAGE_HIGH" => $_[6]
|
|---|
| 105 | }}
|
|---|
| 106 | ;
|
|---|
| 107 |
|
|---|
| 108 | asn1_bit_string:
|
|---|
| 109 | 'BIT' 'STRING'
|
|---|
| 110 | {{
|
|---|
| 111 | "TYPE" => "BIT STRING",
|
|---|
| 112 | "TAG" => 3
|
|---|
| 113 | }}
|
|---|
| 114 | ;
|
|---|
| 115 |
|
|---|
| 116 | asn1_octet_string:
|
|---|
| 117 | 'OCTET' 'STRING'
|
|---|
| 118 | {{
|
|---|
| 119 | "TYPE" => "OCTET STRING",
|
|---|
| 120 | "TAG" => 4
|
|---|
| 121 | }}
|
|---|
| 122 | ;
|
|---|
| 123 |
|
|---|
| 124 | asn1_null:
|
|---|
| 125 | 'NULL'
|
|---|
| 126 | {{
|
|---|
| 127 | "TYPE" => "NULL",
|
|---|
| 128 | "TAG" => 5
|
|---|
| 129 | }}
|
|---|
| 130 | ;
|
|---|
| 131 |
|
|---|
| 132 | asn1_object_identifier:
|
|---|
| 133 | 'OBJECT' 'IDENTIFIER'
|
|---|
| 134 | {{
|
|---|
| 135 | "TYPE" => "OBJECT IDENTIFIER",
|
|---|
| 136 | "TAG" => 6
|
|---|
| 137 | }}
|
|---|
| 138 | ;
|
|---|
| 139 |
|
|---|
| 140 | asn1_real:
|
|---|
| 141 | 'REAL'
|
|---|
| 142 | {{
|
|---|
| 143 | "TYPE" => "REAL",
|
|---|
| 144 | "TAG" => 9
|
|---|
| 145 | }}
|
|---|
| 146 | ;
|
|---|
| 147 |
|
|---|
| 148 | asn1_enumerated:
|
|---|
| 149 | 'ENUMERATED'
|
|---|
| 150 | {{
|
|---|
| 151 | "TYPE" => "ENUMERATED",
|
|---|
| 152 | "TAG" => 10
|
|---|
| 153 | }}
|
|---|
| 154 | ;
|
|---|
| 155 |
|
|---|
| 156 | asn1_sequence:
|
|---|
| 157 | 'SEQUENCE' '{' asn1_var_dec_list '}'
|
|---|
| 158 | {{
|
|---|
| 159 | "TYPE" => "SEQUENCE",
|
|---|
| 160 | "TAG" => 16,
|
|---|
| 161 | "STRUCTURE" => $_[3]
|
|---|
| 162 | }}
|
|---|
| 163 | ;
|
|---|
| 164 |
|
|---|
| 165 | asn1_var_dec_list:
|
|---|
| 166 | asn1_var_dec
|
|---|
| 167 | { [ $_[1] ] }
|
|---|
| 168 | | asn1_var_dec_list ',' asn1_var_dec
|
|---|
| 169 | { push(@{$_[1]}, $_[3]); $_[1] }
|
|---|
| 170 | ;
|
|---|
| 171 |
|
|---|
| 172 | asn1_var_dec:
|
|---|
| 173 | identifier asn1_type
|
|---|
| 174 | {{
|
|---|
| 175 | "NAME" => $_[1],
|
|---|
| 176 | "TYPE" => $_[2]
|
|---|
| 177 | }}
|
|---|
| 178 | ;
|
|---|
| 179 |
|
|---|
| 180 | anytext: #empty { "" }
|
|---|
| 181 | | identifier | constant | text
|
|---|
| 182 | | anytext '-' anytext { "$_[1]$_[2]$_[3]" }
|
|---|
| 183 | | anytext '.' anytext { "$_[1]$_[2]$_[3]" }
|
|---|
| 184 | | anytext '*' anytext { "$_[1]$_[2]$_[3]" }
|
|---|
| 185 | | anytext '>' anytext { "$_[1]$_[2]$_[3]" }
|
|---|
| 186 | | anytext '|' anytext { "$_[1]$_[2]$_[3]" }
|
|---|
| 187 | | anytext '&' anytext { "$_[1]$_[2]$_[3]" }
|
|---|
| 188 | | anytext '/' anytext { "$_[1]$_[2]$_[3]" }
|
|---|
| 189 | | anytext '+' anytext { "$_[1]$_[2]$_[3]" }
|
|---|
| 190 | | anytext '(' anytext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
|
|---|
| 191 | ;
|
|---|
| 192 |
|
|---|
| 193 | delimitter: DELIMITTER
|
|---|
| 194 | ;
|
|---|
| 195 |
|
|---|
| 196 | identifier: IDENTIFIER
|
|---|
| 197 | ;
|
|---|
| 198 |
|
|---|
| 199 | constant: CONSTANT
|
|---|
| 200 | ;
|
|---|
| 201 |
|
|---|
| 202 | text: TEXT { "\"$_[1]\"" }
|
|---|
| 203 | ;
|
|---|
| 204 |
|
|---|
| 205 | #####################################
|
|---|
| 206 | # start code
|
|---|
| 207 | %%
|
|---|
| 208 |
|
|---|
| 209 | use util;
|
|---|
| 210 |
|
|---|
| 211 | sub _ASN1_Error {
|
|---|
| 212 | if (exists $_[0]->YYData->{ERRMSG}) {
|
|---|
| 213 | print $_[0]->YYData->{ERRMSG};
|
|---|
| 214 | delete $_[0]->YYData->{ERRMSG};
|
|---|
| 215 | return;
|
|---|
| 216 | };
|
|---|
| 217 | my $line = $_[0]->YYData->{LINE};
|
|---|
| 218 | my $last_token = $_[0]->YYData->{LAST_TOKEN};
|
|---|
| 219 | my $file = $_[0]->YYData->{INPUT_FILENAME};
|
|---|
| 220 |
|
|---|
| 221 | print "$file:$line: Syntax error near '$last_token'\n";
|
|---|
| 222 | }
|
|---|
| 223 |
|
|---|
| 224 | sub _ASN1_Lexer($)
|
|---|
| 225 | {
|
|---|
| 226 | my($parser)=shift;
|
|---|
| 227 |
|
|---|
| 228 | $parser->YYData->{INPUT}
|
|---|
| 229 | or return('',undef);
|
|---|
| 230 |
|
|---|
| 231 | again:
|
|---|
| 232 | $parser->YYData->{INPUT} =~ s/^[ \t]*//;
|
|---|
| 233 |
|
|---|
| 234 | for ($parser->YYData->{INPUT}) {
|
|---|
| 235 | if (/^\#/) {
|
|---|
| 236 | if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
|
|---|
| 237 | $parser->YYData->{LINE} = $1-1;
|
|---|
| 238 | $parser->YYData->{INPUT_FILENAME} = $2;
|
|---|
| 239 | goto again;
|
|---|
| 240 | }
|
|---|
| 241 | if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
|
|---|
| 242 | $parser->YYData->{LINE} = $1-1;
|
|---|
| 243 | $parser->YYData->{INPUT_FILENAME} = $2;
|
|---|
| 244 | goto again;
|
|---|
| 245 | }
|
|---|
| 246 | if (s/^(\#.*)$//m) {
|
|---|
| 247 | goto again;
|
|---|
| 248 | }
|
|---|
| 249 | }
|
|---|
| 250 | if (s/^(\n)//) {
|
|---|
| 251 | $parser->YYData->{LINE}++;
|
|---|
| 252 | goto again;
|
|---|
| 253 | }
|
|---|
| 254 | if (s/^(--.*\n)//) {
|
|---|
| 255 | $parser->YYData->{LINE}++;
|
|---|
| 256 | goto again;
|
|---|
| 257 | }
|
|---|
| 258 | if (s/^(::=)//) {
|
|---|
| 259 | $parser->YYData->{LAST_TOKEN} = $1;
|
|---|
| 260 | return('DELIMITTER',$1);
|
|---|
| 261 | }
|
|---|
| 262 | if (s/^\"(.*?)\"//) {
|
|---|
| 263 | $parser->YYData->{LAST_TOKEN} = $1;
|
|---|
| 264 | return('TEXT',$1);
|
|---|
| 265 | }
|
|---|
| 266 | if (s/^(\d+)(\W|$)/$2/) {
|
|---|
| 267 | $parser->YYData->{LAST_TOKEN} = $1;
|
|---|
| 268 | return('CONSTANT',$1);
|
|---|
| 269 | }
|
|---|
| 270 | if (s/^([\w_-]+)//) {
|
|---|
| 271 | $parser->YYData->{LAST_TOKEN} = $1;
|
|---|
| 272 | if ($1 =~
|
|---|
| 273 | /^(SEQUENCE|INTEGER|OCTET|STRING|
|
|---|
| 274 | APPLICATION|OPTIONAL|NULL|COMPONENTS|OF|
|
|---|
| 275 | BOOLEAN|ENUMERATED|CHOISE|REAL|BIT|OBJECT|IDENTIFIER|
|
|---|
| 276 | DEFAULT|FALSE|TRUE|SET|DEFINITIONS|BEGIN|END)$/x) {
|
|---|
| 277 | return $1;
|
|---|
| 278 | }
|
|---|
| 279 | return('IDENTIFIER',$1);
|
|---|
| 280 | }
|
|---|
| 281 | if (s/^(.)//s) {
|
|---|
| 282 | $parser->YYData->{LAST_TOKEN} = $1;
|
|---|
| 283 | return($1,$1);
|
|---|
| 284 | }
|
|---|
| 285 | }
|
|---|
| 286 | }
|
|---|
| 287 |
|
|---|
| 288 | sub parse_asn1($$)
|
|---|
| 289 | {
|
|---|
| 290 | my $self = shift;
|
|---|
| 291 | my $filename = shift;
|
|---|
| 292 |
|
|---|
| 293 | my $saved_delim = $/;
|
|---|
| 294 | undef $/;
|
|---|
| 295 | my $cpp = $ENV{CPP};
|
|---|
| 296 | if (! defined $cpp) {
|
|---|
| 297 | $cpp = "cpp"
|
|---|
| 298 | }
|
|---|
| 299 | my $data = `$cpp -xc $filename`;
|
|---|
| 300 | $/ = $saved_delim;
|
|---|
| 301 |
|
|---|
| 302 | $self->YYData->{INPUT} = $data;
|
|---|
| 303 | $self->YYData->{LINE} = 0;
|
|---|
| 304 | $self->YYData->{LAST_TOKEN} = "NONE";
|
|---|
| 305 | return $self->YYParse( yylex => \&_ASN1_Lexer, yyerror => \&_ASN1_Error );
|
|---|
| 306 | }
|
|---|