Annotation of embedaddon/confuse/src/lexer.l, revision 1.1.1.1

1.1       misho       1: %{
                      2: /*
                      3:  * Copyright (c) 2002,2003,2007 Martin Hedenfalk <martin@bzero.se>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17: 
                     18: #ifdef HAVE_CONFIG_H
                     19: # include <config.h>
                     20: #endif
                     21: 
                     22: #include <assert.h>
                     23: 
                     24: #ifdef HAVE_STRING_H
                     25: # include <string.h>
                     26: #endif
                     27: #include "confuse.h"
                     28: 
                     29: #include <errno.h>
                     30: 
                     31: #if defined(ENABLE_NLS) && defined(HAVE_GETTEXT)
                     32: # include <libintl.h>
                     33: # define _(str) dgettext(PACKAGE, str)
                     34: #else
                     35: # define _(str) str
                     36: #endif
                     37: #define N_(str) str
                     38: 
                     39: /*
                     40:  * Prevent compilation of static input() function in generated code
                     41:  * This function is never used but GCC 4.3 will warn about it.
                     42:  */
                     43: #define YY_NO_INPUT
                     44: 
                     45: typedef char * YYSTYPE;
                     46: extern YYSTYPE cfg_yylval;
                     47: 
                     48: #define YY_DECL int cfg_yylex ( cfg_t *cfg )
                     49: 
                     50: /* temporary buffer for the quoted strings scanner
                     51:  */
                     52: char *cfg_qstring = NULL;
                     53: static unsigned int qstring_index = 0;
                     54: static unsigned int qstring_len = 0;
                     55: static void qputc(char ch);
                     56: #define CFG_QSTRING_BUFSIZ 32
                     57: 
                     58: #define MAX_INCLUDE_DEPTH 10
                     59: struct {
                     60:     YY_BUFFER_STATE state;
                     61:     char *filename;
                     62:     unsigned int line;
                     63: } cfg_include_stack[MAX_INCLUDE_DEPTH];
                     64: int cfg_include_stack_ptr = 0;
                     65: 
                     66: static YY_BUFFER_STATE pre_string_scan_state = 0;
                     67: static YY_BUFFER_STATE string_scan_state = 0;
                     68: 
                     69: %}
                     70: 
                     71: %option noyywrap
                     72: 
                     73:  /* start conditions
                     74:   */
                     75: %x comment
                     76: %x dq_str
                     77: %x sq_str
                     78: 
                     79: %%
                     80: 
                     81: [ \t]+    /* eat up whitespace */
                     82: 
                     83: \n   cfg->line++; /* keep track of line number */
                     84: 
                     85: ("#"|"//")[^\n]*     /* eat up one-line comments */
                     86: 
                     87:  /* special keywords/symbols
                     88:   */
                     89: "{"         { cfg_yylval = yytext; return '{'; }
                     90: "}"         { cfg_yylval = yytext; return '}'; }
                     91: "("         { cfg_yylval = yytext; return '('; }
                     92: ")"         { cfg_yylval = yytext; return ')'; }
                     93: "="         { cfg_yylval = yytext; return '='; }
                     94: "+="        { cfg_yylval = yytext; return '+'; }
                     95: ","         { cfg_yylval = yytext; return ','; }
                     96: 
                     97:  /* handle multi-line C-style comments
                     98:   */
                     99: "/*"         BEGIN(comment);
                    100: <comment>[^*\n]*        /* eat anything that's not a '*' */
                    101: <comment>"*"+[^*/\n]*   /* eat up '*'s not followed by '/'s */
                    102: <comment>\n             cfg->line++;
                    103: <comment>"*"+"/"        BEGIN(INITIAL);
                    104: 
                    105:  /* handle C-style strings
                    106:   */
                    107: "\""    {
                    108:     qstring_index = 0;
                    109:     BEGIN(dq_str);
                    110: }
                    111: <dq_str>\"  { /* saw closing quote - all done */
                    112:     BEGIN(INITIAL);
                    113:     qputc('\0');
                    114:     cfg_yylval = cfg_qstring;
                    115:     return CFGT_STR;
                    116:  }
                    117: <dq_str>$\{[^}]*\} { /* environment variable substitution */
                    118:     char *var;
                    119:     char *e;
                    120:     yytext[strlen(yytext) - 1] = 0;
                    121:     e = strchr(yytext+2, ':');
                    122:     if(e && e[1] == '-')
                    123:         *e = 0;
                    124:     else
                    125:         e = 0;
                    126:     var = getenv(yytext+2);
                    127:     if(!var && e)
                    128:         var = e+2;
                    129:     while(var && *var)
                    130:         qputc(*var++);
                    131: }
                    132: <dq_str>\n   {
                    133:     qputc('\n');
                    134:     cfg->line++;
                    135: }
                    136: <dq_str>\\\n { /* allow continuing on next line */
                    137:     /* no-op */
                    138:     cfg->line++;
                    139: }
                    140: <dq_str>\\[0-7]{1,3} {  /* octal escape sequence */
                    141:     unsigned int result;
                    142:     sscanf(yytext + 1, "%o", &result);
                    143:     if(result > 0xFF) {
                    144:         cfg_error(cfg, _("invalid octal number '%s'"), yytext);
                    145:         return 0;
                    146:     }
                    147:     qputc(result);
                    148:  }
                    149: <dq_str>\\[0-9]+   {
                    150:     cfg_error(cfg, _("bad escape sequence '%s'"), yytext);
                    151:     return 0;
                    152: }
                    153: <dq_str>"\\x"[0-9A-Fa-f]{1,2} { /* hexadecimal escape sequence */
                    154:     unsigned int result;
                    155:     sscanf(yytext + 2, "%x", &result);
                    156:     qputc(result);
                    157: }
                    158: <dq_str>\\n  {
                    159:     qputc('\n');
                    160: }
                    161: <dq_str>\\r  {
                    162:     qputc('\r');
                    163: }
                    164: <dq_str>\\b  {
                    165:     qputc('\b');
                    166: }
                    167: <dq_str>\\f  {
                    168:     qputc('\f');
                    169: }
                    170: <dq_str>\\a  {
                    171:     qputc('\007');
                    172: }
                    173: <dq_str>\\e  {
                    174:     qputc('\033');
                    175: }
                    176: <dq_str>\\t  {
                    177:     qputc('\t');
                    178: }
                    179: <dq_str>\\v  {
                    180:     qputc('\v');
                    181: }
                    182: <dq_str>\\.  {
                    183:     qputc(yytext[1]);
                    184: }
                    185: <dq_str>[^\\\"\n]+  {
                    186:     char *yptr = yytext;
                    187:     while(*yptr) {
                    188:         qputc(*yptr++);
                    189:     }
                    190: }
                    191: 
                    192:     /* single-quoted string ('...') */
                    193: "\'" {
                    194:     qstring_index = 0;
                    195:     BEGIN(sq_str);
                    196: }
                    197: <sq_str>\' { /* saw closing quote - all done */
                    198:     BEGIN(INITIAL);
                    199:     qputc('\0');
                    200:     cfg_yylval = cfg_qstring;
                    201:     return CFGT_STR;
                    202: }
                    203: <sq_str>\n   {
                    204:     qputc('\n');
                    205:     cfg->line++;
                    206: }
                    207: <sq_str>\\\n { /* allow continuing on next line */
                    208:     /* no-op */
                    209:     cfg->line++;
                    210: }
                    211: <sq_str>\\[\\\'] {
                    212:     qputc(yytext[1]);
                    213: }
                    214: <sq_str>\\[^\\\'] {
                    215:     qputc(yytext[0]);
                    216:     qputc(yytext[1]);
                    217: }
                    218: <sq_str>[^\\\'\n]+ {
                    219:     char *cp = yytext;
                    220:     while(*cp != '\0') {
                    221:         qputc(*cp++);
                    222:     }
                    223: }
                    224: <sq_str><<EOF>> {
                    225:     cfg_error(cfg, _("unterminated string constant"));
                    226:     return 0;
                    227: }
                    228: 
                    229: <<EOF>> {
                    230:              if (cfg_include_stack_ptr <= 0)
                    231:              {
                    232:                  return EOF;
                    233:              }
                    234:              else
                    235:              {
                    236:                  yy_delete_buffer( YY_CURRENT_BUFFER );
                    237:                  fclose(cfg_yyin);
                    238:                  cfg_yyin = 0;
                    239:                  --cfg_include_stack_ptr;
                    240:                  yy_switch_to_buffer(
                    241:                       cfg_include_stack[cfg_include_stack_ptr].state );
                    242:                  free(cfg->filename);
                    243:                  cfg->filename = cfg_include_stack[cfg_include_stack_ptr].filename;
                    244:                  cfg->line = cfg_include_stack[cfg_include_stack_ptr].line;
                    245:              }
                    246: }
                    247: 
                    248: $\{[^}]*\} {
                    249:     char *var;
                    250:     char *e;
                    251:     yytext[strlen(yytext) - 1] = 0;
                    252:     e = strchr(yytext+2, ':');
                    253:     if(e && e[1] == '-')
                    254:         *e = 0;
                    255:     else
                    256:         e = 0;
                    257:     var = getenv(yytext+2);
                    258:     if(!var && e)
                    259:         var = e+2;
                    260:     if(!var)
                    261:         var = "";
                    262:     cfg_yylval = var;
                    263:     return CFGT_STR;
                    264: }
                    265: 
                    266:  /* an unquoted string
                    267:   * a slash can't be followed by another slash (c++
                    268:   * comment) or an asterisk (C multi-line comment)
                    269:   */
                    270: (\/[^ #\"\'\t\n\r={}()+,\/*]|[^ #\"\'\t\n\r={}()+,\*])+ {
                    271:     cfg_yylval = yytext;
                    272:     return CFGT_STR;
                    273:  }
                    274: 
                    275: . /* eat any non-matching characters */
                    276: 
                    277: %%
                    278: 
                    279: void cfg_dummy_function(void)
                    280: {
                    281:     /* please compiler :-)
                    282:      * otherwise "defined but not used" warning
                    283:      */
                    284:     yyunput(0, 0);
                    285: }
                    286: 
                    287: int cfg_lexer_include(cfg_t *cfg, const char *filename)
                    288: {
                    289:     char *xfilename;
                    290: 
                    291:     if(cfg_include_stack_ptr >= MAX_INCLUDE_DEPTH) {
                    292:         cfg_error(cfg, _("includes nested too deeply"));
                    293:         return 1;
                    294:     }
                    295: 
                    296:     cfg_include_stack[cfg_include_stack_ptr].state = YY_CURRENT_BUFFER;
                    297:     cfg_include_stack[cfg_include_stack_ptr].filename = cfg->filename;
                    298:     cfg_include_stack[cfg_include_stack_ptr].line = cfg->line;
                    299:     cfg_include_stack_ptr++;
                    300: 
                    301:     xfilename = cfg_tilde_expand(filename);
                    302: 
                    303:     cfg_yyin = fopen(xfilename, "r");
                    304: 
                    305:     if(!cfg_yyin) {
                    306:         cfg_error(cfg, "%s: %s", xfilename, strerror(errno));
                    307:         free(xfilename);
                    308:         return 1;
                    309:     }
                    310: 
                    311:     cfg->filename = xfilename;
                    312:     cfg->line = 1;
                    313: 
                    314:     yy_switch_to_buffer(yy_create_buffer(cfg_yyin, YY_BUF_SIZE));
                    315:     return 0;
                    316: }
                    317: 
                    318: /* write a character to the quoted string buffer, and reallocate as
                    319:  * necessary
                    320:  */
                    321: static void qputc(char ch)
                    322: {
                    323:     if(qstring_index >= qstring_len) {
                    324:         qstring_len += CFG_QSTRING_BUFSIZ;
                    325:         cfg_qstring = (char *)realloc(cfg_qstring, qstring_len);
                    326:         assert(cfg_qstring);
                    327:         memset(cfg_qstring + qstring_index, 0, CFG_QSTRING_BUFSIZ);
                    328:     }
                    329:     cfg_qstring[qstring_index++] = ch;
                    330: }
                    331: 
                    332: void cfg_scan_string_begin(const char *buf)
                    333: {
                    334:     pre_string_scan_state = YY_CURRENT_BUFFER;
                    335: 
                    336:     /* yy_scan_string does a yy_switch_to_buffer call for us
                    337:      */
                    338:     string_scan_state = yy_scan_string(buf);
                    339: }
                    340: 
                    341: void cfg_scan_string_end(void)
                    342: {
                    343:     /* restore to previous state
                    344:      */
                    345:     yy_delete_buffer(string_scan_state);
                    346:     if (pre_string_scan_state)
                    347:         yy_switch_to_buffer(pre_string_scan_state);
                    348:     free(cfg_qstring);
                    349:     cfg_qstring = 0;
                    350:     qstring_index = qstring_len = 0;
                    351:     string_scan_state = 0;
                    352: }
                    353: 
                    354: static YY_BUFFER_STATE pre_fp_scan_state;
                    355: static YY_BUFFER_STATE fp_scan_state;
                    356: 
                    357: void cfg_scan_fp_begin(FILE *fp)
                    358: {
                    359:     pre_fp_scan_state = YY_CURRENT_BUFFER;
                    360:     fp_scan_state = yy_create_buffer(fp, YY_BUF_SIZE);
                    361:     yy_switch_to_buffer(fp_scan_state);
                    362: }
                    363: 
                    364: void cfg_scan_fp_end(void)
                    365: {
                    366:     /* restore to previous state
                    367:      */
                    368:     yy_delete_buffer(fp_scan_state);
                    369:     if(pre_fp_scan_state)
                    370:         yy_switch_to_buffer(pre_fp_scan_state);
                    371:     free(cfg_qstring);
                    372:     cfg_qstring = 0;
                    373:     qstring_index = qstring_len = 0;
                    374: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>