/* -*- mode: C -*- */
/* --------------------------------------------------------------------------
libconfig - A library for processing structured configuration files
Copyright (C) 2013-2020 Hercules Dev Team
Copyright (C) 2005-2014 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
.
----------------------------------------------------------------------------
*/
%option nounistd
%option never-interactive
%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
#include
#include
#include
#include "parsectx.h"
#include "scanctx.h"
#include "grammar.h"
#include "wincompat.h"
#define YY_NO_INPUT // Suppress generation of useless input() function
/**
* converts a hexadecimal number literal to an ull integer
*
* @param p - a pointer to the hexacimal expression to parse
* @returns the resulting unsigned long long integer
*/
static unsigned long long fromhex(const char *p)
{
unsigned long long val = 0;
if (*p != '0' || (p[1] != 'x' && p[1] != 'X')) {
return 0;
}
for (p += 2; isxdigit(*p) || *p == '_'; ++p) {
if (*p != '_') {
val <<= 4;
val |= ((*p < 'A') ? (*p & 0xF) : (9 + (*p & 0x7)));
}
}
return val;
}
/**
* converts a binary number literal to an ull integer
*
* @param p - a pointer to the hexacimal expression to parse
* @returns the resulting unsigned long long integer
*/
static unsigned long long frombin (const char *p)
{
unsigned long long val = 0;
if (*p != '0' || (p[1] != 'b' && p[1] != 'B')) {
return 0;
}
for (p += 2; *p == '0' || *p == '1' || *p == '_'; ++p) {
if (*p != '_') {
val <<= 1;
val |= (*p == '0') ? 0 : 1;
}
}
return val;
}
/**
* converts an octal number literal to an ull integer
*
* @param p - a pointer to the hexacimal expression to parse
* @returns the resulting unsigned long long integer
*/
static unsigned long long fromoct (const char *p)
{
unsigned long long val = 0;
if (*p != '0' || (p[1] != 'o' && p[1] != 'O')) {
return 0;
}
for (p += 2; (*p >= '0' && *p <= '7') || *p == '_'; ++p) {
if (*p != '_') {
val <<= 3;
val |= (*p & 0xF);
}
}
return val;
}
/**
* converts a decimal number literal to a ll integer
*
* @param p - a pointer to the hexacimal expression to parse
* @returns the resulting signed long long integer
*/
static long long fromdec (const char *p)
{
unsigned char is_neg = 0;
if (*p == '-') {
is_neg = 1;
p++;
}
long long val = 0;
for (; isdigit(*p) || *p == '_'; ++p) {
if (*p != '_') {
val *= 10;
val += (*p & 0xF);
}
}
return (is_neg == 1) ? -val : val;
}
%}
true [Tt][Rr][Uu][Ee]
false [Ff][Aa][Ll][Ss][Ee]
name [A-Za-z0-9\*][-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)?
bin 0[Bb][01_]+
bin64 0[Bb][01_]+L(L)?
oct 0[Oo][0-7_]+
oct64 0[Oo][0-7_]+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 SCRIPTBLOCK
%%
\/\* { BEGIN COMMENT; }
\*\/ { BEGIN INITIAL; }
. { /* ignore */ }
\n { /* ignore */ }
\" { BEGIN STRING; }
[^\"\\]+ { scanctx_append_string(yyextra, yytext); }
\\n { scanctx_append_string(yyextra, "\n"); }
\\r { scanctx_append_string(yyextra, "\r"); }
\\t { scanctx_append_string(yyextra, "\t"); }
\\f { scanctx_append_string(yyextra, "\f"); }
\\\\ { scanctx_append_string(yyextra, "\\"); }
\\\" { scanctx_append_string(yyextra, "\""); }
{hexchar} {
char c[2] = { (char)(strtol(yytext + 2, NULL, 16) & 0xFF),
0 };
scanctx_append_string(yyextra, c);
}
\\ { scanctx_append_string(yyextra, "\\"); }
\" {
yylval->sval = scanctx_take_string(yyextra);
BEGIN INITIAL;
return(TOK_STRING);
}
\<\" { BEGIN SCRIPTBLOCK; }
([^\"]|\"[^\>])+ { scanctx_append_string(yyextra, yytext); }
\"\> {
yylval->sval = scanctx_take_string(yyextra);
BEGIN INITIAL;
return(TOK_STRING);
}
{include_open} { BEGIN INCLUDE; }
[^\"\\]+ { scanctx_append_string(yyextra, yytext); }
\\\\ { scanctx_append_string(yyextra, "\\"); }
\\\" { scanctx_append_string(yyextra, "\""); }
\" {
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); }
{float} { yylval->fval = atof(yytext); return(TOK_FLOAT); }
{integer} { yylval->ival = (int)fromdec(yytext); return TOK_INTEGER; }
{integer64} { yylval->llval = fromdec(yytext); return TOK_INTEGER64; }
{hex} { yylval->ival = (int)fromhex(yytext); return TOK_HEX; }
{hex64} { yylval->llval = fromhex(yytext); return TOK_HEX64; }
{bin} { yylval->ival = (int)frombin(yytext); return TOK_BIN; }
{bin64} { yylval->llval = frombin(yytext); return TOK_BIN64; }
{oct} { yylval->ival = (int)fromoct(yytext); return TOK_OCT; }
{oct64} { yylval->llval = fromoct(yytext); return TOK_OCT64; }
{name} { yylval->sval = yytext; return(TOK_NAME); }
\[ { return(TOK_ARRAY_START); }
\] { return(TOK_ARRAY_END); }
\( { return(TOK_LIST_START); }
\) { return(TOK_LIST_END); }
; { return(TOK_SEMICOLON); }
{comment} { /* ignore */ }
. { return(TOK_GARBAGE); }
<> {
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();
}