summaryrefslogtreecommitdiffstats
path: root/src/interfaces/ecpg/preproc/pgc.l
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/ecpg/preproc/pgc.l')
-rw-r--r--src/interfaces/ecpg/preproc/pgc.l127
1 files changed, 89 insertions, 38 deletions
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index 996718c..c06b2d6 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -69,7 +69,14 @@ char *token_start;
static int state_before_str_start;
static int state_before_str_stop;
-struct _yy_buffer
+/*
+ * State for handling include files and macro expansion. We use a new
+ * flex input buffer for each level of include or macro, and create a
+ * struct _yy_buffer to remember the previous level. There is not a struct
+ * for the currently active input source; that state is kept in the global
+ * variables YY_CURRENT_BUFFER, yylineno, and input_filename.
+ */
+static struct _yy_buffer
{
YY_BUFFER_STATE buffer;
long lineno;
@@ -77,8 +84,6 @@ struct _yy_buffer
struct _yy_buffer *next;
} *yy_buffer = NULL;
-static char *old;
-
/*
* Vars for handling ifdef/elif/endif constructs. preproc_tos is the current
* nesting depth of such constructs, and stacked_if_value[preproc_tos] is the
@@ -432,6 +437,8 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
%{
/* code to execute during start of each call of yylex() */
+ char *newdefsymbol = NULL;
+
token_start = NULL;
%}
@@ -979,6 +986,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
}
{identifier} {
+ /* First check to see if it's a define symbol to expand */
if (!isdefine())
{
int kwvalue;
@@ -1171,17 +1179,23 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
yytext[i+1] = '\0';
- for (ptr = defines; ptr != NULL; ptr2 = ptr, ptr = ptr->next)
+ /* Find and unset any matching define; should be only 1 */
+ for (ptr = defines; ptr; ptr2 = ptr, ptr = ptr->next)
{
- if (strcmp(yytext, ptr->olddef) == 0)
+ if (strcmp(yytext, ptr->name) == 0)
{
- if (ptr2 == NULL)
- defines = ptr->next;
- else
- ptr2->next = ptr->next;
- free(ptr->newdef);
- free(ptr->olddef);
- free(ptr);
+ free(ptr->value);
+ ptr->value = NULL;
+ /* We cannot forget it if there's a cmdvalue */
+ if (ptr->cmdvalue == NULL)
+ {
+ if (ptr2 == NULL)
+ defines = ptr->next;
+ else
+ ptr2->next = ptr->next;
+ free(ptr->name);
+ free(ptr);
+ }
break;
}
}
@@ -1386,11 +1400,17 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
;
yytext[i+1] = '\0';
- for (defptr = defines;
- defptr != NULL &&
- strcmp(yytext, defptr->olddef) != 0;
- defptr = defptr->next)
- /* skip */ ;
+ /* Does a definition exist? */
+ for (defptr = defines; defptr; defptr = defptr->next)
+ {
+ if (strcmp(yytext, defptr->name) == 0)
+ {
+ /* Found it, but is it currently undefined? */
+ if (defptr->value == NULL)
+ defptr = NULL; /* pretend it's not found */
+ break;
+ }
+ }
this_active = (defptr ? ifcond : !ifcond);
stacked_if_value[preproc_tos].active =
@@ -1411,7 +1431,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
yyterminate();
}
<def_ident>{identifier} {
- old = mm_strdup(yytext);
+ newdefsymbol = mm_strdup(yytext);
BEGIN(def);
startlit();
}
@@ -1420,26 +1440,31 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
yyterminate();
}
<def>{space}*";" {
- struct _defines *ptr, *this;
+ struct _defines *ptr;
+ /* Does it already exist? */
for (ptr = defines; ptr != NULL; ptr = ptr->next)
{
- if (strcmp(old, ptr->olddef) == 0)
- {
- free(ptr->newdef);
- ptr->newdef = mm_strdup(literalbuf);
- }
+ if (strcmp(newdefsymbol, ptr->name) == 0)
+ {
+ free(ptr->value);
+ ptr->value = mm_strdup(literalbuf);
+ /* Don't leak newdefsymbol */
+ free(newdefsymbol);
+ break;
+ }
}
if (ptr == NULL)
{
- this = (struct _defines *) mm_alloc(sizeof(struct _defines));
-
- /* initial definition */
- this->olddef = old;
- this->newdef = mm_strdup(literalbuf);
- this->next = defines;
- this->used = NULL;
- defines = this;
+ /* Not present, make a new entry */
+ ptr = (struct _defines *) mm_alloc(sizeof(struct _defines));
+
+ ptr->name = newdefsymbol;
+ ptr->value = mm_strdup(literalbuf);
+ ptr->cmdvalue = NULL;
+ ptr->used = NULL;
+ ptr->next = defines;
+ defines = ptr;
}
BEGIN(C);
@@ -1456,6 +1481,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
<<EOF>> {
if (yy_buffer == NULL)
{
+ /* No more input */
if (preproc_tos > 0)
{
preproc_tos = 0;
@@ -1465,16 +1491,20 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
}
else
{
+ /* Revert to previous input source */
struct _yy_buffer *yb = yy_buffer;
int i;
struct _defines *ptr;
+ /* Check to see if we are exiting a macro value */
for (ptr = defines; ptr; ptr = ptr->next)
+ {
if (ptr->used == yy_buffer)
{
ptr->used = NULL;
- break;
+ break; /* there can't be multiple matches */
}
+ }
if (yyin != NULL)
fclose(yyin);
@@ -1699,15 +1729,24 @@ ecpg_isspace(char ch)
return false;
}
-static bool isdefine(void)
+/*
+ * If yytext matches a define symbol, begin scanning the symbol's value
+ * and return true
+ */
+static bool
+isdefine(void)
{
struct _defines *ptr;
/* is it a define? */
for (ptr = defines; ptr; ptr = ptr->next)
{
- if (strcmp(yytext, ptr->olddef) == 0 && ptr->used == NULL)
+ /* notice we do not match anything being actively expanded */
+ if (strcmp(yytext, ptr->name) == 0 &&
+ ptr->value != NULL &&
+ ptr->used == NULL)
{
+ /* Save state associated with the current buffer */
struct _yy_buffer *yb;
yb = mm_alloc(sizeof(struct _yy_buffer));
@@ -1716,10 +1755,17 @@ static bool isdefine(void)
yb->lineno = yylineno;
yb->filename = mm_strdup(input_filename);
yb->next = yy_buffer;
+ yy_buffer = yb;
- ptr->used = yy_buffer = yb;
+ /* Mark symbol as being actively expanded */
+ ptr->used = yb;
- yy_scan_string(ptr->newdef);
+ /*
+ * We use yy_scan_string which will copy the value, so there's
+ * no need to worry about a possible undef happening while we
+ * are still scanning it.
+ */
+ yy_scan_string(ptr->value);
return true;
}
}
@@ -1727,7 +1773,12 @@ static bool isdefine(void)
return false;
}
-static bool isinformixdefine(void)
+/*
+ * Handle replacement of INFORMIX built-in defines. This works just
+ * like isdefine() except for the source of the string to scan.
+ */
+static bool
+isinformixdefine(void)
{
const char *new = NULL;