"Fossies" - the Fresh Open Source Software Archive

Member "nsd-4.3.6/zlexer.lex" (6 Apr 2021, 10089 Bytes) of package /linux/misc/dns/nsd-4.3.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "zlexer.lex" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.3.5_vs_4.3.6.

    1 %{
    2 /*
    3  * zlexer.lex - lexical analyzer for (DNS) zone files
    4  * 
    5  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved
    6  *
    7  * See LICENSE for the license.
    8  *
    9  */
   10 /* because flex keeps having sign-unsigned compare problems that are unfixed*/
   11 #if defined(__clang__)||(defined(__GNUC__)&&((__GNUC__ >4)||(defined(__GNUC_MINOR__)&&(__GNUC__ ==4)&&(__GNUC_MINOR__ >=2))))
   12 #pragma GCC diagnostic ignored "-Wsign-compare"
   13 #endif
   14 /* ignore fallthrough warnings in the generated parse code case statements */
   15 #if defined(__clang__)||(defined(__GNUC__)&&(__GNUC__ >=7))
   16 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
   17 #endif
   18 
   19 #include "config.h"
   20 
   21 #include <ctype.h>
   22 #include <errno.h>
   23 #include <string.h>
   24 #include <strings.h>
   25 
   26 #include "zonec.h"
   27 #include "dname.h"
   28 #include "zparser.h"
   29 
   30 #if 0
   31 #define LEXOUT(s)  printf s /* used ONLY when debugging */
   32 #else
   33 #define LEXOUT(s)
   34 #endif
   35 
   36 enum lexer_state {
   37     EXPECT_OWNER,
   38     PARSING_OWNER,
   39     PARSING_TTL_CLASS_TYPE,
   40     PARSING_RDATA
   41 };
   42 
   43 static int parse_token(int token, char *yytext, enum lexer_state *lexer_state);
   44 
   45 static YY_BUFFER_STATE include_stack[MAXINCLUDES];
   46 static zparser_type zparser_stack[MAXINCLUDES];
   47 static int include_stack_ptr = 0;
   48 
   49 /*
   50  * Saves the file specific variables on the include stack.
   51  */
   52 static void
   53 push_parser_state(FILE *input)
   54 {
   55     zparser_stack[include_stack_ptr].filename = parser->filename;
   56     zparser_stack[include_stack_ptr].line = parser->line;
   57     zparser_stack[include_stack_ptr].origin = parser->origin;
   58     include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
   59     yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
   60     ++include_stack_ptr;
   61 }
   62 
   63 /*
   64  * Restores the file specific variables from the include stack.
   65  */
   66 static void
   67 pop_parser_state(void)
   68 {
   69     if (parser->filename)
   70         region_recycle(parser->region, (void *)parser->filename,
   71             strlen(parser->filename)+1);
   72 
   73     --include_stack_ptr;
   74     parser->filename = zparser_stack[include_stack_ptr].filename;
   75     parser->line = zparser_stack[include_stack_ptr].line;
   76     parser->origin = zparser_stack[include_stack_ptr].origin;
   77     yy_delete_buffer(YY_CURRENT_BUFFER);
   78     yy_switch_to_buffer(include_stack[include_stack_ptr]);
   79 }
   80 
   81 static YY_BUFFER_STATE oldstate;
   82 /* Start string scan */
   83 void
   84 parser_push_stringbuf(char* str)
   85 {
   86     oldstate = YY_CURRENT_BUFFER;
   87     yy_switch_to_buffer(yy_scan_string(str));
   88 }
   89 
   90 void
   91 parser_pop_stringbuf(void)
   92 {
   93     yy_delete_buffer(YY_CURRENT_BUFFER);
   94     yy_switch_to_buffer(oldstate);
   95     oldstate = NULL;
   96 }
   97 
   98     static int paren_open = 0;
   99     static enum lexer_state lexer_state = EXPECT_OWNER;
  100 void
  101 parser_flush(void)
  102 {
  103     YY_FLUSH_BUFFER;
  104     paren_open = 0;
  105     lexer_state = EXPECT_OWNER;
  106 }
  107 
  108 #ifndef yy_set_bol /* compat definition, for flex 2.4.6 */
  109 #define yy_set_bol(at_bol) \
  110     { \
  111         if ( ! yy_current_buffer ) \
  112             yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
  113         yy_current_buffer->yy_ch_buf[0] = ((at_bol)?'\n':' '); \
  114     }
  115 #endif
  116     
  117 %}
  118 %option noinput
  119 %option nounput
  120 %{
  121 #ifndef YY_NO_UNPUT
  122 #define YY_NO_UNPUT 1
  123 #endif
  124 #ifndef YY_NO_INPUT
  125 #define YY_NO_INPUT 1
  126 #endif
  127 %}
  128 
  129 SPACE   [ \t]
  130 LETTER  [a-zA-Z]
  131 NEWLINE [\n\r]
  132 ZONESTR [^ \t\n\r();.\"\$]|\\.|\\\n
  133 CHARSTR [^ \t\n\r();.\"]|\\.|\\\n
  134 QUOTE   \"
  135 DOLLAR  \$
  136 COMMENT ;
  137 DOT     \.
  138 BIT [^\]\n]|\\.
  139 ANY     [^\"\n\\]|\\.
  140 
  141 %x  incl bitlabel quotedstring
  142 
  143 %%
  144 {SPACE}*{COMMENT}.* /* ignore */
  145 ^{DOLLAR}TTL            { lexer_state = PARSING_RDATA; return DOLLAR_TTL; }
  146 ^{DOLLAR}ORIGIN         { lexer_state = PARSING_RDATA; return DOLLAR_ORIGIN; }
  147 
  148     /*
  149      * Handle $INCLUDE directives.  See
  150      * http://dinosaur.compilertools.net/flex/flex_12.html#SEC12.
  151      */
  152 ^{DOLLAR}INCLUDE        {
  153     BEGIN(incl);
  154     /* ignore case statement fallthrough on incl<EOF> flex rule */
  155 }
  156 <incl>\n        |
  157 <incl><<EOF>>       {
  158     int error_occurred = parser->error_occurred;
  159     BEGIN(INITIAL);
  160     zc_error("missing file name in $INCLUDE directive");
  161     yy_set_bol(1); /* Set beginning of line, so "^" rules match.  */
  162     ++parser->line;
  163     parser->error_occurred = error_occurred;
  164 }
  165 <incl>.+        {   
  166     char *tmp;
  167     domain_type *origin = parser->origin;
  168     int error_occurred = parser->error_occurred;
  169     
  170     BEGIN(INITIAL);
  171     if (include_stack_ptr >= MAXINCLUDES ) {
  172         zc_error("includes nested too deeply, skipped (>%d)",
  173              MAXINCLUDES);
  174     } else {
  175         FILE *input;
  176 
  177         /* Remove trailing comment.  */
  178         tmp = strrchr(yytext, ';');
  179         if (tmp) {
  180             *tmp = '\0';
  181         }
  182         strip_string(yytext);
  183         
  184         /* Parse origin for include file.  */
  185         tmp = strrchr(yytext, ' ');
  186         if (!tmp) {
  187             tmp = strrchr(yytext, '\t');
  188         }
  189         if (tmp) {
  190             const dname_type *dname;
  191             
  192             /* split the original yytext */
  193             *tmp = '\0';
  194             strip_string(yytext);
  195 
  196             dname = dname_parse(parser->region, tmp + 1);
  197             if (!dname) {
  198                 zc_error("incorrect include origin '%s'",
  199                      tmp + 1);
  200             } else if (*(tmp + strlen(tmp + 1)) != '.') {
  201                 zc_error("$INCLUDE directive requires absolute domain name");
  202             } else {
  203                 origin = domain_table_insert(
  204                     parser->db->domains, dname);
  205             }
  206         }
  207         
  208         if (strlen(yytext) == 0) {
  209             zc_error("missing file name in $INCLUDE directive");
  210         } else if (!(input = fopen(yytext, "r"))) {
  211             zc_error("cannot open include file '%s': %s",
  212                  yytext, strerror(errno));
  213         } else {
  214             /* Initialize parser for include file.  */
  215             char *filename = region_strdup(parser->region, yytext);
  216             push_parser_state(input); /* Destroys yytext.  */
  217             parser->filename = filename;
  218             parser->line = 1;
  219             parser->origin = origin;
  220             lexer_state = EXPECT_OWNER;
  221         }
  222     }
  223 
  224     parser->error_occurred = error_occurred;
  225 }
  226 <INITIAL><<EOF>>    {
  227     yy_set_bol(1); /* Set beginning of line, so "^" rules match.  */
  228     if (include_stack_ptr == 0) {
  229         yyterminate();
  230     } else {
  231         fclose(yyin);
  232         pop_parser_state();
  233     }
  234 }
  235 ^{DOLLAR}{LETTER}+  { zc_warning("Unknown directive: %s", yytext); }
  236 {DOT}   {
  237     LEXOUT((". "));
  238     return parse_token('.', yytext, &lexer_state);
  239 }
  240 @   {
  241     LEXOUT(("@ "));
  242     return parse_token('@', yytext, &lexer_state);
  243 }
  244 \\# {
  245     LEXOUT(("\\# "));
  246     return parse_token(URR, yytext, &lexer_state);
  247 }
  248 {NEWLINE}   {
  249     ++parser->line;
  250     if (!paren_open) { 
  251         lexer_state = EXPECT_OWNER;
  252         LEXOUT(("NL\n"));
  253         return NL;
  254     } else {
  255         LEXOUT(("SP "));
  256         return SP;
  257     }
  258 }
  259 \(  {
  260     if (paren_open) {
  261         zc_error("nested parentheses");
  262         yyterminate();
  263     }
  264     LEXOUT(("( "));
  265     paren_open = 1;
  266     return SP;
  267 }
  268 \)  {
  269     if (!paren_open) {
  270         zc_error("closing parentheses without opening parentheses");
  271         yyterminate();
  272     }
  273     LEXOUT((") "));
  274     paren_open = 0;
  275     return SP;
  276 }
  277 {SPACE}+    {
  278     if (!paren_open && lexer_state == EXPECT_OWNER) {
  279         lexer_state = PARSING_TTL_CLASS_TYPE;
  280         LEXOUT(("PREV "));
  281         return PREV;
  282     }
  283     if (lexer_state == PARSING_OWNER) {
  284         lexer_state = PARSING_TTL_CLASS_TYPE;
  285     }
  286     LEXOUT(("SP "));
  287     return SP;
  288 }
  289 
  290     /* Bitlabels.  Strip leading and ending brackets.  */
  291 \\\[            { BEGIN(bitlabel); }
  292 <bitlabel><<EOF>>   {
  293     zc_error("EOF inside bitlabel");
  294     BEGIN(INITIAL);
  295     yyrestart(yyin); /* this is so that lex does not give an internal err */
  296     yyterminate();
  297 }
  298 <bitlabel>{BIT}*    { yymore(); }
  299 <bitlabel>\n        { ++parser->line; yymore(); }
  300 <bitlabel>\]        {
  301     BEGIN(INITIAL);
  302     yytext[yyleng - 1] = '\0';
  303     return parse_token(BITLAB, yytext, &lexer_state);
  304 }
  305 
  306     /* Quoted strings.  Strip leading and ending quotes.  */
  307 {QUOTE}         { BEGIN(quotedstring); LEXOUT(("\" ")); }
  308 <quotedstring><<EOF>>   {
  309     zc_error("EOF inside quoted string");
  310     BEGIN(INITIAL);
  311     yyrestart(yyin); /* this is so that lex does not give an internal err */
  312     yyterminate();
  313 }
  314 <quotedstring>{ANY}*    { LEXOUT(("QSTR ")); yymore(); }
  315 <quotedstring>\n    { ++parser->line; yymore(); }
  316 <quotedstring>{QUOTE} {
  317     LEXOUT(("\" "));
  318     BEGIN(INITIAL);
  319     yytext[yyleng - 1] = '\0';
  320     return parse_token(QSTR, yytext, &lexer_state);
  321 }
  322 
  323 {ZONESTR}({CHARSTR})* {
  324     /* Any allowed word.  */
  325     return parse_token(STR, yytext, &lexer_state);
  326 }
  327 . {
  328     zc_error("unknown character '%c' (\\%03d) seen - is this a zonefile?",
  329          (int) yytext[0], (int) yytext[0]);
  330 }
  331 %%
  332 
  333 /*
  334  * Analyze "word" to see if it matches an RR type, possibly by using
  335  * the "TYPExxx" notation.  If it matches, the corresponding token is
  336  * returned and the TYPE parameter is set to the RR type value.
  337  */
  338 static int
  339 rrtype_to_token(const char *word, uint16_t *type) 
  340 {
  341     uint16_t t = rrtype_from_string(word);
  342     if (t != 0) {
  343         rrtype_descriptor_type *entry = rrtype_descriptor_by_type(t);
  344         *type = t;
  345         return entry->token;
  346     }
  347 
  348     return 0;
  349 }
  350 
  351 
  352 /*
  353  * Remove \DDD constructs from the input. See RFC 1035, section 5.1.
  354  */
  355 static size_t
  356 zoctet(char *text) 
  357 {
  358     /*
  359      * s follows the string, p lags behind and rebuilds the new
  360      * string
  361      */
  362     char *s;
  363     char *p;
  364     
  365     for (s = p = text; *s; ++s, ++p) {
  366         assert(p <= s);
  367         if (s[0] != '\\') {
  368             /* Ordinary character.  */
  369             *p = *s;
  370         } else if (isdigit((unsigned char)s[1]) && isdigit((unsigned char)s[2]) && isdigit((unsigned char)s[3])) {
  371             /* \DDD escape.  */
  372             int val = (hexdigit_to_int(s[1]) * 100 +
  373                    hexdigit_to_int(s[2]) * 10 +
  374                    hexdigit_to_int(s[3]));
  375             if (0 <= val && val <= 255) {
  376                 s += 3;
  377                 *p = val;
  378             } else {
  379                 zc_warning("text escape \\DDD overflow");
  380                 *p = *++s;
  381             }
  382         } else if (s[1] != '\0') {
  383             /* \X where X is any character, keep X.  */
  384             *p = *++s;
  385         } else {
  386             /* Trailing backslash, ignore it.  */
  387             zc_warning("trailing backslash ignored");
  388             --p;
  389         }
  390     }
  391     *p = '\0';
  392     return p - text;
  393 }
  394 
  395 static int
  396 parse_token(int token, char *yytext, enum lexer_state *lexer_state)
  397 {
  398     size_t len;
  399     char *str;
  400 
  401     if (*lexer_state == EXPECT_OWNER) {
  402         *lexer_state = PARSING_OWNER;
  403     } else if (*lexer_state == PARSING_TTL_CLASS_TYPE) {
  404         const char *t;
  405         int token;
  406         uint16_t rrclass;
  407         
  408         /* type */
  409         token = rrtype_to_token(yytext, &yylval.type);
  410         if (token != 0) {
  411             *lexer_state = PARSING_RDATA;
  412             LEXOUT(("%d[%s] ", token, yytext));
  413             return token;
  414         }
  415 
  416         /* class */
  417         rrclass = rrclass_from_string(yytext);
  418         if (rrclass != 0) {
  419             yylval.klass = rrclass;
  420             LEXOUT(("CLASS "));
  421             return T_RRCLASS;
  422         }
  423 
  424         /* ttl */
  425         yylval.ttl = strtottl(yytext, &t);
  426         if (*t == '\0') {
  427             LEXOUT(("TTL "));
  428             return T_TTL;
  429         }
  430     }
  431 
  432     str = region_strdup(parser->rr_region, yytext);
  433     len = zoctet(str);
  434 
  435     yylval.data.str = str;
  436     yylval.data.len = len;
  437     
  438     LEXOUT(("%d[%s] ", token, yytext));
  439     return token;
  440 }