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:
William S Fulton 2011-02-12 23:27:50 +00:00
commit 16ba0aca53
4 changed files with 182 additions and 70 deletions

View file

@ -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.

View file

@ -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);
}
%}

View file

@ -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)

View file

@ -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);