File diff 000000000000 → d6faa5ffcedf
libconfig-1.4.9/lib/scanner.l
Show inline comments
 
new file 100644
 
/* -*- mode: C -*- */
 
/* --------------------------------------------------------------------------
 
   libconfig - A library for processing structured configuration files
 
   Copyright (C) 2005-2010  Mark A Lindner
 

	
 
   This file is part of libconfig.
 

	
 
   This library is free software; you can redistribute it and/or
 
   modify it under the terms of the GNU Lesser General Public License
 
   as published by the Free Software Foundation; either version 2.1 of
 
   the License, or (at your option) any later version.
 

	
 
   This library is distributed in the hope that it will be useful, but
 
   WITHOUT ANY WARRANTY; without even the implied warranty of
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
   Lesser General Public License for more details.
 

	
 
   You should have received a copy of the GNU Library General Public
 
   License along with this library; if not, see
 
   <http://www.gnu.org/licenses/>.
 
   ----------------------------------------------------------------------------
 
*/
 

	
 
%option nounistd
 
%option reentrant
 
%option noyywrap
 
%option yylineno
 
%option nounput
 
%option bison-bridge
 
%option header-file="scanner.h"
 
%option outfile="lex.yy.c"
 
%option extra-type="struct scan_context *"
 

	
 
%{
 

	
 
#ifdef _MSC_VER
 
#pragma warning (disable: 4996)
 
#endif
 

	
 
#include <stdlib.h>
 
#include <ctype.h>
 
#include <string.h>
 
#include "grammar.h"
 
#include "wincompat.h"
 
#include "parsectx.h"
 
#include "scanctx.h"
 

	
 
#define YY_NO_INPUT // Suppress generation of useless input() function
 

	
 
static unsigned long long fromhex(const char *s)
 
{
 
#ifdef __MINGW32__
 

	
 
  /* MinGW's strtoull() seems to be broken; it only returns the lower
 
   * 32 bits...
 
   */
 

	
 
  const char *p = s;
 
  unsigned long long val = 0;
 

	
 
  if(*p != '0')
 
    return(0);
 

	
 
  ++p;
 

	
 
  if(*p != 'x' && *p != 'X')
 
    return(0);
 

	
 
  for(++p; isxdigit(*p); ++p)
 
  {
 
    val <<= 4;
 
    val |= ((*p < 'A') ? (*p & 0xF) : (9 + (*p & 0x7)));
 
  }
 

	
 
  return(val);
 

	
 
#else /* ! __MINGW32__ */
 

	
 
  return(strtoull(s, NULL, 16));
 

	
 
#endif /* __MINGW32__ */
 
}
 

	
 
%}
 

	
 
true              [Tt][Rr][Uu][Ee]
 
false             [Ff][Aa][Ll][Ss][Ee]
 
name              [A-Za-z\*][-A-Za-z0-9_\*]*
 
integer           [-+]?[0-9]+
 
integer64         [-+]?[0-9]+L(L)?
 
hex               0[Xx][0-9A-Fa-f]+
 
hex64             0[Xx][0-9A-Fa-f]+L(L)?
 
hexchar           \\[Xx][0-9A-Fa-f]{2}
 
float             ([-+]?([0-9]*)?\.[0-9]*([eE][-+]?[0-9]+)?)|([-+]?([0-9]+)(\.[0-9]*)?[eE][-+]?[0-9]+)
 
comment           (#|\/\/).*$
 
include_open      ^[ \t]*@include[ \t]+\"
 

	
 
%x COMMENT STRING INCLUDE
 

	
 
%%
 

	
 
\/\*              { BEGIN COMMENT; }
 
<COMMENT>\*\/     { BEGIN INITIAL; }
 
<COMMENT>.        { /* ignore */ }
 
<COMMENT>\n       { /* ignore */ }
 

	
 
\"                { BEGIN STRING; }
 
<STRING>[^\"\\]+  { scanctx_append_string(yyextra, yytext); }
 
<STRING>\\n       { scanctx_append_string(yyextra, "\n"); }
 
<STRING>\\r       { scanctx_append_string(yyextra, "\r"); }
 
<STRING>\\t       { scanctx_append_string(yyextra, "\t"); }
 
<STRING>\\f       { scanctx_append_string(yyextra, "\f"); }
 
<STRING>\\\\      { scanctx_append_string(yyextra, "\\"); }
 
<STRING>\\\"      { scanctx_append_string(yyextra, "\""); }
 
<STRING>{hexchar} {
 
                    char c[2] = { (char)(strtol(yytext + 2, NULL, 16) & 0xFF),
 
                                  0 };
 
                    scanctx_append_string(yyextra, c);
 
                  }
 
<STRING>\\        { scanctx_append_string(yyextra, "\\"); }
 
<STRING>\"        {
 
                    yylval->sval = scanctx_take_string(yyextra);
 
                    BEGIN INITIAL;
 
                    return(TOK_STRING);
 
                  }
 

	
 
{include_open}    { BEGIN INCLUDE; }
 
<INCLUDE>[^\"\\]+ { scanctx_append_string(yyextra, yytext); }
 
<INCLUDE>\\\\     { scanctx_append_string(yyextra, "\\"); }
 
<INCLUDE>\\\"     { scanctx_append_string(yyextra, "\""); }
 
<INCLUDE>\"       {
 
                    const char *error;
 
                    FILE *fp = scanctx_push_include(yyextra,
 
                                                    (void *)YY_CURRENT_BUFFER,
 
                                                    &error);
 
                    if(fp)
 
                    {
 
                      yyin = fp;
 
                      yy_switch_to_buffer(
 
                        yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner),
 
                        yyscanner);
 
                    }
 
                    else
 
                    {
 
                      yyextra->config->error_text = error;
 
                      yyextra->config->error_file = scanctx_current_filename(
 
                        yyextra);
 
                      yyextra->config->error_line = libconfig_yyget_lineno(
 
                        yyscanner);
 
                      return TOK_ERROR;
 
                    }
 
                    BEGIN INITIAL;
 
                  }
 

	
 
\n|\r|\f          { /* ignore */ }
 
[ \t]+            { /* ignore */ }
 

	
 
\=|\:             { return(TOK_EQUALS); }
 
,                 { return(TOK_COMMA); }
 
\{                { return(TOK_GROUP_START); }
 
\}                { return(TOK_GROUP_END); }
 
{true}            { yylval->ival = 1; return(TOK_BOOLEAN); }
 
{false}           { yylval->ival = 0; return(TOK_BOOLEAN); }
 
{name}            { yylval->sval = yytext; return(TOK_NAME); }
 
{float}           { yylval->fval = atof(yytext); return(TOK_FLOAT); }
 
{integer}         { yylval->ival = atoi(yytext); return(TOK_INTEGER); }
 
{integer64}       { yylval->llval = atoll(yytext); return(TOK_INTEGER64); }
 
{hex}             {
 
                    yylval->ival = strtoul(yytext, NULL, 16);
 
                    return(TOK_HEX);
 
                  }
 
{hex64}           { yylval->llval = fromhex(yytext); return(TOK_HEX64); }
 
\[                { return(TOK_ARRAY_START); }
 
\]                { return(TOK_ARRAY_END); }
 
\(                { return(TOK_LIST_START); }
 
\)                { return(TOK_LIST_END); }
 
;                 { return(TOK_SEMICOLON); }
 
{comment}         { /* ignore */ }
 
.                 { return(TOK_GARBAGE); }
 

	
 
<<EOF>>           {
 
                    YY_BUFFER_STATE buf = (YY_BUFFER_STATE)scanctx_pop_include(
 
                      yyextra);
 
                    if(buf)
 
                    {
 
                      yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner);
 
                      yy_switch_to_buffer(buf, yyscanner);
 
                    }
 
                    else
 
                      yyterminate();
 
                  }