@@ -69,16 +69,21 @@ char *token_start;
69
69
static int state_before_str_start;
70
70
static int state_before_str_stop;
71
71
72
- struct _yy_buffer
72
+ /*
73
+ * State for handling include files and macro expansion. We use a new
74
+ * flex input buffer for each level of include or macro, and create a
75
+ * struct _yy_buffer to remember the previous level. There is not a struct
76
+ * for the currently active input source; that state is kept in the global
77
+ * variables YY_CURRENT_BUFFER, yylineno, and input_filename.
78
+ */
79
+ static struct _yy_buffer
73
80
{
74
81
YY_BUFFER_STATE buffer;
75
82
long lineno;
76
83
char *filename;
77
84
struct _yy_buffer *next;
78
85
} *yy_buffer = NULL ;
79
86
80
- static char *old;
81
-
82
87
/*
83
88
* Vars for handling ifdef/elif/endif constructs. preproc_tos is the current
84
89
* nesting depth of such constructs, and stacked_if_value[preproc_tos] is the
@@ -444,6 +449,8 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
444
449
445
450
%{
446
451
/* code to execute during start of each call of yylex() */
452
+ char *newdefsymbol = NULL ;
453
+
447
454
token_start = NULL ;
448
455
%}
449
456
@@ -1010,6 +1017,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1010
1017
}
1011
1018
1012
1019
{identifier } {
1020
+ /* First check to see if it's a define symbol to expand */
1013
1021
if (!isdefine ())
1014
1022
{
1015
1023
int kwvalue;
@@ -1198,17 +1206,23 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1198
1206
yytext[i+1 ] = ' \0 ' ;
1199
1207
1200
1208
1201
- for (ptr = defines; ptr != NULL ; ptr2 = ptr, ptr = ptr->next )
1209
+ /* Find and unset any matching define; should be only 1 */
1210
+ for (ptr = defines; ptr; ptr2 = ptr, ptr = ptr->next )
1202
1211
{
1203
- if (strcmp (yytext, ptr->olddef ) == 0 )
1212
+ if (strcmp (yytext, ptr->name ) == 0 )
1204
1213
{
1205
- if (ptr2 == NULL )
1206
- defines = ptr->next ;
1207
- else
1208
- ptr2->next = ptr->next ;
1209
- free (ptr->newdef );
1210
- free (ptr->olddef );
1211
- free (ptr);
1214
+ free (ptr->value );
1215
+ ptr->value = NULL ;
1216
+ /* We cannot forget it if there's a cmdvalue */
1217
+ if (ptr->cmdvalue == NULL )
1218
+ {
1219
+ if (ptr2 == NULL )
1220
+ defines = ptr->next ;
1221
+ else
1222
+ ptr2->next = ptr->next ;
1223
+ free (ptr->name );
1224
+ free (ptr);
1225
+ }
1212
1226
break ;
1213
1227
}
1214
1228
}
@@ -1413,11 +1427,17 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1413
1427
;
1414
1428
yytext[i+1 ] = ' \0 ' ;
1415
1429
1416
- for (defptr = defines;
1417
- defptr != NULL &&
1418
- strcmp (yytext, defptr->olddef ) != 0 ;
1419
- defptr = defptr->next )
1420
- /* skip */ ;
1430
+ /* Does a definition exist? */
1431
+ for (defptr = defines; defptr; defptr = defptr->next )
1432
+ {
1433
+ if (strcmp (yytext, defptr->name ) == 0 )
1434
+ {
1435
+ /* Found it, but is it currently undefined? */
1436
+ if (defptr->value == NULL )
1437
+ defptr = NULL ; /* pretend it's not found */
1438
+ break ;
1439
+ }
1440
+ }
1421
1441
1422
1442
this_active = (defptr ? ifcond : !ifcond);
1423
1443
stacked_if_value[preproc_tos].active =
@@ -1438,7 +1458,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1438
1458
yyterminate ();
1439
1459
}
1440
1460
<def_ident >{identifier } {
1441
- old = mm_strdup (yytext);
1461
+ newdefsymbol = mm_strdup (yytext);
1442
1462
BEGIN (def);
1443
1463
startlit ();
1444
1464
}
@@ -1447,26 +1467,31 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1447
1467
yyterminate ();
1448
1468
}
1449
1469
<def >{space }* " ;" {
1450
- struct _defines *ptr, * this ;
1470
+ struct _defines *ptr;
1451
1471
1472
+ /* Does it already exist? */
1452
1473
for (ptr = defines; ptr != NULL ; ptr = ptr->next )
1453
1474
{
1454
- if (strcmp (old, ptr->olddef ) == 0 )
1455
- {
1456
- free (ptr->newdef );
1457
- ptr->newdef = mm_strdup (literalbuf);
1458
- }
1475
+ if (strcmp (newdefsymbol, ptr->name ) == 0 )
1476
+ {
1477
+ free (ptr->value );
1478
+ ptr->value = mm_strdup (literalbuf);
1479
+ /* Don't leak newdefsymbol */
1480
+ free (newdefsymbol);
1481
+ break ;
1482
+ }
1459
1483
}
1460
1484
if (ptr == NULL )
1461
1485
{
1462
- this = (struct _defines *) mm_alloc (sizeof (struct _defines ));
1463
-
1464
- /* initial definition */
1465
- this ->olddef = old;
1466
- this ->newdef = mm_strdup (literalbuf);
1467
- this ->next = defines;
1468
- this ->used = NULL ;
1469
- defines = this ;
1486
+ /* Not present, make a new entry */
1487
+ ptr = (struct _defines *) mm_alloc (sizeof (struct _defines ));
1488
+
1489
+ ptr->name = newdefsymbol;
1490
+ ptr->value = mm_strdup (literalbuf);
1491
+ ptr->cmdvalue = NULL ;
1492
+ ptr->used = NULL ;
1493
+ ptr->next = defines;
1494
+ defines = ptr;
1470
1495
}
1471
1496
1472
1497
BEGIN (C);
@@ -1483,6 +1508,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1483
1508
<<EOF>> {
1484
1509
if (yy_buffer == NULL )
1485
1510
{
1511
+ /* No more input */
1486
1512
if (preproc_tos > 0 )
1487
1513
{
1488
1514
preproc_tos = 0 ;
@@ -1492,16 +1518,20 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
1492
1518
}
1493
1519
else
1494
1520
{
1521
+ /* Revert to previous input source */
1495
1522
struct _yy_buffer *yb = yy_buffer;
1496
1523
int i;
1497
1524
struct _defines *ptr;
1498
1525
1526
+ /* Check to see if we are exiting a macro value */
1499
1527
for (ptr = defines; ptr; ptr = ptr->next )
1528
+ {
1500
1529
if (ptr->used == yy_buffer)
1501
1530
{
1502
1531
ptr->used = NULL ;
1503
- break ;
1532
+ break ; /* there can't be multiple matches */
1504
1533
}
1534
+ }
1505
1535
1506
1536
if (yyin != NULL )
1507
1537
fclose (yyin);
@@ -1727,15 +1757,24 @@ ecpg_isspace(char ch)
1727
1757
return false ;
1728
1758
}
1729
1759
1730
- static bool isdefine (void )
1760
+ /*
1761
+ * If yytext matches a define symbol, begin scanning the symbol's value
1762
+ * and return true
1763
+ */
1764
+ static bool
1765
+ isdefine (void )
1731
1766
{
1732
1767
struct _defines *ptr;
1733
1768
1734
1769
/* is it a define? */
1735
1770
for (ptr = defines; ptr; ptr = ptr->next )
1736
1771
{
1737
- if (strcmp (yytext, ptr->olddef ) == 0 && ptr->used == NULL )
1772
+ /* notice we do not match anything being actively expanded */
1773
+ if (strcmp (yytext, ptr->name ) == 0 &&
1774
+ ptr->value != NULL &&
1775
+ ptr->used == NULL )
1738
1776
{
1777
+ /* Save state associated with the current buffer */
1739
1778
struct _yy_buffer *yb;
1740
1779
1741
1780
yb = mm_alloc (sizeof (struct _yy_buffer ));
@@ -1744,18 +1783,30 @@ static bool isdefine(void)
1744
1783
yb->lineno = yylineno;
1745
1784
yb->filename = mm_strdup (input_filename);
1746
1785
yb->next = yy_buffer;
1786
+ yy_buffer = yb;
1747
1787
1748
- ptr->used = yy_buffer = yb;
1788
+ /* Mark symbol as being actively expanded */
1789
+ ptr->used = yb;
1749
1790
1750
- yy_scan_string (ptr->newdef );
1791
+ /*
1792
+ * We use yy_scan_string which will copy the value, so there's
1793
+ * no need to worry about a possible undef happening while we
1794
+ * are still scanning it.
1795
+ */
1796
+ yy_scan_string (ptr->value );
1751
1797
return true ;
1752
1798
}
1753
1799
}
1754
1800
1755
1801
return false ;
1756
1802
}
1757
1803
1758
- static bool isinformixdefine (void )
1804
+ /*
1805
+ * Handle replacement of INFORMIX built-in defines. This works just
1806
+ * like isdefine() except for the source of the string to scan.
1807
+ */
1808
+ static bool
1809
+ isinformixdefine (void )
1759
1810
{
1760
1811
const char *new = NULL ;
1761
1812
0 commit comments