version 1.1.1.1, 2017/01/24 14:48:56
|
version 1.1.1.2, 2021/03/17 00:49:17
|
Line 1
|
Line 1
|
%{ |
%{ |
/* |
/* |
* Copyright (c) 2002,2003,2007 Martin Hedenfalk <martin@bzero.se> | * Copyright (c) 2002-2017 Martin Hedenfalk <martin@bzero.se> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any | * Permission to use, copy, modify, and/or distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
* copyright notice and this permission notice appear in all copies. |
* copyright notice and this permission notice appear in all copies. |
* |
* |
Line 15
|
Line 15
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
*/ |
*/ |
|
|
|
#include <assert.h> |
|
#include <ctype.h> |
|
#include <errno.h> |
|
|
#ifdef HAVE_CONFIG_H |
#ifdef HAVE_CONFIG_H |
# include <config.h> |
# include <config.h> |
#endif |
#endif |
|
|
#include <assert.h> | #ifndef HAVE_UNISTD_H |
| # define YY_NO_UNISTD_H |
| #else |
| # include <unistd.h> /* isatty() */ |
| #endif |
|
|
#ifdef HAVE_STRING_H |
#ifdef HAVE_STRING_H |
# include <string.h> |
# include <string.h> |
#endif |
#endif |
|
|
|
/* Defines isatty() for non UNIX systems */ |
#include "confuse.h" |
#include "confuse.h" |
|
|
#include <errno.h> |
|
|
|
#if defined(ENABLE_NLS) && defined(HAVE_GETTEXT) |
#if defined(ENABLE_NLS) && defined(HAVE_GETTEXT) |
# include <libintl.h> |
# include <libintl.h> |
# define _(str) dgettext(PACKAGE, str) |
# define _(str) dgettext(PACKAGE, str) |
Line 49 extern YYSTYPE cfg_yylval;
|
Line 57 extern YYSTYPE cfg_yylval;
|
|
|
/* temporary buffer for the quoted strings scanner |
/* temporary buffer for the quoted strings scanner |
*/ |
*/ |
|
#define CFG_QSTRING_BUFSIZ 32 |
char *cfg_qstring = NULL; |
char *cfg_qstring = NULL; |
static unsigned int qstring_index = 0; | static size_t qstring_index = 0; |
static unsigned int qstring_len = 0; | static size_t qstring_len = 0; |
static void qputc(char ch); |
static void qputc(char ch); |
#define CFG_QSTRING_BUFSIZ 32 | static void qput(cfg_t *cfg, char skip); |
| static void qbeg(int state); |
| static int qend(cfg_t *cfg, int trim, int ret); |
| static int qstr(cfg_t *cfg, char skip, int ret); |
|
|
#define MAX_INCLUDE_DEPTH 10 |
#define MAX_INCLUDE_DEPTH 10 |
struct { |
struct { |
YY_BUFFER_STATE state; | FILE *fp; |
char *filename; |
char *filename; |
unsigned int line; |
unsigned int line; |
} cfg_include_stack[MAX_INCLUDE_DEPTH]; |
} cfg_include_stack[MAX_INCLUDE_DEPTH]; |
int cfg_include_stack_ptr = 0; |
int cfg_include_stack_ptr = 0; |
|
|
static YY_BUFFER_STATE pre_string_scan_state = 0; | void cfg_scan_fp_begin(FILE *fp); |
static YY_BUFFER_STATE string_scan_state = 0; | void cfg_scan_fp_end(void); |
|
|
%} |
%} |
|
|
Line 82 static YY_BUFFER_STATE string_scan_state = 0;
|
Line 94 static YY_BUFFER_STATE string_scan_state = 0;
|
|
|
\n cfg->line++; /* keep track of line number */ |
\n cfg->line++; /* keep track of line number */ |
|
|
("#"|"//")[^\n]* /* eat up one-line comments */ | /* |
| * handle one-line comments |
| * |
| * Note: Comments with lots of leading #### or //// are fully |
| * consumed and are not included in CFGT_COMMENT yylval |
| */ |
| "#"{1,}.* return qstr(cfg, '#', CFGT_COMMENT); |
| "/"{2,}.* return qstr(cfg, '/', CFGT_COMMENT); |
|
|
/* special keywords/symbols |
/* special keywords/symbols |
*/ |
*/ |
Line 96 static YY_BUFFER_STATE string_scan_state = 0;
|
Line 115 static YY_BUFFER_STATE string_scan_state = 0;
|
|
|
/* handle multi-line C-style comments |
/* handle multi-line C-style comments |
*/ |
*/ |
"/*" BEGIN(comment); | "/*" qbeg(comment); |
<comment>[^*\n]* /* eat anything that's not a '*' */ | <comment>[^*\n]* qput(NULL, 0); /* anything that's not a '*' */ |
<comment>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ | <comment>"*"+[^*/\n]* qput(NULL, 0); /* '*'s not followed by '/'s */ |
<comment>\n cfg->line++; | <comment>\n qput(cfg, 0); |
<comment>"*"+"/" BEGIN(INITIAL); | <comment>[ \t]*"*"+"/" return qend(cfg, 1, CFGT_COMMENT); |
|
|
/* handle C-style strings |
/* handle C-style strings |
*/ |
*/ |
Line 113 static YY_BUFFER_STATE string_scan_state = 0;
|
Line 132 static YY_BUFFER_STATE string_scan_state = 0;
|
qputc('\0'); |
qputc('\0'); |
cfg_yylval = cfg_qstring; |
cfg_yylval = cfg_qstring; |
return CFGT_STR; |
return CFGT_STR; |
} | } |
<dq_str>$\{[^}]*\} { /* environment variable substitution */ |
<dq_str>$\{[^}]*\} { /* environment variable substitution */ |
char *var; |
char *var; |
char *e; |
char *e; |
Line 182 static YY_BUFFER_STATE string_scan_state = 0;
|
Line 201 static YY_BUFFER_STATE string_scan_state = 0;
|
<dq_str>\\. { |
<dq_str>\\. { |
qputc(yytext[1]); |
qputc(yytext[1]); |
} |
} |
<dq_str>[^\\\"\n]+ { | <dq_str>[^\\\"\n] { |
char *yptr = yytext; | qputc(yytext[0]); |
while(*yptr) { | |
qputc(*yptr++); | |
} | |
} |
} |
|
|
/* single-quoted string ('...') */ |
/* single-quoted string ('...') */ |
Line 217 static YY_BUFFER_STATE string_scan_state = 0;
|
Line 233 static YY_BUFFER_STATE string_scan_state = 0;
|
} |
} |
<sq_str>[^\\\'\n]+ { |
<sq_str>[^\\\'\n]+ { |
char *cp = yytext; |
char *cp = yytext; |
while(*cp != '\0') { | while (*cp != '\0') |
qputc(*cp++); |
qputc(*cp++); |
} |
|
} |
} |
<sq_str><<EOF>> { |
<sq_str><<EOF>> { |
cfg_error(cfg, _("unterminated string constant")); |
cfg_error(cfg, _("unterminated string constant")); |
Line 227 static YY_BUFFER_STATE string_scan_state = 0;
|
Line 242 static YY_BUFFER_STATE string_scan_state = 0;
|
} |
} |
|
|
<<EOF>> { |
<<EOF>> { |
if (cfg_include_stack_ptr <= 0) | if (cfg_include_stack_ptr > 0) |
{ | { |
return EOF; | --cfg_include_stack_ptr; |
} | /* fp opened by cfg_lexer_include()? */ |
else | if (cfg_include_stack[cfg_include_stack_ptr].fp != cfg_yyin) { |
{ | ++cfg_include_stack_ptr; |
yy_delete_buffer( YY_CURRENT_BUFFER ); | return EOF; |
fclose(cfg_yyin); | } |
cfg_yyin = 0; | free(cfg->filename); |
--cfg_include_stack_ptr; | cfg->filename = cfg_include_stack[cfg_include_stack_ptr].filename; |
yy_switch_to_buffer( | cfg->line = cfg_include_stack[cfg_include_stack_ptr].line; |
cfg_include_stack[cfg_include_stack_ptr].state ); | fclose(cfg_yyin); |
free(cfg->filename); | cfg_scan_fp_end(); |
cfg->filename = cfg_include_stack[cfg_include_stack_ptr].filename; | } |
cfg->line = cfg_include_stack[cfg_include_stack_ptr].line; | else |
} | { |
| return EOF; |
| } |
} |
} |
|
|
$\{[^}]*\} { |
$\{[^}]*\} { |
char *var; |
char *var; |
char *e; |
char *e; |
|
|
yytext[strlen(yytext) - 1] = 0; |
yytext[strlen(yytext) - 1] = 0; |
e = strchr(yytext+2, ':'); |
e = strchr(yytext+2, ':'); |
if(e && e[1] == '-') | if (e && e[1] == '-') |
*e = 0; |
*e = 0; |
else |
else |
e = 0; |
e = 0; |
var = getenv(yytext+2); |
var = getenv(yytext+2); |
if(!var && e) | if (!var && e) |
var = e+2; |
var = e+2; |
if(!var) | if (!var) |
var = ""; |
var = ""; |
cfg_yylval = var; |
cfg_yylval = var; |
|
|
return CFGT_STR; |
return CFGT_STR; |
} |
} |
|
|
Line 286 void cfg_dummy_function(void)
|
Line 305 void cfg_dummy_function(void)
|
|
|
int cfg_lexer_include(cfg_t *cfg, const char *filename) |
int cfg_lexer_include(cfg_t *cfg, const char *filename) |
{ |
{ |
|
FILE *fp; |
char *xfilename; |
char *xfilename; |
|
|
if(cfg_include_stack_ptr >= MAX_INCLUDE_DEPTH) { | if (cfg_include_stack_ptr >= MAX_INCLUDE_DEPTH) |
| { |
cfg_error(cfg, _("includes nested too deeply")); |
cfg_error(cfg, _("includes nested too deeply")); |
return 1; | return CFG_PARSE_ERROR; |
} |
} |
|
|
cfg_include_stack[cfg_include_stack_ptr].state = YY_CURRENT_BUFFER; |
|
cfg_include_stack[cfg_include_stack_ptr].filename = cfg->filename; |
cfg_include_stack[cfg_include_stack_ptr].filename = cfg->filename; |
cfg_include_stack[cfg_include_stack_ptr].line = cfg->line; |
cfg_include_stack[cfg_include_stack_ptr].line = cfg->line; |
cfg_include_stack_ptr++; |
|
|
|
xfilename = cfg_tilde_expand(filename); | if (cfg->path) |
| { |
| xfilename = cfg_searchpath(cfg->path, filename); |
| if (!xfilename) |
| { |
| cfg_error(cfg, _("%s: Not found in search path"), filename); |
| return CFG_PARSE_ERROR; |
| } |
| } |
| else |
| { |
| xfilename = cfg_tilde_expand(filename); |
| if (!xfilename) |
| { |
| cfg_error(cfg, _("%s: Failed tilde expand"), filename); |
| return CFG_PARSE_ERROR; |
| } |
| } |
|
|
cfg_yyin = fopen(xfilename, "r"); | fp = fopen(xfilename, "r"); |
| if (!fp) |
if(!cfg_yyin) { | { |
cfg_error(cfg, "%s: %s", xfilename, strerror(errno)); |
cfg_error(cfg, "%s: %s", xfilename, strerror(errno)); |
free(xfilename); |
free(xfilename); |
return 1; | return CFG_PARSE_ERROR; |
} |
} |
|
|
|
cfg_include_stack[cfg_include_stack_ptr].fp = fp; |
|
cfg_include_stack_ptr++; |
cfg->filename = xfilename; |
cfg->filename = xfilename; |
cfg->line = 1; |
cfg->line = 1; |
|
cfg_scan_fp_begin(fp); |
|
|
yy_switch_to_buffer(yy_create_buffer(cfg_yyin, YY_BUF_SIZE)); | return CFG_SUCCESS; |
return 0; | |
} |
} |
|
|
/* write a character to the quoted string buffer, and reallocate as |
/* write a character to the quoted string buffer, and reallocate as |
Line 320 int cfg_lexer_include(cfg_t *cfg, const char *filename
|
Line 358 int cfg_lexer_include(cfg_t *cfg, const char *filename
|
*/ |
*/ |
static void qputc(char ch) |
static void qputc(char ch) |
{ |
{ |
if(qstring_index >= qstring_len) { | if (qstring_index >= qstring_len) { |
qstring_len += CFG_QSTRING_BUFSIZ; |
qstring_len += CFG_QSTRING_BUFSIZ; |
cfg_qstring = (char *)realloc(cfg_qstring, qstring_len); | cfg_qstring = (char *)realloc(cfg_qstring, qstring_len + 1); |
assert(cfg_qstring); |
assert(cfg_qstring); |
memset(cfg_qstring + qstring_index, 0, CFG_QSTRING_BUFSIZ); | memset(cfg_qstring + qstring_index, 0, CFG_QSTRING_BUFSIZ + 1); |
} |
} |
cfg_qstring[qstring_index++] = ch; |
cfg_qstring[qstring_index++] = ch; |
} |
} |
|
|
void cfg_scan_string_begin(const char *buf) | static void qput(cfg_t *cfg, char skip) |
{ |
{ |
pre_string_scan_state = YY_CURRENT_BUFFER; | char *cp; |
|
|
/* yy_scan_string does a yy_switch_to_buffer call for us | if (cfg) |
*/ | cfg->line++; |
string_scan_state = yy_scan_string(buf); | |
| cp = yytext; |
| |
| while (skip && *cp == skip) |
| cp++; |
| |
| while (*cp) |
| qputc(*cp++); |
} |
} |
|
|
void cfg_scan_string_end(void) | static void qbeg(int state) |
{ |
{ |
/* restore to previous state | BEGIN(state); |
*/ | qstring_index = 0; |
yy_delete_buffer(string_scan_state); | if (cfg_qstring) |
if (pre_string_scan_state) | memset(cfg_qstring, 0, qstring_len); |
yy_switch_to_buffer(pre_string_scan_state); | |
free(cfg_qstring); | |
cfg_qstring = 0; | |
qstring_index = qstring_len = 0; | |
string_scan_state = 0; | |
} |
} |
|
|
static YY_BUFFER_STATE pre_fp_scan_state; | static char *trim_whitespace(char *str, unsigned int len) |
static YY_BUFFER_STATE fp_scan_state; | { |
| if (!str || !str[0]) |
| return str; |
|
|
|
while (len > 1) { |
|
if ((str[len] == 0 || isspace(str[len])) && isspace(str[len - 1])) |
|
len--; |
|
else |
|
break; |
|
} |
|
str[len] = 0; |
|
|
|
while (isspace(*str)) |
|
str++; |
|
|
|
return str; |
|
} |
|
|
|
static int qend(cfg_t *cfg, int trim, int ret) |
|
{ |
|
char *ptr = cfg_qstring; |
|
|
|
BEGIN(INITIAL); |
|
if (cfg) |
|
cfg->line++; |
|
|
|
if (trim) |
|
ptr = trim_whitespace(cfg_qstring, qstring_index); |
|
else |
|
qputc('\0'); |
|
|
|
cfg_yylval = ptr; |
|
|
|
return ret; |
|
} |
|
|
|
static int qstr(cfg_t *cfg, char skip, int ret) |
|
{ |
|
qbeg(comment); |
|
qput(cfg, skip); |
|
|
|
return qend(cfg, 1, ret); |
|
} |
|
|
void cfg_scan_fp_begin(FILE *fp) |
void cfg_scan_fp_begin(FILE *fp) |
{ |
{ |
pre_fp_scan_state = YY_CURRENT_BUFFER; | cfg_yypush_buffer_state(cfg_yy_create_buffer(fp, YY_BUF_SIZE)); |
fp_scan_state = yy_create_buffer(fp, YY_BUF_SIZE); | |
yy_switch_to_buffer(fp_scan_state); | |
} |
} |
|
|
void cfg_scan_fp_end(void) |
void cfg_scan_fp_end(void) |
{ |
{ |
/* restore to previous state | if (cfg_qstring) |
*/ | free(cfg_qstring); |
yy_delete_buffer(fp_scan_state); | cfg_qstring = NULL; |
if(pre_fp_scan_state) | |
yy_switch_to_buffer(pre_fp_scan_state); | |
free(cfg_qstring); | |
cfg_qstring = 0; | |
qstring_index = qstring_len = 0; |
qstring_index = qstring_len = 0; |
|
cfg_yypop_buffer_state(); |
} |
} |