File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / confuse / src / lexer.l
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Jan 24 14:48:56 2017 UTC (7 years, 5 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    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>