blob: bce91880024d466da63531bbaab43fcc980c6954 [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001%{
2
3#include <string.h>
4#include <errno.h>
5#include <assert.h>
6
7#include "asn1parser.h"
8#include "asn1p_y.h"
9
10int asn1p_lex(void);
11void asn1p_lexer_hack_push_opaque_state(void); /* Used in .y */
12void asn1p_lexer_hack_enable_with_syntax(void); /* Used in .y */
vlm9283dbe2004-08-18 04:59:12 +000013void asn1p_lexer_hack_push_encoding_control(void); /* Used in .y */
vlmfa67ddc2004-06-03 03:38:44 +000014
15#define YY_FATAL_ERROR(msg) do { \
16 fprintf(stderr, \
17 "lexer error at line %d, " \
18 "text \"%s\"\n", \
19 yylineno, yytext); \
20 exit(1); \
21 } while(0)
22
23int asn1p_lexer_pedantic_1990 = 0;
24int asn1p_lexer_types_year = 0;
25int asn1p_lexer_constructs_year = 0;
vlm2728a8d2005-01-23 09:51:44 +000026static asn1c_integer_t asn1p_atoi(char *ptr); /* errno is either 0 or ERANGE */
vlmfa67ddc2004-06-03 03:38:44 +000027
vlm066dc102005-08-22 12:23:54 +000028int asn1p_as_pointer;
29
vlmfa67ddc2004-06-03 03:38:44 +000030/*
31 * Check that the type is defined in the year of the standard choosen.
32 */
33#define TYPE_LIFETIME(fyr, lyr) \
34 (!asn1p_lexer_types_year \
35 || (fyr && fyr <= asn1p_lexer_types_year) \
36 || (lyr && lyr > asn1p_lexer_types_year))
37
38/*
39 * Check the the construction (or concept, i.e. CLASS) is defined in
40 * a given year.
41 */
42#define CONSTRUCT_LIFETIME(fyr, lyr) \
43 (!asn1p_lexer_constructs_year \
44 || (fyr && fyr <= asn1p_lexer_constructs_year) \
45 || (lyr && lyr > asn1p_lexer_constructs_year))
46
47/*
vlmfa67ddc2004-06-03 03:38:44 +000048 * Append quoted string.
49 */
50#define QAPPEND(text, tlen) do { \
51 char *prev_text = asn1p_lval.tv_opaque.buf; \
52 int prev_len = asn1p_lval.tv_opaque.len; \
53 char *p; \
54 \
55 p = malloc((tlen) + prev_len + 1); \
56 if(p == NULL) return -1; \
57 \
58 if(prev_text) memcpy(p, prev_text, prev_len); \
59 memcpy(p + prev_len, text, tlen); \
60 p[prev_len + (tlen)] = '\0'; \
61 \
62 free(asn1p_lval.tv_opaque.buf); \
63 asn1p_lval.tv_opaque.buf = p; \
64 asn1p_lval.tv_opaque.len = (tlen) + prev_len; \
65 } while(0)
66
67%}
68
69%option never-interactive
vlm9283dbe2004-08-18 04:59:12 +000070%option noinput
vlmfa67ddc2004-06-03 03:38:44 +000071%option noyywrap stack
72/* Performance penalty is OK */
73%option yylineno
74/* Controlled from within application */
75%option debug
76
77%pointer
78
79%x dash_comment
vlmb5abdc92005-07-02 21:42:40 +000080%x idash_comment
vlmfa67ddc2004-06-03 03:38:44 +000081%x cpp_comment
82%x quoted
83%x opaque
vlm9283dbe2004-08-18 04:59:12 +000084%x encoding_control
vlmfa67ddc2004-06-03 03:38:44 +000085%x with_syntax
86
87/* Newline */
88NL [\r\v\f\n]
89/* White-space */
90WSP [\t\r\v\f\n ]
91
92%%
93
vlmb5abdc92005-07-02 21:42:40 +000094-{3,}/[\r\n] /* Immediately terminated long comment */
95-{3,}/[^-\r\n] yy_push_state(idash_comment); /* Incorrect, but acceptable */
96<idash_comment>{
97 -{3,} yy_pop_state(); /* Acceptable end of comment */
98}
99
vlm177a5b62005-09-05 05:17:57 +0000100--<[ \t]*ASN1C.RepresentAsPointer[ \t]*>-- asn1p_as_pointer = 1;
101
vlmb5abdc92005-07-02 21:42:40 +0000102-- yy_push_state(dash_comment);
103<dash_comment,idash_comment>{
vlmfa67ddc2004-06-03 03:38:44 +0000104
105 {NL} yy_pop_state();
106
107 -- yy_pop_state(); /* End of comment */
108 - /* Eat single dash */
vlm177a5b62005-09-05 05:17:57 +0000109 [^\r\v\f\n-]+ /* Eat */
vlmfa67ddc2004-06-03 03:38:44 +0000110}
vlmb5abdc92005-07-02 21:42:40 +0000111
vlmfa67ddc2004-06-03 03:38:44 +0000112<INITIAL,cpp_comment>"/*" yy_push_state(cpp_comment);
113<cpp_comment>{
vlm066dc102005-08-22 12:23:54 +0000114 [^*/<] /* Eat */
vlmfa67ddc2004-06-03 03:38:44 +0000115 "*/" yy_pop_state();
116 . /* Eat */
117}
118
119
120 /*
121 * This is state is being set from corresponding .y module when
122 * higher-level data is necessary to make proper parsing of the
123 * underlying data. Thus, we enter the <opaque> state and save
124 * everything for later processing.
125 */
126<opaque>{
127
128 "{" {
129 yy_push_state(opaque);
130 asn1p_lval.tv_opaque.buf = strdup(yytext);
131 asn1p_lval.tv_opaque.len = yyleng;
132 return TOK_opaque;
133 }
134
135 "}" {
136 yy_pop_state();
137 asn1p_lval.tv_opaque.buf = strdup(yytext);
138 asn1p_lval.tv_opaque.len = yyleng;
139 return TOK_opaque;
140 }
141
142 [^{}:=]+ {
143 asn1p_lval.tv_opaque.buf = strdup(yytext);
144 asn1p_lval.tv_opaque.len = yyleng;
145 return TOK_opaque;
146 }
147
148 "::=" {
149 fprintf(stderr,
150 "ASN.1 Parser syncronization failure: "
151 "\"%s\" at line %d must not appear "
152 "inside value definition\n",
153 yytext, yylineno);
154 return -1;
155 }
156
157 [:=] {
158 asn1p_lval.tv_opaque.buf = strdup(yytext);
159 asn1p_lval.tv_opaque.len = yyleng;
160 return TOK_opaque;
161 }
162
163 }
164
165\"[^\"]* {
166 asn1p_lval.tv_opaque.buf = 0;
167 asn1p_lval.tv_opaque.len = 0;
168 QAPPEND(yytext+1, yyleng-1);
169 yy_push_state(quoted);
170 }
171<quoted>{
172
173 \"\" { QAPPEND(yytext, yyleng-1); } /* Add a single quote */
174 [^\"]+ { QAPPEND(yytext, yyleng); }
175
176 \" {
177 yy_pop_state();
178 /* Do not append last quote:
179 // QAPPEND(yytext, yyleng); */
180
181 if(asn1p_lexer_pedantic_1990
182 && strchr(yytext, '\n')) {
183 fprintf(stderr, "%s: "
184 "Newlines are prohibited by ASN.1:1990\n",
185 asn1p_lval.tv_opaque.buf);
186 return -1;
187 }
188
189 return TOK_cstring;
190 }
191
192 }
193
vlm9283dbe2004-08-18 04:59:12 +0000194<encoding_control>{
195 ENCODING-CONTROL {
196 const char *s = "ENCODING-CONTROL";
197 const char *p = s + sizeof("ENCODING-CONTROL") - 2;
198 for(; p >= s; p--) unput(*p);
199 yy_pop_state();
200 }
201 END unput('D'); unput('N'); unput('E'); yy_pop_state();
202 [^{} \t\r\v\f\n]+
203 [[:alnum:]]+
204 . /* Eat everything else */
205 "\n"
206 }
vlmfa67ddc2004-06-03 03:38:44 +0000207
208'[0-9A-F \t\r\v\f\n]+'H {
209 /* " \t\r\n" weren't allowed in ASN.1:1990. */
210 asn1p_lval.tv_str = yytext;
211 return TOK_hstring;
212 }
213
214'[01 \t\r\v\f\n]+'B {
215 /* " \t\r\n" weren't allowed in ASN.1:1990. */
216 asn1p_lval.tv_str = strdup(yytext);
217 return TOK_bstring;
218 }
219
220
221-[1-9][0-9]* {
222 asn1p_lval.a_int = asn1p_atoi(yytext);
223 if(errno == ERANGE)
224 return -1;
225 return TOK_number_negative;
226 }
227
228[1-9][0-9]* {
229 asn1p_lval.a_int = asn1p_atoi(yytext);
230 if(errno == ERANGE)
231 return -1;
232 return TOK_number;
233 }
234
235"0" {
236 asn1p_lval.a_int = asn1p_atoi(yytext);
237 if(errno == ERANGE)
238 return -1;
239 return TOK_number;
240 }
241
vlmfa67ddc2004-06-03 03:38:44 +0000242ABSENT return TOK_ABSENT;
vlmc94e28f2004-09-15 11:59:51 +0000243 /*
vlmfa67ddc2004-06-03 03:38:44 +0000244ABSTRACT-SYNTAX return TOK_ABSTRACT_SYNTAX;
vlmc94e28f2004-09-15 11:59:51 +0000245 */
vlmfa67ddc2004-06-03 03:38:44 +0000246ALL return TOK_ALL;
247ANY {
248 /* Appeared in 1990, removed in 1997 */
249 if(TYPE_LIFETIME(1990, 1997))
250 return TOK_ANY;
251 fprintf(stderr, "Keyword \"%s\" at line %d "
252 "is obsolete\n", yytext, yylineno);
253 REJECT;
254 }
255APPLICATION return TOK_APPLICATION;
256AUTOMATIC return TOK_AUTOMATIC;
257BEGIN return TOK_BEGIN;
258BIT return TOK_BIT;
259BMPString {
260 if(TYPE_LIFETIME(1994, 0))
261 return TOK_BMPString;
262 REJECT;
263 }
264BOOLEAN return TOK_BOOLEAN;
265BY return TOK_BY;
266CHARACTER return TOK_CHARACTER;
267CHOICE return TOK_CHOICE;
268CLASS return TOK_CLASS;
269COMPONENT return TOK_COMPONENT;
270COMPONENTS return TOK_COMPONENTS;
vlm6611add2005-03-20 14:28:32 +0000271CONSTRAINED return TOK_CONSTRAINED;
vlmfa67ddc2004-06-03 03:38:44 +0000272CONTAINING return TOK_CONTAINING;
273DEFAULT return TOK_DEFAULT;
274DEFINED {
275 /* Appeared in 1990, removed in 1997 */
276 if(TYPE_LIFETIME(1990, 1997))
277 return TOK_DEFINED;
278 fprintf(stderr, "Keyword \"%s\" at line %d "
279 "is obsolete\n", yytext, yylineno);
280 /* Deprecated since */
281 REJECT;
282 }
283DEFINITIONS return TOK_DEFINITIONS;
284EMBEDDED return TOK_EMBEDDED;
285ENCODED return TOK_ENCODED;
vlm9283dbe2004-08-18 04:59:12 +0000286ENCODING-CONTROL return TOK_ENCODING_CONTROL;
vlmfa67ddc2004-06-03 03:38:44 +0000287END return TOK_END;
288ENUMERATED return TOK_ENUMERATED;
289EXCEPT return TOK_EXCEPT;
290EXPLICIT return TOK_EXPLICIT;
291EXPORTS return TOK_EXPORTS;
292EXTENSIBILITY return TOK_EXTENSIBILITY;
293EXTERNAL return TOK_EXTERNAL;
294FALSE return TOK_FALSE;
295FROM return TOK_FROM;
296GeneralizedTime return TOK_GeneralizedTime;
297GeneralString return TOK_GeneralString;
298GraphicString return TOK_GraphicString;
299IA5String return TOK_IA5String;
300IDENTIFIER return TOK_IDENTIFIER;
301IMPLICIT return TOK_IMPLICIT;
302IMPLIED return TOK_IMPLIED;
303IMPORTS return TOK_IMPORTS;
304INCLUDES return TOK_INCLUDES;
305INSTANCE return TOK_INSTANCE;
vlm9283dbe2004-08-18 04:59:12 +0000306INSTRUCTIONS return TOK_INSTRUCTIONS;
vlmfa67ddc2004-06-03 03:38:44 +0000307INTEGER return TOK_INTEGER;
308INTERSECTION return TOK_INTERSECTION;
309ISO646String return TOK_ISO646String;
310MAX return TOK_MAX;
311MIN return TOK_MIN;
312MINUS-INFINITY return TOK_MINUS_INFINITY;
313NULL return TOK_NULL;
314NumericString return TOK_NumericString;
315OBJECT return TOK_OBJECT;
316ObjectDescriptor return TOK_ObjectDescriptor;
317OCTET return TOK_OCTET;
318OF return TOK_OF;
319OPTIONAL return TOK_OPTIONAL;
320PATTERN return TOK_PATTERN;
321PDV return TOK_PDV;
322PLUS-INFINITY return TOK_PLUS_INFINITY;
323PRESENT return TOK_PRESENT;
324PrintableString return TOK_PrintableString;
325PRIVATE return TOK_PRIVATE;
326REAL return TOK_REAL;
327RELATIVE-OID return TOK_RELATIVE_OID;
328SEQUENCE return TOK_SEQUENCE;
329SET return TOK_SET;
330SIZE return TOK_SIZE;
331STRING return TOK_STRING;
332SYNTAX return TOK_SYNTAX;
333T61String return TOK_T61String;
334TAGS return TOK_TAGS;
335TeletexString return TOK_TeletexString;
336TRUE return TOK_TRUE;
337TYPE-IDENTIFIER return TOK_TYPE_IDENTIFIER;
338UNION return TOK_UNION;
339UNIQUE return TOK_UNIQUE;
340UNIVERSAL return TOK_UNIVERSAL;
341UniversalString {
342 if(TYPE_LIFETIME(1994, 0))
343 return TOK_UniversalString;
344 REJECT;
345 }
346UTCTime return TOK_UTCTime;
347UTF8String {
348 if(TYPE_LIFETIME(1994, 0))
349 return TOK_UTF8String;
350 REJECT;
351 }
352VideotexString return TOK_VideotexString;
353VisibleString return TOK_VisibleString;
354WITH return TOK_WITH;
355
356
vlmb5abdc92005-07-02 21:42:40 +0000357<INITIAL,with_syntax>&[A-Z][A-Za-z0-9]*([-][A-Za-z0-9]+)* {
vlmfa67ddc2004-06-03 03:38:44 +0000358 asn1p_lval.tv_str = strdup(yytext);
359 return TOK_typefieldreference;
360 }
361
vlmb5abdc92005-07-02 21:42:40 +0000362<INITIAL,with_syntax>&[a-z][a-zA-Z0-9]*([-][a-zA-Z0-9]+)* {
vlmfa67ddc2004-06-03 03:38:44 +0000363 asn1p_lval.tv_str = strdup(yytext);
364 return TOK_valuefieldreference;
365 }
366
367
vlmb5abdc92005-07-02 21:42:40 +0000368[a-z][a-zA-Z0-9]*([-][a-zA-Z0-9]+)* {
vlmfa67ddc2004-06-03 03:38:44 +0000369 asn1p_lval.tv_str = strdup(yytext);
370 return TOK_identifier;
371 }
372
373 /*
374 * objectclassreference
375 */
vlmb5abdc92005-07-02 21:42:40 +0000376[A-Z][A-Z0-9]*([-][A-Z0-9]+)* {
vlmfa67ddc2004-06-03 03:38:44 +0000377 asn1p_lval.tv_str = strdup(yytext);
vlm9283dbe2004-08-18 04:59:12 +0000378 return TOK_capitalreference;
vlmfa67ddc2004-06-03 03:38:44 +0000379 }
380
381 /*
382 * typereference, modulereference
383 * NOTE: TOK_objectclassreference must be combined
384 * with this token to produce true typereference.
385 */
vlmb5abdc92005-07-02 21:42:40 +0000386[A-Z][A-Za-z0-9]*([-][A-Za-z0-9]+)* {
vlmfa67ddc2004-06-03 03:38:44 +0000387 asn1p_lval.tv_str = strdup(yytext);
388 return TOK_typereference;
389 }
390
391"::=" return TOK_PPEQ;
392
393"..." return TOK_ThreeDots;
394".." return TOK_TwoDots;
395
vlmfa67ddc2004-06-03 03:38:44 +0000396<with_syntax>{
397
398 [^&{} \t\r\v\f\n]+ {
399 asn1p_lval.tv_opaque.buf = strdup(yytext);
400 asn1p_lval.tv_opaque.len = yyleng;
401 return TOK_opaque;
402 }
403
404 {WSP}+ {
405 asn1p_lval.tv_opaque.buf = strdup(yytext);
406 asn1p_lval.tv_opaque.len = yyleng;
407 return TOK_opaque;
408 }
409
410 "}" {
411 yy_pop_state();
412 return '}';
413 }
414
415}
416
vlm2c8c44d2005-03-24 16:22:35 +0000417
418{WSP}+ /* Ignore whitespace */
419
420
421[{][\t\r\v\f\n ]*[0-7][,][\t\r\v\f\n ]*[0-9]+[\t\r\v\f\n ]*[}] {
422 asn1c_integer_t v1 = -1, v2 = -1;
423 char *p;
424 for(p = yytext; *p; p++)
425 if(*p >= '0' && *p <= '9')
426 { v1 = asn1p_atoi(p); break; }
427 while(*p >= '0' && *p <= '9') p++; /* Skip digits */
428 for(; *p; p++) if(*p >= '0' && *p <= '9')
429 { v2 = asn1p_atoi(p); break; }
430 if(v1 < 0 || v1 > 7) {
431 fprintf(stderr, "%s at line %d: X.680:2003, #37.14 "
432 "mandates 0..7 range for Tuple's TableColumn\n",
433 yytext, yylineno);
434 return -1;
435 }
436 if(v2 < 0 || v2 > 15) {
437 fprintf(stderr, "%s at line %d: X.680:2003, #37.14 "
438 "mandates 0..15 range for Tuple's TableRow\n",
439 yytext, yylineno);
440 return -1;
441 }
442 asn1p_lval.a_int = (v1 << 4) + v2;
443 return TOK_tuple;
444 }
445
446[{][\t\r\v\f\n ]*[0-9]+[,][\t\r\v\f\n ]*[0-9]+[,][\t\r\v\f\n ]*[0-9]+[,][\t\r\v\f\n ]*[0-9]+[\t\r\v\f\n ]*[}] {
447 asn1c_integer_t v1 = -1, v2 = -1, v3 = -1, v4 = -1;
448 char *p;
449 for(p = yytext; *p; p++)
450 if(*p >= '0' && *p <= '9')
451 { v1 = asn1p_atoi(p); break; }
452 while(*p >= '0' && *p <= '9') p++; /* Skip digits */
453 for(; *p; p++) if(*p >= '0' && *p <= '9')
454 { v2 = asn1p_atoi(p); break; }
455 while(*p >= '0' && *p <= '9') p++;
456 for(; *p; p++) if(*p >= '0' && *p <= '9')
457 { v3 = asn1p_atoi(p); break; }
458 while(*p >= '0' && *p <= '9') p++;
459 for(; *p; p++) if(*p >= '0' && *p <= '9')
460 { v4 = asn1p_atoi(p); break; }
461 if(v1 < 0 || v1 > 127) {
462 fprintf(stderr, "%s at line %d: X.680:2003, #37.12 "
463 "mandates 0..127 range for Quadruple's Group\n",
464 yytext, yylineno);
465 return -1;
466 }
467 if(v2 < 0 || v2 > 255) {
468 fprintf(stderr, "%s at line %d: X.680:2003, #37.12 "
469 "mandates 0..255 range for Quadruple's Plane\n",
470 yytext, yylineno);
471 return -1;
472 }
473 if(v3 < 0 || v3 > 255) {
474 fprintf(stderr, "%s at line %d: X.680:2003, #37.12 "
475 "mandates 0..255 range for Quadruple's Row\n",
476 yytext, yylineno);
477 return -1;
478 }
479 if(v4 < 0 || v4 > 255) {
480 fprintf(stderr, "%s at line %d: X.680:2003, #37.12 "
481 "mandates 0..255 range for Quadruple's Cell\n",
482 yytext, yylineno);
483 return -1;
484 }
485 asn1p_lval.a_int = (v1 << 24) | (v2 << 16) | (v3 << 8) | v4;
486 return TOK_quadruple;
487 }
488
489
490[(){},;:|!.&@\[\]^] return yytext[0];
491
492[^A-Za-z0-9:=,{}<.@()[]'\"|&^*;!-] {
493 if(TYPE_LIFETIME(1994, 0))
494 fprintf(stderr, "ERROR: ");
495 fprintf(stderr,
496 "Symbol '%c' at line %d is prohibited "
497 "by ASN.1:1994 and ASN.1:1997\n",
498 yytext[0], yylineno);
499 if(TYPE_LIFETIME(1994, 0))
500 return -1;
501 }
vlmfa67ddc2004-06-03 03:38:44 +0000502
503<*>. {
504 fprintf(stderr,
505 "Unexpected token at line %d: \"%s\"\n",
506 yylineno, yytext);
507 while(YYSTATE != INITIAL)
508 yy_pop_state();
vlmc94e28f2004-09-15 11:59:51 +0000509 if(0) {
510 yy_top_state(); /* Just to use this function. */
511 yy_fatal_error("Parse error");
512 }
vlmfa67ddc2004-06-03 03:38:44 +0000513 return -1;
514}
515
516<*><<EOF>> {
517 while(YYSTATE != INITIAL)
518 yy_pop_state();
519 yyterminate();
520 }
521
522
523%%
524
525/*
526 * Very dirty but wonderful hack allowing to rule states from within .y file.
527 */
vlm9283dbe2004-08-18 04:59:12 +0000528void asn1p_lexer_hack_push_opaque_state() { yy_push_state(opaque); }
vlmfa67ddc2004-06-03 03:38:44 +0000529
530/*
531 * Another hack which disables recognizing some tokens when inside WITH SYNTAX.
532 */
vlm9283dbe2004-08-18 04:59:12 +0000533void asn1p_lexer_hack_enable_with_syntax() { yy_push_state(with_syntax); }
534
535/* Yet another */
536void asn1p_lexer_hack_push_encoding_control() {
537 yy_push_state(encoding_control);
vlmfa67ddc2004-06-03 03:38:44 +0000538}
539
vlm2728a8d2005-01-23 09:51:44 +0000540static asn1c_integer_t
vlmfa67ddc2004-06-03 03:38:44 +0000541asn1p_atoi(char *ptr) {
vlm2728a8d2005-01-23 09:51:44 +0000542 asn1c_integer_t value;
vlmfa67ddc2004-06-03 03:38:44 +0000543 errno = 0; /* Clear the error code */
544
545 if(sizeof(value) <= sizeof(int)) {
546 value = strtol(ptr, 0, 10);
547 } else {
548#ifdef HAVE_STRTOIMAX
549 value = strtoimax(ptr, 0, 10);
550#elif HAVE_STRTOLL
551 value = strtoll(ptr, 0, 10);
552#else
553 value = strtol(ptr, 0, 10);
554#endif
555 }
556
557 if(errno == ERANGE) {
558 fprintf(stderr,
559 "Value \"%s\" at line %d is too large "
vlm86912f02005-04-05 08:46:22 +0000560 "for this compiler! Please contact the asn1c author.\n",
vlmfa67ddc2004-06-03 03:38:44 +0000561 ptr, yylineno);
562 errno = ERANGE; /* Restore potentially clobbered errno */
563 }
564
565 return value;
566}
567