@@ -63,16 +63,21 @@ static bool isinformixdefine(void);
63
63
char *token_start;
64
64
static int state_before;
65
65
66
- struct _yy_buffer
66
+ /*
67
+ * State for handling include files and macro expansion. We use a new
68
+ * flex input buffer for each level of include or macro, and create a
69
+ * struct _yy_buffer to remember the previous level. There is not a struct
70
+ * for the currently active input source; that state is kept in the global
71
+ * variables YY_CURRENT_BUFFER, yylineno, and input_filename.
72
+ */
73
+ static struct _yy_buffer
67
74
{
68
75
YY_BUFFER_STATE buffer;
69
76
long lineno;
70
77
char *filename;
71
78
struct _yy_buffer *next;
72
79
} *yy_buffer = NULL ;
73
80
74
- static char *old;
75
-
76
81
#define MAX_NESTED_IF 128
77
82
static short preproc_tos;
78
83
static short ifcond;
@@ -401,6 +406,8 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
401
406
402
407
%{
403
408
/* code to execute during start of each call of yylex() */
409
+ char *newdefsymbol = NULL ;
410
+
404
411
token_start = NULL ;
405
412
%}
406
413
@@ -920,6 +927,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
920
927
}
921
928
922
929
{identifier } {
930
+ /* First check to see if it's a define symbol to expand */
923
931
if (!isdefine ())
924
932
{
925
933
int kwvalue;
@@ -1112,17 +1120,23 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1112
1120
yytext[i+1 ] = ' \0 ' ;
1113
1121
1114
1122
1115
- for (ptr = defines; ptr != NULL ; ptr2 = ptr, ptr = ptr->next )
1123
+ /* Find and unset any matching define; should be only 1 */
1124
+ for (ptr = defines; ptr; ptr2 = ptr, ptr = ptr->next )
1116
1125
{
1117
- if (strcmp (yytext, ptr->olddef ) == 0 )
1126
+ if (strcmp (yytext, ptr->name ) == 0 )
1118
1127
{
1119
- if (ptr2 == NULL )
1120
- defines = ptr->next ;
1121
- else
1122
- ptr2->next = ptr->next ;
1123
- free (ptr->newdef );
1124
- free (ptr->olddef );
1125
- free (ptr);
1128
+ free (ptr->value );
1129
+ ptr->value = NULL ;
1130
+ /* We cannot forget it if there's a cmdvalue */
1131
+ if (ptr->cmdvalue == NULL )
1132
+ {
1133
+ if (ptr2 == NULL )
1134
+ defines = ptr->next ;
1135
+ else
1136
+ ptr2->next = ptr->next ;
1137
+ free (ptr->name );
1138
+ free (ptr);
1139
+ }
1126
1140
break ;
1127
1141
}
1128
1142
}
@@ -1299,11 +1313,17 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1299
1313
;
1300
1314
yytext[i+1 ] = ' \0 ' ;
1301
1315
1302
- for (defptr = defines;
1303
- defptr != NULL &&
1304
- strcmp (yytext, defptr->olddef ) != 0 ;
1305
- defptr = defptr->next )
1306
- /* skip */ ;
1316
+ /* Does a definition exist? */
1317
+ for (defptr = defines; defptr; defptr = defptr->next )
1318
+ {
1319
+ if (strcmp (yytext, defptr->name ) == 0 )
1320
+ {
1321
+ /* Found it, but is it currently undefined? */
1322
+ if (defptr->value == NULL )
1323
+ defptr = NULL ; /* pretend it's not found */
1324
+ break ;
1325
+ }
1326
+ }
1307
1327
1308
1328
preproc_tos++;
1309
1329
stacked_if_value[preproc_tos].else_branch = false ;
@@ -1322,7 +1342,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1322
1342
yyterminate ();
1323
1343
}
1324
1344
<def_ident >{identifier } {
1325
- old = mm_strdup (yytext);
1345
+ newdefsymbol = mm_strdup (yytext);
1326
1346
BEGIN (def);
1327
1347
startlit ();
1328
1348
}
@@ -1331,26 +1351,31 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1331
1351
yyterminate ();
1332
1352
}
1333
1353
<def >{space }* " ;" {
1334
- struct _defines *ptr, * this ;
1354
+ struct _defines *ptr;
1335
1355
1356
+ /* Does it already exist? */
1336
1357
for (ptr = defines; ptr != NULL ; ptr = ptr->next )
1337
1358
{
1338
- if (strcmp (old, ptr->olddef ) == 0 )
1339
- {
1340
- free (ptr->newdef );
1341
- ptr->newdef = mm_strdup (literalbuf);
1342
- }
1359
+ if (strcmp (newdefsymbol, ptr->name ) == 0 )
1360
+ {
1361
+ free (ptr->value );
1362
+ ptr->value = mm_strdup (literalbuf);
1363
+ /* Don't leak newdefsymbol */
1364
+ free (newdefsymbol);
1365
+ break ;
1366
+ }
1343
1367
}
1344
1368
if (ptr == NULL )
1345
1369
{
1346
- this = (struct _defines *) mm_alloc (sizeof (struct _defines ));
1347
-
1348
- /* initial definition */
1349
- this ->olddef = old;
1350
- this ->newdef = mm_strdup (literalbuf);
1351
- this ->next = defines;
1352
- this ->used = NULL ;
1353
- defines = this ;
1370
+ /* Not present, make a new entry */
1371
+ ptr = (struct _defines *) mm_alloc (sizeof (struct _defines ));
1372
+
1373
+ ptr->name = newdefsymbol;
1374
+ ptr->value = mm_strdup (literalbuf);
1375
+ ptr->cmdvalue = NULL ;
1376
+ ptr->used = NULL ;
1377
+ ptr->next = defines;
1378
+ defines = ptr;
1354
1379
}
1355
1380
1356
1381
BEGIN (C);
@@ -1367,6 +1392,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1367
1392
<<EOF>> {
1368
1393
if (yy_buffer == NULL )
1369
1394
{
1395
+ /* No more input */
1370
1396
if ( preproc_tos > 0 )
1371
1397
{
1372
1398
preproc_tos = 0 ;
@@ -1376,16 +1402,20 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1376
1402
}
1377
1403
else
1378
1404
{
1405
+ /* Revert to previous input source */
1379
1406
struct _yy_buffer *yb = yy_buffer;
1380
1407
int i;
1381
1408
struct _defines *ptr;
1382
1409
1410
+ /* Check to see if we are exiting a macro value */
1383
1411
for (ptr = defines; ptr; ptr = ptr->next )
1412
+ {
1384
1413
if (ptr->used == yy_buffer)
1385
1414
{
1386
1415
ptr->used = NULL ;
1387
- break ;
1416
+ break ; /* there can't be multiple matches */
1388
1417
}
1418
+ }
1389
1419
1390
1420
if (yyin != NULL )
1391
1421
fclose (yyin);
@@ -1608,15 +1638,24 @@ ecpg_isspace(char ch)
1608
1638
return false ;
1609
1639
}
1610
1640
1611
- static bool isdefine (void )
1641
+ /*
1642
+ * If yytext matches a define symbol, begin scanning the symbol's value
1643
+ * and return true
1644
+ */
1645
+ static bool
1646
+ isdefine (void )
1612
1647
{
1613
1648
struct _defines *ptr;
1614
1649
1615
1650
/* is it a define? */
1616
1651
for (ptr = defines; ptr; ptr = ptr->next )
1617
1652
{
1618
- if (strcmp (yytext, ptr->olddef ) == 0 && ptr->used == NULL )
1653
+ /* notice we do not match anything being actively expanded */
1654
+ if (strcmp (yytext, ptr->name ) == 0 &&
1655
+ ptr->value != NULL &&
1656
+ ptr->used == NULL )
1619
1657
{
1658
+ /* Save state associated with the current buffer */
1620
1659
struct _yy_buffer *yb;
1621
1660
1622
1661
yb = mm_alloc (sizeof (struct _yy_buffer ));
@@ -1625,18 +1664,30 @@ static bool isdefine(void)
1625
1664
yb->lineno = yylineno;
1626
1665
yb->filename = mm_strdup (input_filename);
1627
1666
yb->next = yy_buffer;
1667
+ yy_buffer = yb;
1628
1668
1629
- ptr->used = yy_buffer = yb;
1669
+ /* Mark symbol as being actively expanded */
1670
+ ptr->used = yb;
1630
1671
1631
- yy_scan_string (ptr->newdef );
1672
+ /*
1673
+ * We use yy_scan_string which will copy the value, so there's
1674
+ * no need to worry about a possible undef happening while we
1675
+ * are still scanning it.
1676
+ */
1677
+ yy_scan_string (ptr->value );
1632
1678
return true ;
1633
1679
}
1634
1680
}
1635
1681
1636
1682
return false ;
1637
1683
}
1638
1684
1639
- static bool isinformixdefine (void )
1685
+ /*
1686
+ * Handle replacement of INFORMIX built-in defines. This works just
1687
+ * like isdefine() except for the source of the string to scan.
1688
+ */
1689
+ static bool
1690
+ isinformixdefine (void )
1640
1691
{
1641
1692
const char *new = NULL ;
1642
1693
0 commit comments