mirror of
https://github.com/ascii-boxes/boxes.git
synced 2025-03-19 17:17:34 +01:00
parent
46aab3faa6
commit
97b62dd09a
@ -94,7 +94,7 @@ tools.o: tools.c tools.h boxes.h shape.h unicode.h config.h | check_dir
|
|||||||
unicode.o: unicode.c unicode.h boxes.h tools.h config.h | check_dir
|
unicode.o: unicode.c unicode.h boxes.h tools.h config.h | check_dir
|
||||||
shape.o: shape.c shape.h boxes.h tools.h config.h | check_dir
|
shape.o: shape.c shape.h boxes.h tools.h config.h | check_dir
|
||||||
generate.o: generate.c generate.h boxes.h shape.h tools.h unicode.h config.h | check_dir
|
generate.o: generate.c generate.h boxes.h shape.h tools.h unicode.h config.h | check_dir
|
||||||
parsing.o: parsing.c parsing.h boxes.h config.h | check_dir
|
parsing.o: parsing.c parsing.h parser.h lex.yy.h boxes.h tools.h config.h | check_dir
|
||||||
remove.o: remove.c remove.h boxes.h shape.h tools.h unicode.h config.h | check_dir
|
remove.o: remove.c remove.h boxes.h shape.h tools.h unicode.h config.h | check_dir
|
||||||
regulex.o: regulex.c regulex.h boxes.h tools.h unicode.h config.h | check_dir
|
regulex.o: regulex.c regulex.h boxes.h tools.h unicode.h config.h | check_dir
|
||||||
getopt.o: misc/getopt.c misc/getopt.h | check_dir
|
getopt.o: misc/getopt.c misc/getopt.h | check_dir
|
||||||
|
200
src/lexer.l
200
src/lexer.l
@ -25,10 +25,20 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
void begin_speedmode();
|
|
||||||
|
typedef struct {
|
||||||
|
int yyerrcnt;
|
||||||
|
|
||||||
|
/** pointer to the currently active string delimiter character in bison_args */
|
||||||
|
char *sdel_ptr;
|
||||||
|
|
||||||
|
/** pointer to the currently active string escape character in bison_args */
|
||||||
|
char *sesc_ptr;
|
||||||
|
} pass_to_flex;
|
||||||
|
|
||||||
|
|
||||||
void chg_strdelims (const char asdel, const char asesc);
|
|
||||||
|
void begin_speedmode(void *yyscanner);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,10 +48,10 @@ void chg_strdelims (const char asdel, const char asesc);
|
|||||||
* dynamically enlarge its input buffer to accomodate larger tokens. Thus, we simply set the buffer size to the
|
* dynamically enlarge its input buffer to accomodate larger tokens. Thus, we simply set the buffer size to the
|
||||||
* input file size plus 10 bytes margin-of-error.
|
* input file size plus 10 bytes margin-of-error.
|
||||||
*
|
*
|
||||||
* @param scanner pointer to the scanner data block
|
* @param yyscanner pointer to the scanner data block
|
||||||
* @param configfile the path to the config file we are reading
|
* @param configfile the path to the config file we are reading
|
||||||
*/
|
*/
|
||||||
void inflate_inbuf(void *scanner, const char *configfile);
|
void inflate_inbuf(void *yyscanner, const char *configfile);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +59,7 @@ void inflate_inbuf(void *scanner, const char *configfile);
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "shape.h"
|
#include "shape.h"
|
||||||
#define FILE_LEXER_L
|
#define FILE_LEXER_L
|
||||||
#include "boxes.h"
|
#include "boxes.h"
|
||||||
@ -60,21 +71,18 @@ void inflate_inbuf(void *scanner, const char *configfile);
|
|||||||
|
|
||||||
#define LEX_MAX_WARN 3 /* number of lex errors per design */
|
#define LEX_MAX_WARN 3 /* number of lex errors per design */
|
||||||
|
|
||||||
static int yyerrcnt = 0;
|
static void report_state_char(char *symbol, char c, char *expected_state_str);
|
||||||
|
|
||||||
/* the currently active string delimiter character */
|
|
||||||
static char sdel = '\"';
|
|
||||||
|
|
||||||
/* the currently active string escape character */
|
|
||||||
static char sesc = '\\';
|
|
||||||
|
|
||||||
|
static void report_state(char *symbol, char *text, char *expected_state_str);
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
||||||
%option 8bit
|
%option 8bit
|
||||||
%option bison-bridge
|
%option bison-bridge
|
||||||
%option case-insensitive
|
%option case-insensitive
|
||||||
%option ecs
|
%option ecs
|
||||||
|
%option extra-type="pass_to_flex *"
|
||||||
%option never-interactive
|
%option never-interactive
|
||||||
%option nodefault
|
%option nodefault
|
||||||
%option noinput
|
%option noinput
|
||||||
@ -85,12 +93,12 @@ static char sesc = '\\';
|
|||||||
%option yylineno
|
%option yylineno
|
||||||
|
|
||||||
|
|
||||||
%x SAMPLE
|
|
||||||
%x SPEEDMODE
|
|
||||||
%x DELWORD
|
%x DELWORD
|
||||||
%x PARENT
|
%x PARENT
|
||||||
%s SHAPES
|
%x SAMPLE
|
||||||
|
%x SPEEDMODE
|
||||||
%s ELASTIC
|
%s ELASTIC
|
||||||
|
%s SHAPES
|
||||||
|
|
||||||
|
|
||||||
PWORD [a-zA-ZäöüÄÖÜ][a-zA-Z0-9\-_üäöÜÄÖß]*
|
PWORD [a-zA-ZäöüÄÖÜ][a-zA-Z0-9\-_üäöÜÄÖß]*
|
||||||
@ -104,24 +112,22 @@ PFILENAME [^\r\n]+
|
|||||||
%%
|
%%
|
||||||
|
|
||||||
|
|
||||||
<DELWORD,SHAPES,ELASTIC,INITIAL>[ \r\t] /* ignore whitespace */
|
<INITIAL,DELWORD,ELASTIC,SHAPES>[ \r\t] /* ignore whitespace */
|
||||||
|
|
||||||
<DELWORD,SHAPES,ELASTIC,INITIAL>\n {}
|
<INITIAL,DELWORD,ELASTIC,SHAPES>\n {}
|
||||||
|
|
||||||
|
|
||||||
<DELWORD>[^ \t\r\n]+ {
|
<DELWORD>[^ \t\r\n]+ {
|
||||||
/*
|
/*
|
||||||
* String delimiter spec - like WORD, but allow any character
|
* String delimiter spec - like WORD, but allow any character
|
||||||
*/
|
*/
|
||||||
#ifdef LEXER_DEBUG
|
|
||||||
fprintf (stderr, "\nYDELWOR: %s -- STATE INITIAL", yytext);
|
|
||||||
#endif
|
|
||||||
yylval->s = (char *) strdup (yytext);
|
yylval->s = (char *) strdup (yytext);
|
||||||
if (yylval->s == NULL) {
|
if (yylval->s == NULL) {
|
||||||
perror (PROJECT);
|
perror (PROJECT);
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
BEGIN INITIAL;
|
BEGIN(INITIAL);
|
||||||
|
report_state("YDELWOR", yytext, "INITIAL");
|
||||||
return YDELWORD;
|
return YDELWORD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +142,7 @@ PFILENAME [^\r\n]+
|
|||||||
int rest_len = yyleng - 1; /* length of string pointed to by p */
|
int rest_len = yyleng - 1; /* length of string pointed to by p */
|
||||||
int qcnt = 0; /* esc char count in current string */
|
int qcnt = 0; /* esc char count in current string */
|
||||||
|
|
||||||
if (yytext[0] != sdel) {
|
if (yytext[0] != *(yyextra->sdel_ptr)) {
|
||||||
REJECT; /* that was not our delimiter */
|
REJECT; /* that was not our delimiter */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,35 +154,34 @@ PFILENAME [^\r\n]+
|
|||||||
p = yylval->s;
|
p = yylval->s;
|
||||||
|
|
||||||
while (*p) {
|
while (*p) {
|
||||||
if (*p == sesc) {
|
if (*p == *(yyextra->sesc_ptr)) {
|
||||||
memmove (p, p+1, rest_len); /* incl. '\0' */
|
memmove (p, p+1, rest_len); /* incl. '\0' */
|
||||||
++qcnt;
|
++qcnt;
|
||||||
--rest_len;
|
--rest_len;
|
||||||
if (*p == '\0')
|
if (*p == '\0')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (*p == sdel) {
|
else if (*p == *(yyextra->sdel_ptr)) {
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
yyless ((p-yylval->s)+2+qcnt); /* string plus quotes */
|
yyless ((p-yylval->s)+2+qcnt); /* string plus quotes */
|
||||||
#ifdef LEXER_DEBUG
|
#ifdef LEXER_DEBUG
|
||||||
fprintf (stderr, "\n STRING: \"%s\"", yylval->s);
|
fprintf (stderr, " STRING: \"%s\"\n", yylval->s);
|
||||||
#endif
|
#endif
|
||||||
return STRING;
|
return STRING;
|
||||||
}
|
}
|
||||||
--rest_len;
|
--rest_len;
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
if (yyerrcnt++ < 5)
|
if ((yyextra->yyerrcnt)++ < 5) {
|
||||||
yyerror(NULL, "Unterminated String -- %s", yytext);
|
yyerror(NULL, "Unterminated String -- %s", yytext);
|
||||||
|
}
|
||||||
return YUNREC;
|
return YUNREC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{PPARENT} {
|
{PPARENT} {
|
||||||
#ifdef LEXER_DEBUG
|
BEGIN(PARENT);
|
||||||
fprintf (stderr, "\nYPARENT: %s", yytext);
|
report_state("YPARENT", yytext, "PARENT");
|
||||||
#endif
|
|
||||||
BEGIN PARENT;
|
|
||||||
return YPARENT;
|
return YPARENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,23 +195,20 @@ PFILENAME [^\r\n]+
|
|||||||
while ((*p == ' ' || *p == '\t') && p >= yylval->s) {
|
while ((*p == ' ' || *p == '\t') && p >= yylval->s) {
|
||||||
*p-- = '\0';
|
*p-- = '\0';
|
||||||
}
|
}
|
||||||
#ifdef LEXER_DEBUG
|
BEGIN(INITIAL);
|
||||||
fprintf (stderr, "\n STRING: \"%s\"", yylval->s);
|
report_state("FILENAM", yylval->s, "INITIAL");
|
||||||
#endif
|
return FILENAME;
|
||||||
BEGIN INITIAL;
|
|
||||||
return STRING;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<PARENT>\n {
|
<PARENT>\r?\n {
|
||||||
BEGIN INITIAL;
|
/* This is triggered only when no parent filename was specified. */
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
report_state(" NL", "", "INITIAL");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Sample {
|
Sample {
|
||||||
#ifdef LEXER_DEBUG
|
BEGIN(SAMPLE);
|
||||||
fprintf (stderr, "\nYSAMPLE: %s -- STATE SAMPLE", yytext);
|
report_state("YSAMPLE", yytext, "SAMPLE");
|
||||||
#endif
|
|
||||||
BEGIN SAMPLE;
|
|
||||||
return YSAMPLE;
|
return YSAMPLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,19 +237,18 @@ Sample {
|
|||||||
len = p - yytext; /* yyless(n): push back all but the first n */
|
len = p - yytext; /* yyless(n): push back all but the first n */
|
||||||
yyless (len); /* allow him to return YENDSAMPLE */
|
yyless (len); /* allow him to return YENDSAMPLE */
|
||||||
|
|
||||||
yylval->s[len] = '\n'; /* replace 'e' with newline */
|
yylval->s[len] = '\n'; /* replace 'e' with newline */
|
||||||
btrim (yylval->s, &len);
|
btrim (yylval->s, &len);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
strcat (yylval->s, "\n"); /* memory was allocated with strdup */
|
strcat (yylval->s, "\n"); /* memory was allocated with strdup */
|
||||||
#ifdef LEXER_DEBUG
|
BEGIN(INITIAL);
|
||||||
fprintf (stderr, "\n STRING: \"%s\" -- STATE INITIAL", yylval->s);
|
report_state(" STRING", yylval->s, "INITIAL");
|
||||||
#endif
|
|
||||||
BEGIN INITIAL;
|
|
||||||
return STRING;
|
return STRING;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (yyerrcnt++ < 5)
|
if ((yyextra->yyerrcnt)++ < 5) {
|
||||||
yyerror(NULL, "SAMPLE block must not be empty");
|
yyerror(NULL, "SAMPLE block must not be empty");
|
||||||
|
}
|
||||||
BFREE (yylval->s);
|
BFREE (yylval->s);
|
||||||
return YUNREC;
|
return YUNREC;
|
||||||
}
|
}
|
||||||
@ -259,7 +260,7 @@ Sample {
|
|||||||
|
|
||||||
ends[ \t\r]*$ {
|
ends[ \t\r]*$ {
|
||||||
#ifdef LEXER_DEBUG
|
#ifdef LEXER_DEBUG
|
||||||
fprintf (stderr, "\nYENDSAM: %s", yytext);
|
fprintf (stderr, "YENDSAM: %s\n", yytext);
|
||||||
#endif
|
#endif
|
||||||
return YENDSAMPLE;
|
return YENDSAMPLE;
|
||||||
}
|
}
|
||||||
@ -267,26 +268,22 @@ ends[ \t\r]*$ {
|
|||||||
|
|
||||||
|
|
||||||
Elastic {
|
Elastic {
|
||||||
#ifdef LEXER_DEBUG
|
BEGIN(ELASTIC);
|
||||||
fprintf (stderr, "\nYELASTC: %s -- STATE ELASTIC", yytext);
|
report_state("YELASTC", yytext, "ELASTIC");
|
||||||
#endif
|
|
||||||
BEGIN ELASTIC;
|
|
||||||
return YELASTIC;
|
return YELASTIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shapes {
|
Shapes {
|
||||||
#ifdef LEXER_DEBUG
|
BEGIN(SHAPES);
|
||||||
fprintf (stderr, "\nYSHAPES: %s -- STATE SHAPES", yytext);
|
report_state("YSHAPES", yytext, "SHAPES");
|
||||||
#endif
|
|
||||||
BEGIN SHAPES;
|
|
||||||
return YSHAPES;
|
return YSHAPES;
|
||||||
}
|
}
|
||||||
|
|
||||||
{PBOX} {
|
{PBOX} {
|
||||||
#ifdef LEXER_DEBUG
|
#ifdef LEXER_DEBUG
|
||||||
fprintf (stderr, "\n YBOX: %s", yytext);
|
fprintf (stderr, " YBOX: %s\n", yytext);
|
||||||
#endif
|
#endif
|
||||||
yyerrcnt = 0;
|
yyextra->yyerrcnt = 0;
|
||||||
return YBOX;
|
return YBOX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,18 +315,14 @@ Once { yylval->c = 'o'; return YRXPFLAG; }
|
|||||||
<SHAPES,ELASTIC>wnw { yylval->shape = WNW; return SHAPE; }
|
<SHAPES,ELASTIC>wnw { yylval->shape = WNW; return SHAPE; }
|
||||||
|
|
||||||
<ELASTIC>\) {
|
<ELASTIC>\) {
|
||||||
#ifdef LEXER_DEBUG
|
BEGIN(INITIAL);
|
||||||
fprintf (stderr, "\n SYMBOL: \'%c\' -- STATE INITIAL", yytext[0]);
|
report_state_char("SYMBOL", yytext[0], "INITIAL");
|
||||||
#endif
|
|
||||||
BEGIN INITIAL;
|
|
||||||
return yytext[0];
|
return yytext[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
<SHAPES>\} {
|
<SHAPES>\} {
|
||||||
#ifdef LEXER_DEBUG
|
BEGIN(INITIAL);
|
||||||
fprintf (stderr, "\n SYMBOL: \'%c\' -- STATE INITIAL", yytext[0]);
|
report_state_char("SYMBOL", yytext[0], "INITIAL");
|
||||||
#endif
|
|
||||||
BEGIN INITIAL;
|
|
||||||
return yytext[0];
|
return yytext[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,7 +332,7 @@ author|designer|tags|created|revision|revdate|indent {
|
|||||||
* general key words
|
* general key words
|
||||||
*/
|
*/
|
||||||
#ifdef LEXER_DEBUG
|
#ifdef LEXER_DEBUG
|
||||||
fprintf (stderr, "\nKEYWORD: %s", yytext);
|
fprintf (stderr, "KEYWORD: %s\n", yytext);
|
||||||
#endif
|
#endif
|
||||||
yylval->s = (char *) strdup (yytext);
|
yylval->s = (char *) strdup (yytext);
|
||||||
if (yylval->s == NULL) {
|
if (yylval->s == NULL) {
|
||||||
@ -354,17 +347,15 @@ Delimiter|Delim {
|
|||||||
/*
|
/*
|
||||||
* Change string delimiting characters
|
* Change string delimiting characters
|
||||||
*/
|
*/
|
||||||
#ifdef LEXER_DEBUG
|
BEGIN(DELWORD);
|
||||||
fprintf (stderr, "\nYCHGDEL: %s -- STATE DELWORD", yytext);
|
report_state("YCHGDEL", yytext, "DELWORD");
|
||||||
#endif
|
|
||||||
BEGIN DELWORD;
|
|
||||||
return YCHGDEL;
|
return YCHGDEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{PWORD} {
|
{PWORD} {
|
||||||
#ifdef LEXER_DEBUG
|
#ifdef LEXER_DEBUG
|
||||||
fprintf (stderr, "\n WORD: %s", yytext);
|
fprintf (stderr, " WORD: %s\n", yytext);
|
||||||
#endif
|
#endif
|
||||||
yylval->s = (char *) strdup (yytext);
|
yylval->s = (char *) strdup (yytext);
|
||||||
if (yylval->s == NULL) {
|
if (yylval->s == NULL) {
|
||||||
@ -377,7 +368,7 @@ Delimiter|Delim {
|
|||||||
|
|
||||||
[\+-]?[0-9]+ {
|
[\+-]?[0-9]+ {
|
||||||
#ifdef LEXER_DEBUG
|
#ifdef LEXER_DEBUG
|
||||||
fprintf (stderr, "\nYNUMBER: %s", yytext);
|
fprintf (stderr, "YNUMBER: %s\n", yytext);
|
||||||
#endif
|
#endif
|
||||||
yylval->num = atoi (yytext);
|
yylval->num = atoi (yytext);
|
||||||
return YNUMBER;
|
return YNUMBER;
|
||||||
@ -386,7 +377,7 @@ Delimiter|Delim {
|
|||||||
|
|
||||||
[,(){}] {
|
[,(){}] {
|
||||||
#ifdef LEXER_DEBUG
|
#ifdef LEXER_DEBUG
|
||||||
fprintf (stderr, "\n SYMBOL: \'%c\'", yytext[0]);
|
fprintf (stderr, " SYMBOL: \'%c\'\n", yytext[0]);
|
||||||
#endif
|
#endif
|
||||||
return yytext[0];
|
return yytext[0];
|
||||||
}
|
}
|
||||||
@ -395,25 +386,23 @@ Delimiter|Delim {
|
|||||||
#.*$ {
|
#.*$ {
|
||||||
/* ignore comments */
|
/* ignore comments */
|
||||||
#ifdef LEXER_DEBUG
|
#ifdef LEXER_DEBUG
|
||||||
fprintf (stderr, "\nCOMMENT: %s", yytext+1);
|
fprintf (stderr, "COMMENT: %s\n", yytext+1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
. {
|
. {
|
||||||
if (yyerrcnt++ < LEX_MAX_WARN)
|
if ((yyextra->yyerrcnt)++ < LEX_MAX_WARN)
|
||||||
yyerror(NULL, "Unrecognized input char \'%s\'", yytext);
|
yyerror(NULL, "Unrecognized input char \'%s\'", yytext);
|
||||||
return YUNREC;
|
return YUNREC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<SPEEDMODE>{PBOX}{PWHITE}+{PWORD} {
|
<SPEEDMODE>{PBOX}{PWHITE}+{PWORD}|{PPARENT} {
|
||||||
#ifdef LEXER_DEBUG
|
/* end speedmode, but then give back the whole match so BOX or PARENT can be started properly */
|
||||||
fprintf (stderr, "\n STATUS: %s -- STATE INITIAL", yytext);
|
yyless(0);
|
||||||
#endif
|
BEGIN(INITIAL);
|
||||||
yyless (0);
|
report_state(" STATUS", "", "INITIAL");
|
||||||
speeding = 0;
|
|
||||||
BEGIN INITIAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<SPEEDMODE>\n {}
|
<SPEEDMODE>\n {}
|
||||||
@ -424,11 +413,7 @@ Delimiter|Delim {
|
|||||||
%%
|
%%
|
||||||
|
|
||||||
|
|
||||||
/* TODO These functions should go away. The cast to (struct yyguts_t *) is a hack.
|
void inflate_inbuf(void *yyscanner, const char *configfile)
|
||||||
* And they use global variables which is not reentrant at all. Use extra data instead.
|
|
||||||
* Maybe inflate_inbuf() can be moved to parsing.c? */
|
|
||||||
|
|
||||||
void inflate_inbuf(void *scanner, const char *configfile)
|
|
||||||
{
|
{
|
||||||
struct stat sinf;
|
struct stat sinf;
|
||||||
|
|
||||||
@ -436,31 +421,42 @@ void inflate_inbuf(void *scanner, const char *configfile)
|
|||||||
perror (PROJECT);
|
perror (PROJECT);
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
struct yyguts_t *yyg = (struct yyguts_t *) scanner;
|
struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
|
||||||
yy_delete_buffer(YY_CURRENT_BUFFER, scanner);
|
yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner);
|
||||||
yy_switch_to_buffer (yy_create_buffer(yyin, sinf.st_size+10, scanner), scanner);
|
yy_switch_to_buffer (yy_create_buffer(yyin, sinf.st_size+10, yyscanner), yyscanner);
|
||||||
|
BEGIN(INITIAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void begin_speedmode(void *scanner)
|
void begin_speedmode(void *yyscanner)
|
||||||
{
|
{
|
||||||
#ifdef LEXER_DEBUG
|
struct yyguts_t *yyg = (struct yyguts_t *) yyscanner;
|
||||||
fprintf (stderr, "\n STATUS: begin_speedmode() -- STATE SPEEDMODE");
|
BEGIN(SPEEDMODE);
|
||||||
#endif
|
report_state(" STATUS", "begin_speedmode()", "SPEEDMODE");
|
||||||
struct yyguts_t *yyg = (struct yyguts_t *) scanner;
|
|
||||||
BEGIN SPEEDMODE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void chg_strdelims (const char asesc, const char asdel)
|
static void report_state_char(char *symbol, char c, char *expected_state_str)
|
||||||
{
|
{
|
||||||
|
char *s = (char *) malloc(4);
|
||||||
|
sprintf(s, "'%c'", c);
|
||||||
|
report_state(symbol, s, expected_state_str);
|
||||||
|
BFREE(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void report_state(char *symbol, char *text, char *expected_state_str)
|
||||||
|
{
|
||||||
|
int lexerDebug = 0;
|
||||||
#ifdef LEXER_DEBUG
|
#ifdef LEXER_DEBUG
|
||||||
fprintf (stderr, "\n STATUS: chg_strdelims ('%c', '%c')", asesc, asdel);
|
lexerDebug = 1;
|
||||||
#endif
|
#endif
|
||||||
sesc = asesc;
|
if (lexerDebug) {
|
||||||
sdel = asdel;
|
fprintf(stderr, "%7s: %s -- STATE %s\n", symbol, text, expected_state_str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
139
src/parser.y
139
src/parser.y
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#include "boxes.h"
|
#include "boxes.h"
|
||||||
|
|
||||||
extern int speeding;
|
|
||||||
|
|
||||||
/** all the arguments which we pass to the bison parser */
|
/** all the arguments which we pass to the bison parser */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -41,6 +40,31 @@ typedef struct {
|
|||||||
/** the path to the config file we are parsing */
|
/** the path to the config file we are parsing */
|
||||||
char *config_file;
|
char *config_file;
|
||||||
|
|
||||||
|
/** the currently active string delimiter character */
|
||||||
|
char sdel;
|
||||||
|
|
||||||
|
/** the currently active string escape character */
|
||||||
|
char sesc;
|
||||||
|
|
||||||
|
int num_mandatory;
|
||||||
|
|
||||||
|
int time_for_se_check;
|
||||||
|
|
||||||
|
/** number of user-specified shapes */
|
||||||
|
int num_shapespec;
|
||||||
|
|
||||||
|
/** used to limit "skipping" msgs */
|
||||||
|
int skipping;
|
||||||
|
|
||||||
|
/** true if we're skipping designs, but no error */
|
||||||
|
int speeding;
|
||||||
|
|
||||||
|
/** names of config files specified via "parent" */
|
||||||
|
char **parent_configs;
|
||||||
|
|
||||||
|
/** number of parent config files (size of parent_configs array) */
|
||||||
|
size_t num_parent_configs;
|
||||||
|
|
||||||
/** the flex scanner, which is explicitly passed to reentrant bison */
|
/** the flex scanner, which is explicitly passed to reentrant bison */
|
||||||
void *lexer_state;
|
void *lexer_state;
|
||||||
} pass_to_bison;
|
} pass_to_bison;
|
||||||
@ -62,13 +86,13 @@ typedef struct {
|
|||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "lex.yy.h"
|
#include "lex.yy.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Valid characters to be used as string delimiters. Note that the
|
* Valid characters to be used as string delimiters. Note that the
|
||||||
* following list must correspond to the DELIM definition in lexer.l.
|
* following list must correspond to the DELIM definition in lexer.l.
|
||||||
*/
|
*/
|
||||||
#define LEX_SDELIM "\"~'`!@%&*=:;<>?/|.\\"
|
#define LEX_SDELIM "\"~'`!@%&*=:;<>?/|.\\"
|
||||||
|
|
||||||
|
|
||||||
/** required for bison-flex bridge */
|
/** required for bison-flex bridge */
|
||||||
#define scanner bison_args->lexer_state
|
#define scanner bison_args->lexer_state
|
||||||
|
|
||||||
@ -76,14 +100,6 @@ typedef struct {
|
|||||||
#define curdes (bison_args->designs[bison_args->design_idx])
|
#define curdes (bison_args->designs[bison_args->design_idx])
|
||||||
|
|
||||||
|
|
||||||
static int num_mandatory = 0;
|
|
||||||
static int time_for_se_check = 0;
|
|
||||||
static int num_shapespec = 0; /* number of user-specified shapes */
|
|
||||||
|
|
||||||
int speeding = 0; /* true if we're skipping designs, but no error */
|
|
||||||
static int skipping = 0; /* used to limit "skipping" msgs */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int check_sizes(pass_to_bison *bison_args)
|
static int check_sizes(pass_to_bison *bison_args)
|
||||||
/*
|
/*
|
||||||
@ -293,6 +309,17 @@ static int perform_se_check(pass_to_bison *bison_args)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void chg_strdelims (pass_to_bison *bison_args, const char asesc, const char asdel)
|
||||||
|
{
|
||||||
|
#ifdef PARSER_DEBUG
|
||||||
|
fprintf (stderr, " STATUS: chg_strdelims ('%c', '%c') - This changes lexer behavior!\n", asesc, asdel);
|
||||||
|
#endif
|
||||||
|
bison_args->sesc = asesc;
|
||||||
|
bison_args->sdel = asdel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void recover(pass_to_bison *bison_args)
|
static void recover(pass_to_bison *bison_args)
|
||||||
/*
|
/*
|
||||||
* Reset parser to neutral state, so a new design can be parsed.
|
* Reset parser to neutral state, so a new design can be parsed.
|
||||||
@ -300,10 +327,10 @@ static void recover(pass_to_bison *bison_args)
|
|||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
num_mandatory = 0;
|
bison_args->num_mandatory = 0;
|
||||||
time_for_se_check = 0;
|
bison_args->time_for_se_check = 0;
|
||||||
num_shapespec = 0;
|
bison_args->num_shapespec = 0;
|
||||||
chg_strdelims ('\\', '\"');
|
chg_strdelims(bison_args, '\\', '\"');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear current design
|
* Clear current design
|
||||||
@ -358,7 +385,6 @@ static int design_needed (const char *name, const int design_idx)
|
|||||||
|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|_*/
|
|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|_*/
|
||||||
|
|
||||||
%define api.pure true
|
%define api.pure true
|
||||||
%pure-parser
|
|
||||||
%lex-param {void *scanner}
|
%lex-param {void *scanner}
|
||||||
%parse-param {pass_to_bison *bison_args}
|
%parse-param {pass_to_bison *bison_args}
|
||||||
|
|
||||||
@ -375,6 +401,7 @@ static int design_needed (const char *name, const int design_idx)
|
|||||||
%token <s> KEYWORD
|
%token <s> KEYWORD
|
||||||
%token <s> WORD
|
%token <s> WORD
|
||||||
%token <s> STRING
|
%token <s> STRING
|
||||||
|
%token <s> FILENAME
|
||||||
%token <shape> SHAPE
|
%token <shape> SHAPE
|
||||||
%token <num> YNUMBER
|
%token <num> YNUMBER
|
||||||
%token <c> YRXPFLAG
|
%token <c> YRXPFLAG
|
||||||
@ -410,6 +437,7 @@ first_rule:
|
|||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
bison_args->num_designs = 1;
|
bison_args->num_designs = 1;
|
||||||
|
|
||||||
bison_args->designs->indentmode = DEF_INDENTMODE;
|
bison_args->designs->indentmode = DEF_INDENTMODE;
|
||||||
bison_args->designs->defined_in = bison_args->config_file;
|
bison_args->designs->defined_in = bison_args->config_file;
|
||||||
}
|
}
|
||||||
@ -424,14 +452,11 @@ config_file
|
|||||||
if (bison_args->design_idx == 0) {
|
if (bison_args->design_idx == 0) {
|
||||||
BFREE (bison_args->designs);
|
BFREE (bison_args->designs);
|
||||||
bison_args->num_designs = 0;
|
bison_args->num_designs = 0;
|
||||||
if (opt.design_choice_by_user) {
|
if (!opt.design_choice_by_user && bison_args->num_parent_configs == 0) {
|
||||||
fprintf (stderr, "%s: unknown box design -- %s\n",
|
fprintf (stderr, "%s: no valid data in config file -- %s\n", PROJECT, bison_args->config_file);
|
||||||
PROJECT, (char *) opt.design);
|
YYABORT;
|
||||||
}
|
}
|
||||||
else {
|
YYACCEPT;
|
||||||
yyerror(bison_args, "no valid designs found");
|
|
||||||
}
|
|
||||||
YYABORT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--(bison_args->design_idx);
|
--(bison_args->design_idx);
|
||||||
@ -444,21 +469,21 @@ config_file
|
|||||||
bison_args->designs = tmp;
|
bison_args->designs = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent_def: YPARENT STRING
|
parent_def: YPARENT FILENAME
|
||||||
{
|
{
|
||||||
char *filepath = $2;
|
char *filepath = $2;
|
||||||
#ifdef PARSER_DEBUG
|
#ifdef PARSER_DEBUG
|
||||||
fprintf (stderr, "parent config file specified: [%s]\n", filepath);
|
fprintf (stderr, "parent config file specified: [%s]\n", filepath);
|
||||||
#endif
|
#endif
|
||||||
if (filepath == NULL || filepath[0] == '\0') {
|
if (filepath == NULL || filepath[0] == '\0') {
|
||||||
skipping = 1;
|
bison_args->skipping = 1;
|
||||||
yyerror(bison_args, "parent reference is empty");
|
yyerror(bison_args, "parent reference is empty");
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
else if (strcasecmp(filepath, ":global:") == 0) { /* special token */
|
else if (strcasecmp(filepath, ":global:") == 0) { /* special token */
|
||||||
filepath = discover_config_file(1);
|
filepath = discover_config_file(1);
|
||||||
if (filepath == NULL) {
|
if (filepath == NULL) {
|
||||||
skipping = 1; /* prevent redundant "skipping to next design" message */
|
bison_args->skipping = 1; /* prevent redundant "skipping to next design" message */
|
||||||
yyerror(bison_args, "parent reference to global config which cannot be found");
|
yyerror(bison_args, "parent reference to global config which cannot be found");
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
@ -466,7 +491,7 @@ parent_def: YPARENT STRING
|
|||||||
else {
|
else {
|
||||||
FILE *f = fopen(filepath, "r");
|
FILE *f = fopen(filepath, "r");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
skipping = 1;
|
bison_args->skipping = 1;
|
||||||
yyerror(bison_args, "parent config file not found: %s", filepath);
|
yyerror(bison_args, "parent config file not found: %s", filepath);
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
@ -478,16 +503,17 @@ parent_def: YPARENT STRING
|
|||||||
fprintf (stderr, "parent config file path resolved: [%s]\n", filepath);
|
fprintf (stderr, "parent config file path resolved: [%s]\n", filepath);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int is_new = !array_contains(parent_configs, num_parent_configs, filepath);
|
int is_new = !array_contains(bison_args->parent_configs, bison_args->num_parent_configs, filepath);
|
||||||
if (!is_new) {
|
if (!is_new) {
|
||||||
#ifdef PARSER_DEBUG
|
#ifdef PARSER_DEBUG
|
||||||
fprintf (stderr, "duplicate parent / cycle: [%s]\n", filepath);
|
fprintf (stderr, "duplicate parent / cycle: [%s]\n", filepath);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
parent_configs = realloc(parent_configs, (num_parent_configs + 1) * sizeof(char *));
|
bison_args->parent_configs = realloc(bison_args->parent_configs,
|
||||||
parent_configs[num_parent_configs] = filepath;
|
(bison_args->num_parent_configs + 1) * sizeof(char *));
|
||||||
++num_parent_configs;
|
bison_args->parent_configs[bison_args->num_parent_configs] = filepath;
|
||||||
|
++(bison_args->num_parent_configs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,20 +522,21 @@ config_file: config_file design_or_error | design_or_error | config_file parent_
|
|||||||
|
|
||||||
design_or_error: design | error
|
design_or_error: design | error
|
||||||
{
|
{
|
||||||
if (!speeding && !skipping) {
|
if (!(bison_args->speeding) && !(bison_args->skipping)) {
|
||||||
recover(bison_args);
|
recover(bison_args);
|
||||||
yyerror(bison_args, "skipping to next design");
|
yyerror(bison_args, "skipping to next design");
|
||||||
skipping = 1;
|
bison_args->skipping = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
design: YBOX WORD
|
design: YBOX WORD
|
||||||
{
|
{
|
||||||
chg_strdelims ('\\', '\"');
|
chg_strdelims(bison_args, '\\', '\"');
|
||||||
skipping = 0;
|
bison_args->speeding = 0;
|
||||||
|
bison_args->skipping = 0;
|
||||||
if (!design_needed ($2, bison_args->design_idx)) {
|
if (!design_needed ($2, bison_args->design_idx)) {
|
||||||
speeding = 1;
|
bison_args->speeding = 1;
|
||||||
begin_speedmode(scanner);
|
begin_speedmode(scanner);
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
@ -529,7 +556,7 @@ layout YEND WORD
|
|||||||
yyerror(bison_args, "box design name differs at BOX and END");
|
yyerror(bison_args, "box design name differs at BOX and END");
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
if (num_mandatory < 3) {
|
if (bison_args->num_mandatory < 3) {
|
||||||
yyerror(bison_args, "entries SAMPLE, SHAPES, and ELASTIC are mandatory");
|
yyerror(bison_args, "entries SAMPLE, SHAPES, and ELASTIC are mandatory");
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
@ -556,9 +583,9 @@ layout YEND WORD
|
|||||||
perror (PROJECT);
|
perror (PROJECT);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
num_mandatory = 0;
|
bison_args->num_mandatory = 0;
|
||||||
time_for_se_check = 0;
|
bison_args->time_for_se_check = 0;
|
||||||
num_shapespec = 0;
|
bison_args->num_shapespec = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if we need to continue parsing. If not, return.
|
* Check if we need to continue parsing. If not, return.
|
||||||
@ -655,6 +682,24 @@ entry: KEYWORD STRING
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| YPARENT FILENAME
|
||||||
|
{
|
||||||
|
char *filename = $2;
|
||||||
|
if (filename[0] != filename[strlen(filename) - 1]
|
||||||
|
|| (filename[0] >= 'a' && filename[0] <= 'z')
|
||||||
|
|| (filename[0] >= 'A' && filename[0] <= 'Z')
|
||||||
|
|| (filename[0] >= '0' && filename[0] <= '9'))
|
||||||
|
{
|
||||||
|
yyerror(bison_args, "string expected", filename);
|
||||||
|
YYERROR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#ifdef PARSER_DEBUG
|
||||||
|
fprintf (stderr, "%s: Discarding entry [%s = %s].\n", PROJECT, "parent", filename);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
| YCHGDEL YDELWORD
|
| YCHGDEL YDELWORD
|
||||||
{
|
{
|
||||||
if (strlen($2) != 2) {
|
if (strlen($2) != 2) {
|
||||||
@ -670,7 +715,7 @@ entry: KEYWORD STRING
|
|||||||
($2)[1], LEX_SDELIM);
|
($2)[1], LEX_SDELIM);
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
chg_strdelims ($2[0], $2[1]);
|
chg_strdelims(bison_args, $2[0], $2[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
| WORD STRING
|
| WORD STRING
|
||||||
@ -704,7 +749,7 @@ block: YSAMPLE STRING YENDSAMPLE
|
|||||||
}
|
}
|
||||||
|
|
||||||
curdes.sample = line;
|
curdes.sample = line;
|
||||||
++num_mandatory;
|
++(bison_args->num_mandatory);
|
||||||
}
|
}
|
||||||
|
|
||||||
| YSHAPES '{' slist '}'
|
| YSHAPES '{' slist '}'
|
||||||
@ -719,7 +764,7 @@ block: YSAMPLE STRING YENDSAMPLE
|
|||||||
/*
|
/*
|
||||||
* At least one shape must be specified
|
* At least one shape must be specified
|
||||||
*/
|
*/
|
||||||
if (num_shapespec < 1) {
|
if (bison_args->num_shapespec < 1) {
|
||||||
yyerror(bison_args, "must specify at least one non-empty shape per design");
|
yyerror(bison_args, "must specify at least one non-empty shape per design");
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
@ -808,8 +853,8 @@ block: YSAMPLE STRING YENDSAMPLE
|
|||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
++num_mandatory;
|
++(bison_args->num_mandatory);
|
||||||
if (++time_for_se_check > 1) {
|
if (++(bison_args->time_for_se_check) > 1) {
|
||||||
if (perform_se_check(bison_args) != 0) {
|
if (perform_se_check(bison_args) != 0) {
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
@ -863,8 +908,8 @@ block: YSAMPLE STRING YENDSAMPLE
|
|||||||
|
|
||||||
| YELASTIC '(' elist ')'
|
| YELASTIC '(' elist ')'
|
||||||
{
|
{
|
||||||
++num_mandatory;
|
++(bison_args->num_mandatory);
|
||||||
if (++time_for_se_check > 1) {
|
if (++(bison_args->time_for_se_check) > 1) {
|
||||||
if (perform_se_check(bison_args) != 0) {
|
if (perform_se_check(bison_args) != 0) {
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
@ -970,7 +1015,7 @@ slist_entry: SHAPE shape_def
|
|||||||
if (isempty (curdes.shape + $1)) {
|
if (isempty (curdes.shape + $1)) {
|
||||||
curdes.shape[$1] = $2;
|
curdes.shape[$1] = $2;
|
||||||
if (!isdeepempty(&($2))) {
|
if (!isdeepempty(&($2))) {
|
||||||
++num_shapespec;
|
++(bison_args->num_shapespec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
231
src/parsing.c
231
src/parsing.c
@ -24,73 +24,85 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
#include "boxes.h"
|
#include "boxes.h"
|
||||||
#include "parsing.h"
|
#include "parsing.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "lex.yy.h"
|
#include "lex.yy.h"
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
|
|
||||||
/* file name of the config file currently being parsed */
|
|
||||||
char *current_config_file_name = NULL;
|
|
||||||
|
|
||||||
/** file handle of the config file currently being parsed */
|
/** file handle of the config file currently being parsed */
|
||||||
static FILE *current_config_handle = NULL;
|
static FILE *current_config_handle = NULL;
|
||||||
|
|
||||||
/** names of config files specified via "parent" */
|
|
||||||
char **parent_configs = NULL;
|
|
||||||
|
|
||||||
/** number of parent config files (size of parent_configs array) */
|
|
||||||
size_t num_parent_configs = 0;
|
|
||||||
|
|
||||||
/** the arguments passed to our current invocation of the parser */
|
/** the arguments passed to our current invocation of the parser */
|
||||||
static pass_to_bison *current_bison_args = NULL;
|
static pass_to_bison *current_bison_args = NULL;
|
||||||
|
|
||||||
|
/** the name of the initially specified config file */
|
||||||
|
static const char *first_config_file = NULL;
|
||||||
|
|
||||||
|
/** all parent configs encountered across all parsed config files */
|
||||||
|
static char **parent_configs = NULL;
|
||||||
|
|
||||||
|
/** total number of parent configs (the size of the `parent_configs` array) */
|
||||||
|
static size_t num_parent_configs = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set yyin and current_config_file_name to the config file to be used.
|
* Set yyin to the config file to be used.
|
||||||
*
|
*
|
||||||
* @param bison_args the bison args that we set up in the calling function
|
* @param bison_args the bison args that we set up in the calling function (contains config file path)
|
||||||
* @param config_file_path the new file name to set
|
* @return 0 if successful (yyin is set)
|
||||||
* @return 0 if successful (yyin and current_config_file_name are set)
|
|
||||||
* != 0 on error (yyin is unmodified)
|
* != 0 on error (yyin is unmodified)
|
||||||
*/
|
*/
|
||||||
static int open_yy_config_file(pass_to_bison *bison_args, const char *config_file_path)
|
static int open_yy_config_file(pass_to_bison *bison_args)
|
||||||
{
|
{
|
||||||
current_config_handle = fopen(config_file_path, "r");
|
current_config_handle = fopen(bison_args->config_file, "r");
|
||||||
if (current_config_handle == NULL) {
|
if (current_config_handle == NULL) {
|
||||||
fprintf(stderr, "%s: Couldn't open config file '%s' for input\n", PROJECT, config_file_path);
|
fprintf(stderr, "%s: Couldn't open config file '%s' for input\n", PROJECT, bison_args->config_file);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
current_config_file_name = (char *) config_file_path;
|
|
||||||
yyset_in(current_config_handle, bison_args->lexer_state);
|
yyset_in(current_config_handle, bison_args->lexer_state);
|
||||||
// TODO to reset parser, ‘YY_FLUSH_BUFFER’ and BEGIN INITIAL after each change to yyin.
|
|
||||||
// --> should be ok, because we delete the whole buffer at the beginning, but BEGIN INITIAL may make sense
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void print_design_list_header()
|
void print_design_list_header()
|
||||||
{
|
{
|
||||||
char buf[42];
|
char buf[42];
|
||||||
sprintf(buf, "%d", anz_designs);
|
sprintf(buf, "%d", anz_designs);
|
||||||
|
|
||||||
fprintf(opt.outfile, "%d Available Style%s in \"%s\":\n",
|
fprintf(opt.outfile, "%d Available Style%s", anz_designs, anz_designs == 1 ? "" : "s");
|
||||||
anz_designs, anz_designs == 1 ? "" : "s", current_config_file_name);
|
if (num_parent_configs > 0) {
|
||||||
fprintf(opt.outfile, "-----------------------%s",
|
fprintf(opt.outfile, ":\n");
|
||||||
anz_designs == 1 ? "" : "-");
|
fprintf(opt.outfile, "-----------------%s", anz_designs == 1 ? "" : "-");
|
||||||
for (int i = strlen(current_config_file_name) + strlen(buf); i > 0; --i) {
|
for (int i = strlen(buf); i > 0; --i) {
|
||||||
fprintf(opt.outfile, "-");
|
fprintf(opt.outfile, "-");
|
||||||
|
}
|
||||||
|
fprintf(opt.outfile, "\n\n");
|
||||||
|
fprintf(opt.outfile, "Configuration Files:\n");
|
||||||
|
fprintf(opt.outfile, " - %s\n", first_config_file);
|
||||||
|
for (size_t i = 0; i < num_parent_configs; i++) {
|
||||||
|
fprintf(opt.outfile, " - %s (parent)\n", parent_configs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(opt.outfile, " in \"%s\":\n", first_config_file);
|
||||||
|
fprintf(opt.outfile, "-----------------------%s", anz_designs == 1 ? "" : "-");
|
||||||
|
for (int i = strlen(first_config_file) + strlen(buf); i > 0; --i) {
|
||||||
|
fprintf(opt.outfile, "-");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fprintf(opt.outfile, "\n\n");
|
fprintf(opt.outfile, "\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print configuration file parser errors.
|
* Print configuration file parser errors.
|
||||||
* @param bison_args pointer to the parser arguments
|
* @param bison_args pointer to the parser arguments
|
||||||
@ -104,9 +116,7 @@ int yyerror(pass_to_bison *bison_args, const char *fmt, ...)
|
|||||||
va_start (ap, fmt);
|
va_start (ap, fmt);
|
||||||
|
|
||||||
pass_to_bison *bargs = bison_args ? bison_args : current_bison_args;
|
pass_to_bison *bargs = bison_args ? bison_args : current_bison_args;
|
||||||
fprintf(stderr, "%s: %s: line %d: ", PROJECT,
|
fprintf(stderr, "%s: %s: line %d: ", PROJECT, bargs->config_file, yyget_lineno(bargs->lexer_state));
|
||||||
current_config_file_name ? current_config_file_name : "(null)",
|
|
||||||
yyget_lineno(bargs->lexer_state));
|
|
||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
fputc('\n', stderr);
|
fputc('\n', stderr);
|
||||||
|
|
||||||
@ -117,24 +127,54 @@ int yyerror(pass_to_bison *bison_args, const char *fmt, ...)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static design_t *parse_config_file(const char *config_file, size_t *r_num_designs)
|
static pass_to_bison new_bison_args(const char *config_file)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf (stderr, "Parsing Config File %s ...\n", config_file);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pass_to_bison bison_args;
|
pass_to_bison bison_args;
|
||||||
bison_args.designs = NULL;
|
bison_args.designs = NULL;
|
||||||
bison_args.num_designs = 0;
|
bison_args.num_designs = 0;
|
||||||
bison_args.design_idx = 0;
|
bison_args.design_idx = 0;
|
||||||
bison_args.config_file = (char *) config_file;
|
bison_args.config_file = (char *) config_file;
|
||||||
|
bison_args.sdel = '\"'; /* sdel is shared by flex and bison */
|
||||||
|
bison_args.sesc = '\\'; /* sesc is shared by flex and bison */
|
||||||
|
bison_args.num_mandatory = 0;
|
||||||
|
bison_args.time_for_se_check = 0;
|
||||||
|
bison_args.num_shapespec = 0;
|
||||||
|
bison_args.skipping = 0;
|
||||||
|
bison_args.speeding = 0;
|
||||||
|
bison_args.parent_configs = NULL;
|
||||||
|
bison_args.num_parent_configs = 0;
|
||||||
bison_args.lexer_state = NULL;
|
bison_args.lexer_state = NULL;
|
||||||
|
return bison_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static pass_to_flex new_flex_extra_data(pass_to_bison *bison_args)
|
||||||
|
{
|
||||||
|
pass_to_flex flex_extra_data;
|
||||||
|
flex_extra_data.yyerrcnt = 0;
|
||||||
|
flex_extra_data.sdel_ptr = &(bison_args->sdel);
|
||||||
|
flex_extra_data.sesc_ptr = &(bison_args->sesc);
|
||||||
|
return flex_extra_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static pass_to_bison parse_config_file(const char *config_file)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf (stderr, "Parsing Config File %s ...\n", config_file);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pass_to_bison bison_args = new_bison_args(config_file);
|
||||||
|
pass_to_flex flex_extra_data = new_flex_extra_data(&bison_args);
|
||||||
current_bison_args = &bison_args;
|
current_bison_args = &bison_args;
|
||||||
|
|
||||||
yylex_init (&(bison_args.lexer_state));
|
yylex_init (&(bison_args.lexer_state));
|
||||||
int rc = open_yy_config_file(&bison_args, config_file);
|
yylex_init_extra(&flex_extra_data, &(bison_args.lexer_state));
|
||||||
|
int rc = open_yy_config_file(&bison_args);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
return NULL;
|
return new_bison_args(config_file);
|
||||||
}
|
}
|
||||||
inflate_inbuf(bison_args.lexer_state, config_file);
|
inflate_inbuf(bison_args.lexer_state, config_file);
|
||||||
rc = yyparse(&bison_args);
|
rc = yyparse(&bison_args);
|
||||||
@ -146,19 +186,126 @@ static design_t *parse_config_file(const char *config_file, size_t *r_num_design
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
return NULL;
|
#ifdef DEBUG
|
||||||
|
fprintf (stderr, "yyparse() returned %d\n", rc);
|
||||||
|
#endif
|
||||||
|
return new_bison_args(config_file);
|
||||||
}
|
}
|
||||||
*r_num_designs = bison_args.num_designs;
|
return bison_args;
|
||||||
return bison_args.designs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
design_t *parse_config_files(const char *first_config_file, size_t *r_num_designs)
|
static int designs_contain(design_t *designs, size_t num_designs, design_t adesign)
|
||||||
{
|
{
|
||||||
// TODO much code
|
int result = adesign.name == NULL; /* broken records count as "present", so we don't copy them */
|
||||||
|
if (designs != NULL && num_designs > 0 && adesign.name != NULL) {
|
||||||
|
for (size_t d = 0; d < num_designs; d++) {
|
||||||
|
if (strcasecmp(designs[d].name, adesign.name) == 0) {
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return parse_config_file(first_config_file, r_num_designs);
|
|
||||||
|
|
||||||
|
static int record_parent_config_files(pass_to_bison *bison_args)
|
||||||
|
{
|
||||||
|
if (bison_args->num_parent_configs > 0) {
|
||||||
|
for (int parent_idx = bison_args->num_parent_configs - 1; parent_idx >= 0; parent_idx--) {
|
||||||
|
char *parent_file = bison_args->parent_configs[parent_idx];
|
||||||
|
int is_new = !array_contains(parent_configs, num_parent_configs, parent_file);
|
||||||
|
if (is_new) {
|
||||||
|
parent_configs = (char **) realloc(parent_configs, (num_parent_configs + 1) * sizeof(char *));
|
||||||
|
if (parent_configs == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
parent_configs[num_parent_configs] = parent_file;
|
||||||
|
++num_parent_configs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BFREE(bison_args->parent_configs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int copy_designs(pass_to_bison *bison_args, design_t **r_result, size_t *r_num_designs)
|
||||||
|
{
|
||||||
|
if (bison_args->num_designs > 0) {
|
||||||
|
if (*r_result == NULL) {
|
||||||
|
*r_result = bison_args->designs;
|
||||||
|
*r_num_designs = bison_args->num_designs;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (size_t d = 0; d < bison_args->num_designs; d++) {
|
||||||
|
if (!designs_contain(*r_result, *r_num_designs, bison_args->designs[d])) {
|
||||||
|
*r_result = (design_t *) realloc(*r_result, (*r_num_designs + 1) * sizeof(design_t));
|
||||||
|
if (*r_result == NULL) {
|
||||||
|
perror(PROJECT);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
memcpy(*r_result + *r_num_designs, bison_args->designs + d, sizeof(design_t));
|
||||||
|
(*r_num_designs)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BFREE(bison_args->designs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
design_t *parse_config_files(const char *p_first_config_file, size_t *r_num_designs)
|
||||||
|
{
|
||||||
|
size_t parents_parsed = -1; /** how many parent config files have already been parsed */
|
||||||
|
|
||||||
|
design_t *result = NULL;
|
||||||
|
*r_num_designs = 0;
|
||||||
|
|
||||||
|
first_config_file = p_first_config_file;
|
||||||
|
const char *config_file = p_first_config_file;
|
||||||
|
do {
|
||||||
|
pass_to_bison bison_args = parse_config_file(config_file);
|
||||||
|
++parents_parsed;
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf (stderr, "bison_args returned: "
|
||||||
|
".num_parent_configs=%d, .parent_configs=%p, .num_designs=%d, .designs=%p\n",
|
||||||
|
(int) bison_args.num_parent_configs, bison_args.parent_configs,
|
||||||
|
(int) bison_args.num_designs, bison_args.designs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (record_parent_config_files(&bison_args) != 0) {
|
||||||
|
perror(PROJECT);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (copy_designs(&bison_args, &result, r_num_designs) != 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf (stderr, "design count raised to: %d\n", (int) *r_num_designs);
|
||||||
|
#endif
|
||||||
|
if (parents_parsed < num_parent_configs) {
|
||||||
|
config_file = parent_configs[parents_parsed];
|
||||||
|
}
|
||||||
|
} while (parents_parsed < num_parent_configs);
|
||||||
|
|
||||||
|
if (*r_num_designs == 0) {
|
||||||
|
if (opt.design_choice_by_user) {
|
||||||
|
fprintf (stderr, "%s: unknown box design -- %s\n", PROJECT, (char *) opt.design);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf (stderr, "%s: no valid designs found\n", PROJECT);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,20 +28,8 @@
|
|||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
|
|
||||||
/** file name of config file used */
|
|
||||||
extern char *config_file_name;
|
|
||||||
|
|
||||||
/** names of config files specified via "parent" */
|
|
||||||
extern char **parent_configs;
|
|
||||||
|
|
||||||
/** number of parent config files (size of parent_configs array) */
|
|
||||||
extern size_t num_parent_configs;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print the header for the design list output, which includes the file name.
|
* Print the header for the design list output, which includes the file name(s).
|
||||||
* TODO what if more file names used?
|
|
||||||
*/
|
*/
|
||||||
void print_design_list_header();
|
void print_design_list_header();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user