Fix preprocessor breakages introduced in rev 12441 which was fixing defined() being expanded outside of #if and #elif preprocessor directives
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12455 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
63af0a2d72
commit
16ba0aca53
4 changed files with 182 additions and 70 deletions
|
|
@ -5,7 +5,7 @@ See the RELEASENOTES file for a summary of changes in each release.
|
||||||
Version 2.0.2 (in progress)
|
Version 2.0.2 (in progress)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
2011-02-07: wsfulton
|
2011-02-12: wsfulton
|
||||||
Fix #1940536, overactive preprocessor which was expanding defined(...) outside of #if and #elif
|
Fix #1940536, overactive preprocessor which was expanding defined(...) outside of #if and #elif
|
||||||
preprocessor directives.
|
preprocessor directives.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,3 +34,75 @@ int call_checking(void) {
|
||||||
return checking();
|
return checking();
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Check #if/#elif defined() macro expansions
|
||||||
|
Also checks #if/#elif defined() works correctly within macros... this is not
|
||||||
|
standard C, but is now relied on in the SWIG library. */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#define AAA
|
||||||
|
#define BBB
|
||||||
|
#define CCC
|
||||||
|
|
||||||
|
#if defined(AAA)\
|
||||||
|
&& defined(BBB) \
|
||||||
|
&& defined(CCC)
|
||||||
|
%{
|
||||||
|
void thing(int i) {}
|
||||||
|
void stuff(int i) {}
|
||||||
|
struct Defined {
|
||||||
|
int defined;
|
||||||
|
};
|
||||||
|
void bumpf(int i) {}
|
||||||
|
%}
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%define ANOTHER_MACRO(TYPE)
|
||||||
|
|
||||||
|
#if defined(AAA) && defined(BBB) && defined(CCC)
|
||||||
|
void thing(TYPE) {}
|
||||||
|
#else
|
||||||
|
void thing_not(TYPE) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(AAA) &&\
|
||||||
|
defined(BBB) \\
|
||||||
|
&& defined(CCC)
|
||||||
|
void stuff(TYPE) {}
|
||||||
|
#else
|
||||||
|
void stuff_not(TYPE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(0)
|
||||||
|
void defined_not(TYPE);
|
||||||
|
#elif defined(AAA) && defined( BBB ) && defined(CCC)
|
||||||
|
struct Defined {
|
||||||
|
int defined;
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
void defined_not(TYPE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !( defined(AAA) \
|
||||||
|
defined(BBB) \\
|
||||||
|
&& defined(CCC) )
|
||||||
|
void bumpf_not(TYPE);
|
||||||
|
#else
|
||||||
|
void bumpf(TYPE) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%enddef
|
||||||
|
|
||||||
|
ANOTHER_MACRO(int)
|
||||||
|
|
||||||
|
%{
|
||||||
|
void another_macro_checking(void) {
|
||||||
|
struct Defined d;
|
||||||
|
d.defined = 10;
|
||||||
|
thing(10);
|
||||||
|
stuff(10);
|
||||||
|
bumpf(10);
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,10 @@ import preproc_defined
|
||||||
|
|
||||||
if preproc_defined.call_checking() != 1:
|
if preproc_defined.call_checking() != 1:
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
|
|
||||||
|
d = preproc_defined.Defined()
|
||||||
|
d.defined = 10
|
||||||
|
|
||||||
|
preproc_defined.thing(10)
|
||||||
|
preproc_defined.stuff(10)
|
||||||
|
preproc_defined.bumpf(10)
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ static Hash *included_files = 0;
|
||||||
static List *dependencies = 0;
|
static List *dependencies = 0;
|
||||||
static Scanner *id_scan = 0;
|
static Scanner *id_scan = 0;
|
||||||
static int error_as_warning = 0; /* Understand the cpp #error directive as a special #warning */
|
static int error_as_warning = 0; /* Understand the cpp #error directive as a special #warning */
|
||||||
static int defined_operator_accepted = 0;
|
static int expand_defined_operator = 0;
|
||||||
static int macro_level = 0;
|
static int macro_level = 0;
|
||||||
static int macro_start_line = 0;
|
static int macro_start_line = 0;
|
||||||
static const String * macro_start_file = 0;
|
static const String * macro_start_file = 0;
|
||||||
|
|
@ -152,6 +152,9 @@ static String *kpp_dextern = 0;
|
||||||
static String *kpp_LINE = 0;
|
static String *kpp_LINE = 0;
|
||||||
static String *kpp_FILE = 0;
|
static String *kpp_FILE = 0;
|
||||||
|
|
||||||
|
static String *kpp_hash_if = 0;
|
||||||
|
static String *kpp_hash_elif = 0;
|
||||||
|
|
||||||
void Preprocessor_init(void) {
|
void Preprocessor_init(void) {
|
||||||
Hash *s;
|
Hash *s;
|
||||||
|
|
||||||
|
|
@ -188,6 +191,9 @@ void Preprocessor_init(void) {
|
||||||
kpp_LINE = NewString("__LINE__");
|
kpp_LINE = NewString("__LINE__");
|
||||||
kpp_FILE = NewString("__FILE__");
|
kpp_FILE = NewString("__FILE__");
|
||||||
|
|
||||||
|
kpp_hash_if = NewString("#if");
|
||||||
|
kpp_hash_elif = NewString("#elif");
|
||||||
|
|
||||||
cpp = NewHash();
|
cpp = NewHash();
|
||||||
s = NewHash();
|
s = NewHash();
|
||||||
Setattr(cpp, kpp_symbols, s);
|
Setattr(cpp, kpp_symbols, s);
|
||||||
|
|
@ -229,9 +235,12 @@ void Preprocessor_delete(void) {
|
||||||
Delete(kpp_ddefine);
|
Delete(kpp_ddefine);
|
||||||
Delete(kpp_dline);
|
Delete(kpp_dline);
|
||||||
|
|
||||||
|
|
||||||
Delete(kpp_LINE);
|
Delete(kpp_LINE);
|
||||||
Delete(kpp_FILE);
|
Delete(kpp_FILE);
|
||||||
|
|
||||||
|
Delete(kpp_hash_if);
|
||||||
|
Delete(kpp_hash_elif);
|
||||||
|
|
||||||
Delete(cpp);
|
Delete(cpp);
|
||||||
Delete(included_files);
|
Delete(included_files);
|
||||||
Preprocessor_expr_delete();
|
Preprocessor_expr_delete();
|
||||||
|
|
@ -946,22 +955,6 @@ static String *expand_macro(String *name, List *args, String *line_file) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
|
||||||
* evaluate_args()
|
|
||||||
*
|
|
||||||
* Evaluate the arguments of a macro
|
|
||||||
* ----------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
List *evaluate_args(List *x) {
|
|
||||||
Iterator i;
|
|
||||||
List *nl = NewList();
|
|
||||||
|
|
||||||
for (i = First(x); i.item; i = Next(i)) {
|
|
||||||
Append(nl, Preprocessor_replace(i.item));
|
|
||||||
}
|
|
||||||
return nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* DOH *Preprocessor_replace(DOH *s)
|
* DOH *Preprocessor_replace(DOH *s)
|
||||||
*
|
*
|
||||||
|
|
@ -976,7 +969,6 @@ List *evaluate_args(List *x) {
|
||||||
static DOH *Preprocessor_replace(DOH *s) {
|
static DOH *Preprocessor_replace(DOH *s) {
|
||||||
DOH *ns, *symbols, *m;
|
DOH *ns, *symbols, *m;
|
||||||
int c, i, state = 0;
|
int c, i, state = 0;
|
||||||
|
|
||||||
String *id = NewStringEmpty();
|
String *id = NewStringEmpty();
|
||||||
|
|
||||||
assert(cpp);
|
assert(cpp);
|
||||||
|
|
@ -990,10 +982,18 @@ static DOH *Preprocessor_replace(DOH *s) {
|
||||||
while ((c = Getc(s)) != EOF) {
|
while ((c = Getc(s)) != EOF) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 0:
|
case 0:
|
||||||
if (isidentifier(c) || (c == '%')) {
|
if (isidentifier(c)) {
|
||||||
Clear(id);
|
Clear(id);
|
||||||
Putc(c, id);
|
Putc(c, id);
|
||||||
state = 1;
|
state = 4;
|
||||||
|
} else if (c == '%') {
|
||||||
|
Clear(id);
|
||||||
|
Putc(c, id);
|
||||||
|
state = 2;
|
||||||
|
} else if (c == '#') {
|
||||||
|
Clear(id);
|
||||||
|
Putc(c, id);
|
||||||
|
state = 4;
|
||||||
} else if (c == '\"') {
|
} else if (c == '\"') {
|
||||||
Putc(c, ns);
|
Putc(c, ns);
|
||||||
skip_tochar(s, '\"', ns);
|
skip_tochar(s, '\"', ns);
|
||||||
|
|
@ -1003,62 +1003,87 @@ static DOH *Preprocessor_replace(DOH *s) {
|
||||||
} else if (c == '/') {
|
} else if (c == '/') {
|
||||||
Putc(c, ns);
|
Putc(c, ns);
|
||||||
state = 10;
|
state = 10;
|
||||||
|
} else if (c == '\\') {
|
||||||
|
Putc(c, ns);
|
||||||
|
c = Getc(s);
|
||||||
|
if (c == '\n') {
|
||||||
|
Putc(c, ns);
|
||||||
|
} else {
|
||||||
|
Ungetc(c, s);
|
||||||
|
}
|
||||||
|
} else if (c == '\n') {
|
||||||
|
Putc(c, ns);
|
||||||
|
expand_defined_operator = 0;
|
||||||
} else {
|
} else {
|
||||||
Putc(c, ns);
|
Putc(c, ns);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: /* An identifier */
|
case 2:
|
||||||
|
/* Found '%#' */
|
||||||
|
if (c == '#') {
|
||||||
|
Putc(c, id);
|
||||||
|
state = 4;
|
||||||
|
} else {
|
||||||
|
Ungetc(c, s);
|
||||||
|
state = 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4: /* An identifier */
|
||||||
if (isidchar(c)) {
|
if (isidchar(c)) {
|
||||||
Putc(c, id);
|
Putc(c, id);
|
||||||
state = 1;
|
state = 4;
|
||||||
} else {
|
} else {
|
||||||
/* We found the end of a valid identifier */
|
/* We found the end of a valid identifier */
|
||||||
Ungetc(c, s);
|
Ungetc(c, s);
|
||||||
/* See if this is the special "defined" operator */
|
/* See if this is the special "defined" operator */
|
||||||
if (Equal(kpp_defined, id) && defined_operator_accepted) {
|
if (Equal(kpp_defined, id)) {
|
||||||
int lenargs = 0;
|
if (expand_defined_operator) {
|
||||||
DOH *args = 0;
|
int lenargs = 0;
|
||||||
/* See whether or not a parenthesis has been used */
|
DOH *args = 0;
|
||||||
skip_whitespace(s, 0);
|
/* See whether or not a parenthesis has been used */
|
||||||
c = Getc(s);
|
skip_whitespace(s, 0);
|
||||||
if (c == '(') {
|
c = Getc(s);
|
||||||
Ungetc(c, s);
|
if (c == '(') {
|
||||||
args = find_args(s, 0, kpp_defined);
|
Ungetc(c, s);
|
||||||
} else if (isidchar(c)) {
|
args = find_args(s, 0, kpp_defined);
|
||||||
DOH *arg = NewStringEmpty();
|
} else if (isidchar(c)) {
|
||||||
args = NewList();
|
DOH *arg = NewStringEmpty();
|
||||||
Putc(c, arg);
|
args = NewList();
|
||||||
while (((c = Getc(s)) != EOF)) {
|
|
||||||
if (!isidchar(c)) {
|
|
||||||
Ungetc(c, s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Putc(c, arg);
|
Putc(c, arg);
|
||||||
|
while (((c = Getc(s)) != EOF)) {
|
||||||
|
if (!isidchar(c)) {
|
||||||
|
Ungetc(c, s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Putc(c, arg);
|
||||||
|
}
|
||||||
|
if (Len(arg))
|
||||||
|
Append(args, arg);
|
||||||
|
Delete(arg);
|
||||||
|
} else {
|
||||||
|
Seek(s, -1, SEEK_CUR);
|
||||||
}
|
}
|
||||||
if (Len(arg))
|
lenargs = Len(args);
|
||||||
Append(args, arg);
|
if ((!args) || (!lenargs)) {
|
||||||
Delete(arg);
|
/* This is not a defined() operator. */
|
||||||
} else {
|
Append(ns, id);
|
||||||
Seek(s, -1, SEEK_CUR);
|
state = 0;
|
||||||
}
|
|
||||||
lenargs = Len(args);
|
|
||||||
if ((!args) || (!lenargs)) {
|
|
||||||
/* This is not a defined() operator. */
|
|
||||||
Append(ns, id);
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (i = 0; i < lenargs; i++) {
|
|
||||||
DOH *o = Getitem(args, i);
|
|
||||||
if (!Getattr(symbols, o)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < lenargs; i++) {
|
||||||
|
DOH *o = Getitem(args, i);
|
||||||
|
if (!Getattr(symbols, o)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i < lenargs)
|
||||||
|
Putc('0', ns);
|
||||||
|
else
|
||||||
|
Putc('1', ns);
|
||||||
|
Delete(args);
|
||||||
|
} else {
|
||||||
|
Append(ns, id);
|
||||||
}
|
}
|
||||||
if (i < lenargs)
|
|
||||||
Putc('0', ns);
|
|
||||||
else
|
|
||||||
Putc('1', ns);
|
|
||||||
Delete(args);
|
|
||||||
state = 0;
|
state = 0;
|
||||||
break;
|
break;
|
||||||
} else if (Equal(kpp_LINE, id)) {
|
} else if (Equal(kpp_LINE, id)) {
|
||||||
|
|
@ -1072,6 +1097,9 @@ static DOH *Preprocessor_replace(DOH *s) {
|
||||||
Delete(fn);
|
Delete(fn);
|
||||||
state = 0;
|
state = 0;
|
||||||
break;
|
break;
|
||||||
|
} else if (Equal(kpp_hash_if, id) || Equal(kpp_hash_elif, id)) {
|
||||||
|
expand_defined_operator = 1;
|
||||||
|
Append(ns, id);
|
||||||
} else if ((m = Getattr(symbols, id))) {
|
} else if ((m = Getattr(symbols, id))) {
|
||||||
/* See if the macro is defined in the preprocessor symbol table */
|
/* See if the macro is defined in the preprocessor symbol table */
|
||||||
DOH *args = 0;
|
DOH *args = 0;
|
||||||
|
|
@ -1119,11 +1147,15 @@ static DOH *Preprocessor_replace(DOH *s) {
|
||||||
Putc(c, ns);
|
Putc(c, ns);
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
|
/* in C++ comment */
|
||||||
Putc(c, ns);
|
Putc(c, ns);
|
||||||
if (c == '\n')
|
if (c == '\n') {
|
||||||
|
expand_defined_operator = 0;
|
||||||
state = 0;
|
state = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
|
/* in C comment */
|
||||||
Putc(c, ns);
|
Putc(c, ns);
|
||||||
if (c == '*')
|
if (c == '*')
|
||||||
state = 13;
|
state = 13;
|
||||||
|
|
@ -1142,8 +1174,8 @@ static DOH *Preprocessor_replace(DOH *s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Identifier at the end */
|
/* Identifier at the end */
|
||||||
if (state == 1) {
|
if (state == 2 || state == 4) {
|
||||||
/* See if this is the special "defined" macro */
|
/* See if this is the special "defined" operator */
|
||||||
if (Equal(kpp_defined, id)) {
|
if (Equal(kpp_defined, id)) {
|
||||||
Swig_error(Getfile(s), Getline(s), "No arguments given to defined()\n");
|
Swig_error(Getfile(s), Getline(s), "No arguments given to defined()\n");
|
||||||
} else if (Equal(kpp_LINE, id)) {
|
} else if (Equal(kpp_LINE, id)) {
|
||||||
|
|
@ -1556,7 +1588,7 @@ String *Preprocessor_parse(String *s) {
|
||||||
if (allow) {
|
if (allow) {
|
||||||
int val;
|
int val;
|
||||||
String *sval;
|
String *sval;
|
||||||
defined_operator_accepted = 1;
|
expand_defined_operator = 1;
|
||||||
sval = Preprocessor_replace(value);
|
sval = Preprocessor_replace(value);
|
||||||
start_level = level;
|
start_level = level;
|
||||||
Seek(sval, 0, SEEK_SET);
|
Seek(sval, 0, SEEK_SET);
|
||||||
|
|
@ -1573,7 +1605,7 @@ String *Preprocessor_parse(String *s) {
|
||||||
if (val == 0)
|
if (val == 0)
|
||||||
allow = 0;
|
allow = 0;
|
||||||
}
|
}
|
||||||
defined_operator_accepted = 0;
|
expand_defined_operator = 0;
|
||||||
mask = 1;
|
mask = 1;
|
||||||
}
|
}
|
||||||
} else if (Equal(id, kpp_elif)) {
|
} else if (Equal(id, kpp_elif)) {
|
||||||
|
|
@ -1581,7 +1613,7 @@ String *Preprocessor_parse(String *s) {
|
||||||
Swig_error(Getfile(s), Getline(id), "Misplaced #elif.\n");
|
Swig_error(Getfile(s), Getline(id), "Misplaced #elif.\n");
|
||||||
} else {
|
} else {
|
||||||
cond_lines[level - 1] = Getline(id);
|
cond_lines[level - 1] = Getline(id);
|
||||||
defined_operator_accepted = 1;
|
expand_defined_operator = 1;
|
||||||
if (allow) {
|
if (allow) {
|
||||||
allow = 0;
|
allow = 0;
|
||||||
mask = 0;
|
mask = 0;
|
||||||
|
|
@ -1604,7 +1636,7 @@ String *Preprocessor_parse(String *s) {
|
||||||
allow = 0;
|
allow = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defined_operator_accepted = 0;
|
expand_defined_operator = 0;
|
||||||
}
|
}
|
||||||
} else if (Equal(id, kpp_warning)) {
|
} else if (Equal(id, kpp_warning)) {
|
||||||
if (allow) {
|
if (allow) {
|
||||||
|
|
@ -1884,6 +1916,7 @@ String *Preprocessor_parse(String *s) {
|
||||||
if ((state >= 30) && (state < 40)) {
|
if ((state >= 30) && (state < 40)) {
|
||||||
Swig_error(Getfile(s), -1, "Unterminated comment starting on line %d\n", start_line);
|
Swig_error(Getfile(s), -1, "Unterminated comment starting on line %d\n", start_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_location(s, chunk);
|
copy_location(s, chunk);
|
||||||
add_chunk(ns, chunk, allow);
|
add_chunk(ns, chunk, allow);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue