7 #include "asn1parser.h"
11 void asn1p_lexer_hack_push_opaque_state(void); /* Used in .y */
12 void asn1p_lexer_hack_enable_with_syntax(void); /* Used in .y */
13 void asn1p_lexer_hack_push_encoding_control(void); /* Used in .y */
15 #define YY_FATAL_ERROR(msg) do { \
17 "lexer error at line %d, " \
23 int asn1p_lexer_pedantic_1990 = 0;
24 int asn1p_lexer_types_year = 0;
25 int asn1p_lexer_constructs_year = 0;
26 int asn1p_lexer_extended_values = 0;
30 static asn1c_integer_t _lex_atoi(const char *ptr);
31 static double _lex_atod(const char *ptr);
34 * Check that the type is defined in the year of the standard choosen.
36 #define TYPE_LIFETIME(fyr, lyr) \
37 (!asn1p_lexer_types_year \
38 || (fyr && fyr <= asn1p_lexer_types_year) \
39 || (lyr && lyr > asn1p_lexer_types_year))
42 * Check the the construction (or concept, i.e. CLASS) is defined in
45 #define CONSTRUCT_LIFETIME(fyr, lyr) \
46 (!asn1p_lexer_constructs_year \
47 || (fyr && fyr <= asn1p_lexer_constructs_year) \
48 || (lyr && lyr > asn1p_lexer_constructs_year))
51 * Append quoted string.
53 #define QAPPEND(text, tlen) do { \
54 char *prev_text = asn1p_lval.tv_opaque.buf; \
55 int prev_len = asn1p_lval.tv_opaque.len; \
58 p = malloc((tlen) + prev_len + 1); \
59 if(p == NULL) return -1; \
61 if(prev_text) memcpy(p, prev_text, prev_len); \
62 memcpy(p + prev_len, text, tlen); \
63 p[prev_len + (tlen)] = '\0'; \
65 free(asn1p_lval.tv_opaque.buf); \
66 asn1p_lval.tv_opaque.buf = p; \
67 asn1p_lval.tv_opaque.len = (tlen) + prev_len; \
72 %option never-interactive
74 %option noyywrap stack
75 /* Performance penalty is OK */
77 /* Controlled from within application */
98 <INITIAL>"\xef\xbb\xbf" return UTF8_BOM;
100 -{3,}/[\r\n] /* Immediately terminated long comment */
101 -{3,}/[^-\r\n] yy_push_state(idash_comment); /* Incorrect, but acceptable */
103 -{3,} yy_pop_state(); /* Acceptable end of comment */
106 --<[ \t]*ASN1C.RepresentAsPointer[ \t]*>-- asn1p_as_pointer = 1;
111 return TOK_ExtValue_BIT_STRING;
115 <INITIAL,with_syntax>-- yy_push_state(dash_comment);
116 <dash_comment,idash_comment>{
120 -- yy_pop_state(); /* End of comment */
121 - /* Eat single dash */
122 [^\r\v\f\n-]+ /* Eat */
125 <INITIAL,cpp_comment,with_syntax>"/*" yy_push_state(cpp_comment);
134 * This is state is being set from corresponding .y module when
135 * higher-level data is necessary to make proper parsing of the
136 * underlying data. Thus, we enter the <opaque> state and save
137 * everything for later processing.
142 yy_push_state(opaque);
143 asn1p_lval.tv_opaque.buf = strdup(yytext);
144 asn1p_lval.tv_opaque.len = yyleng;
150 asn1p_lval.tv_opaque.buf = strdup(yytext);
151 asn1p_lval.tv_opaque.len = yyleng;
156 asn1p_lval.tv_opaque.buf = strdup(yytext);
157 asn1p_lval.tv_opaque.len = yyleng;
163 "ASN.1 Parser synchronization failure: "
164 "\"%s\" at line %d must not appear "
165 "inside value definition\n",
171 asn1p_lval.tv_opaque.buf = strdup(yytext);
172 asn1p_lval.tv_opaque.len = yyleng;
179 asn1p_lval.tv_opaque.buf = 0;
180 asn1p_lval.tv_opaque.len = 0;
181 QAPPEND(yytext+1, yyleng-1);
182 yy_push_state(quoted);
186 \"\" { QAPPEND(yytext, yyleng-1); } /* Add a single quote */
187 [^\"]+ { QAPPEND(yytext, yyleng); }
191 /* Do not append last quote:
192 // QAPPEND(yytext, yyleng); */
194 if(asn1p_lexer_pedantic_1990
195 && strchr(yytext, '\n')) {
196 fprintf(stderr, "%s: "
197 "Newlines are prohibited by ASN.1:1990\n",
198 asn1p_lval.tv_opaque.buf);
209 const char *s = "ENCODING-CONTROL";
210 const char *p = s + sizeof("ENCODING-CONTROL") - 2;
211 for(; p >= s; p--) unput(*p);
214 END unput('D'); unput('N'); unput('E'); yy_pop_state();
217 . /* Eat everything else */
221 '[0-9A-F \t\r\v\f\n]+'H {
222 /* " \t\r\n" weren't allowed in ASN.1:1990. */
223 asn1p_lval.tv_str = strdup(yytext);
227 '[01 \t\r\v\f\n]+'B {
228 /* " \t\r\n" weren't allowed in ASN.1:1990. */
229 asn1p_lval.tv_str = strdup(yytext);
235 asn1p_lval.a_int = _lex_atoi(yytext);
238 return TOK_number_negative;
242 asn1p_lval.a_int = _lex_atoi(yytext);
249 asn1p_lval.a_int = _lex_atoi(yytext);
255 [-+]?[0-9]+[.]?([eE][-+]?)?[0-9]+ {
256 asn1p_lval.a_dbl = _lex_atod(yytext);
259 return TOK_realnumber;
262 ABSENT return TOK_ABSENT;
265 /* Appeared in 1990, removed in 1997 */
266 if(TYPE_LIFETIME(1990, 1997))
268 fprintf(stderr, "Keyword \"%s\" at line %d "
269 "is obsolete\n", yytext, yylineno);
272 APPLICATION return TOK_APPLICATION;
273 AUTOMATIC return TOK_AUTOMATIC;
275 if(asn1p_lexer_extended_values) {
276 yy_push_state(extended_values);
282 if(TYPE_LIFETIME(1994, 0))
283 return TOK_BMPString;
286 BOOLEAN return TOK_BOOLEAN;
288 CHARACTER return TOK_CHARACTER;
289 CHOICE return TOK_CHOICE;
290 CLASS return TOK_CLASS;
291 COMPONENT return TOK_COMPONENT;
292 COMPONENTS return TOK_COMPONENTS;
293 CONSTRAINED return TOK_CONSTRAINED;
294 CONTAINING return TOK_CONTAINING;
295 DEFAULT return TOK_DEFAULT;
297 /* Appeared in 1990, removed in 1997 */
298 if(TYPE_LIFETIME(1990, 1997))
300 fprintf(stderr, "Keyword \"%s\" at line %d "
301 "is obsolete\n", yytext, yylineno);
302 /* Deprecated since */
305 DEFINITIONS return TOK_DEFINITIONS;
306 EMBEDDED return TOK_EMBEDDED;
307 ENCODED return TOK_ENCODED;
308 ENCODING-CONTROL return TOK_ENCODING_CONTROL;
310 if(YYSTATE == extended_values) {
315 ENUMERATED return TOK_ENUMERATED;
316 EXCEPT return TOK_EXCEPT;
317 EXPLICIT return TOK_EXPLICIT;
318 EXPORTS return TOK_EXPORTS;
319 EXTENSIBILITY return TOK_EXTENSIBILITY;
320 EXTERNAL return TOK_EXTERNAL;
321 FALSE return TOK_FALSE;
322 FROM return TOK_FROM;
323 GeneralizedTime return TOK_GeneralizedTime;
324 GeneralString return TOK_GeneralString;
325 GraphicString return TOK_GraphicString;
326 IA5String return TOK_IA5String;
327 IDENTIFIER return TOK_IDENTIFIER;
328 IMPLICIT return TOK_IMPLICIT;
329 IMPLIED return TOK_IMPLIED;
330 IMPORTS return TOK_IMPORTS;
331 INCLUDES return TOK_INCLUDES;
332 INSTANCE return TOK_INSTANCE;
333 INSTRUCTIONS return TOK_INSTRUCTIONS;
334 INTEGER return TOK_INTEGER;
335 INTERSECTION return TOK_INTERSECTION;
336 ISO646String return TOK_ISO646String;
339 MINUS-INFINITY return TOK_MINUS_INFINITY;
340 NULL return TOK_NULL;
341 NumericString return TOK_NumericString;
342 OBJECT return TOK_OBJECT;
343 ObjectDescriptor return TOK_ObjectDescriptor;
344 OCTET return TOK_OCTET;
346 OPTIONAL return TOK_OPTIONAL;
347 PATTERN return TOK_PATTERN;
349 PLUS-INFINITY return TOK_PLUS_INFINITY;
350 PRESENT return TOK_PRESENT;
351 PrintableString return TOK_PrintableString;
352 PRIVATE return TOK_PRIVATE;
353 REAL return TOK_REAL;
354 RELATIVE-OID return TOK_RELATIVE_OID;
355 SEQUENCE return TOK_SEQUENCE;
357 SIZE return TOK_SIZE;
358 STRING return TOK_STRING;
359 SYNTAX return TOK_SYNTAX;
360 T61String return TOK_T61String;
361 TAGS return TOK_TAGS;
362 TeletexString return TOK_TeletexString;
363 TRUE return TOK_TRUE;
364 UNION return TOK_UNION;
365 UNIQUE return TOK_UNIQUE;
366 UNIVERSAL return TOK_UNIVERSAL;
368 if(TYPE_LIFETIME(1994, 0))
369 return TOK_UniversalString;
372 UTCTime return TOK_UTCTime;
374 if(TYPE_LIFETIME(1994, 0))
375 return TOK_UTF8String;
378 VideotexString return TOK_VideotexString;
379 VisibleString return TOK_VisibleString;
380 WITH return TOK_WITH;
383 <INITIAL,with_syntax>&[A-Z][A-Za-z0-9]*([-][A-Za-z0-9]+)* {
384 asn1p_lval.tv_str = strdup(yytext);
385 return TOK_typefieldreference;
388 <INITIAL,with_syntax>&[a-z][a-zA-Z0-9]*([-][a-zA-Z0-9]+)* {
389 asn1p_lval.tv_str = strdup(yytext);
390 return TOK_valuefieldreference;
394 [a-z][a-zA-Z0-9]*([-][a-zA-Z0-9]+)* {
395 asn1p_lval.tv_str = strdup(yytext);
396 return TOK_identifier;
400 * objectclassreference
402 <INITIAL,extended_values>[A-Z][A-Z0-9]*([-][A-Z0-9]+)* {
403 asn1p_lval.tv_str = strdup(yytext);
404 return TOK_capitalreference;
408 * typereference, modulereference
409 * NOTE: TOK_objectclassreference must be combined
410 * with this token to produce true typereference.
412 [A-Z][A-Za-z0-9]*([-][A-Za-z0-9]+)* {
413 asn1p_lval.tv_str = strdup(yytext);
414 return TOK_typereference;
417 <INITIAL,extended_values>"::=" return TOK_PPEQ;
419 "..." return TOK_ThreeDots;
420 ".." return TOK_TwoDots;
424 [A-Z][A-Za-z0-9]*([-][A-Za-z0-9]+)* {
425 asn1p_lval.tv_str = strdup(yytext);
430 asn1p_lval.tv_str = strdup(yytext);
435 yy_push_state(with_syntax);
436 asn1p_lval.tv_str = strdup(yytext);
444 asn1p_lval.tv_opaque.buf = strdup(yytext);
445 asn1p_lval.tv_opaque.len = yyleng;
446 return TOK_whitespace;
451 if(YYSTATE == with_syntax) {
452 asn1p_lval.tv_str = strdup(yytext);
462 <INITIAL,extended_values>{WSP}+ /* Ignore whitespace */
465 [{][\t\r\v\f\n ]*[0-7][,][\t\r\v\f\n ]*[0-9]+[\t\r\v\f\n ]*[}] {
466 asn1c_integer_t v1 = -1, v2 = -1;
468 for(p = yytext; *p; p++)
469 if(*p >= '0' && *p <= '9')
470 { v1 = _lex_atoi(p); break; }
471 while(*p >= '0' && *p <= '9') p++; /* Skip digits */
472 for(; *p; p++) if(*p >= '0' && *p <= '9')
473 { v2 = _lex_atoi(p); break; }
474 if(v1 < 0 || v1 > 7) {
475 fprintf(stderr, "%s at line %d: X.680:2003, #37.14 "
476 "mandates 0..7 range for Tuple's TableColumn\n",
480 if(v2 < 0 || v2 > 15) {
481 fprintf(stderr, "%s at line %d: X.680:2003, #37.14 "
482 "mandates 0..15 range for Tuple's TableRow\n",
486 asn1p_lval.a_int = (v1 << 4) + v2;
490 [{][\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 ]*[}] {
491 asn1c_integer_t v1 = -1, v2 = -1, v3 = -1, v4 = -1;
493 for(p = yytext; *p; p++)
494 if(*p >= '0' && *p <= '9')
495 { v1 = _lex_atoi(p); break; }
496 while(*p >= '0' && *p <= '9') p++; /* Skip digits */
497 for(; *p; p++) if(*p >= '0' && *p <= '9')
498 { v2 = _lex_atoi(p); break; }
499 while(*p >= '0' && *p <= '9') p++;
500 for(; *p; p++) if(*p >= '0' && *p <= '9')
501 { v3 = _lex_atoi(p); break; }
502 while(*p >= '0' && *p <= '9') p++;
503 for(; *p; p++) if(*p >= '0' && *p <= '9')
504 { v4 = _lex_atoi(p); break; }
505 if(v1 < 0 || v1 > 127) {
506 fprintf(stderr, "%s at line %d: X.680:2003, #37.12 "
507 "mandates 0..127 range for Quadruple's Group\n",
511 if(v2 < 0 || v2 > 255) {
512 fprintf(stderr, "%s at line %d: X.680:2003, #37.12 "
513 "mandates 0..255 range for Quadruple's Plane\n",
517 if(v3 < 0 || v3 > 255) {
518 fprintf(stderr, "%s at line %d: X.680:2003, #37.12 "
519 "mandates 0..255 range for Quadruple's Row\n",
523 if(v4 < 0 || v4 > 255) {
524 fprintf(stderr, "%s at line %d: X.680:2003, #37.12 "
525 "mandates 0..255 range for Quadruple's Cell\n",
529 asn1p_lval.a_int = (v1 << 24) | (v2 << 16) | (v3 << 8) | v4;
530 return TOK_quadruple;
534 "[[" return TOK_VBracketLeft;
535 "]]" return TOK_VBracketRight;
537 [(){},;:|!.&@\[\]^] return yytext[0];
539 [^A-Za-z0-9:=,{}<.@()[]'\"|&^*;!-] {
540 if(TYPE_LIFETIME(1994, 0))
541 fprintf(stderr, "ERROR: ");
543 "Symbol '%c' at line %d is prohibited "
544 "by ASN.1:1994 and ASN.1:1997\n",
545 yytext[0], yylineno);
546 if(TYPE_LIFETIME(1994, 0))
552 "Unexpected token at line %d: \"%s\"\n",
554 while(YYSTATE != INITIAL)
557 yy_top_state(); /* Just to use this function. */
558 yy_fatal_error("Parse error");
564 while(YYSTATE != INITIAL)
573 * Very dirty but wonderful hack allowing to rule states from within .y file.
575 void asn1p_lexer_hack_push_opaque_state() { yy_push_state(opaque); }
578 * Another hack which disables recognizing some tokens when inside WITH SYNTAX.
580 void asn1p_lexer_hack_enable_with_syntax() { yy_push_state(with_syntax); }
583 void asn1p_lexer_hack_push_encoding_control() {
584 yy_push_state(encoding_control);
587 static asn1c_integer_t
588 _lex_atoi(const char *ptr) {
589 asn1c_integer_t value;
590 if(asn1p_atoi(ptr, &value)) {
592 "Value \"%s\" at line %d is too large "
593 "for this compiler! Please contact the asn1c author.\n",
601 _lex_atod(const char *ptr) {
604 value = strtod(ptr, 0);
607 "Value \"%s\" at line %d is outside of `double` range "
608 "in this compiler! Please contact the asn1c author.\n",