diff --git a/CHANGES.current b/CHANGES.current index e4022a642..aaaf2254b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,9 +5,13 @@ See the RELEASENOTES file for a summary of changes in each release. Version 2.0.1 (in progress) =========================== +2010-08-26: wsfulton + Fix __LINE__ and __FILE__ expansion reported by Camille Gillot. Mostly this + did not work at all. + 2010-08-17: wsfulton [Perl] Fix corner case marshalling of doubles - errno was not being correctly - set before calling strtod - patch from Justin Vallon. + set before calling strtod - patch from Justin Vallon - SF Bug #3038936. 2010-08-17: wsfulton Fix make distclean when some of the more obscure languages are detected by diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index af9316656..e385b11dd 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -486,6 +486,7 @@ C_TEST_CASES += \ overload_extendc \ preproc \ preproc_constants_c \ + preproc_line_file \ ret_by_value \ simple_array \ sizeof_pointer \ diff --git a/Examples/test-suite/java/preproc_line_file_runme.java b/Examples/test-suite/java/preproc_line_file_runme.java new file mode 100644 index 000000000..6550e4a78 --- /dev/null +++ b/Examples/test-suite/java/preproc_line_file_runme.java @@ -0,0 +1,41 @@ +import preproc_line_file.*; + +public class preproc_line_file_runme { + + static { + try { + System.loadLibrary("preproc_line_file"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) throws Throwable + { + int myline = preproc_line_file.MYLINE; + int myline_adjusted = preproc_line_file.MYLINE_ADJUSTED; + if (myline != 4) + throw new RuntimeException("preproc failure"); + if (myline + 100 + 1 != myline_adjusted) + throw new RuntimeException("preproc failure"); + + String myfile = preproc_line_file.MYFILE; + String myfile_adjusted = preproc_line_file.MYFILE_ADJUSTED; + if (!(myfile.equals("../../../../Examples/test-suite/preproc_line_file.i") || myfile.equals("..\\..\\..\\..\\Examples\\test-suite\\preproc_line_file.i"))) + throw new RuntimeException("preproc failure"); + + if (!(myfile_adjusted.equals("../../../../Examples/test-suite/preproc_line_file.i.bak") || myfile_adjusted.equals("..\\..\\..\\..\\Examples\\test-suite\\preproc_line_file.i.bak"))) + throw new RuntimeException("preproc failure"); + + if (!preproc_line_file.MY_STRINGNUM_A.equals("my15")) + throw new RuntimeException("preproc failed MY_STRINGNUM_A"); + + if (!preproc_line_file.MY_STRINGNUM_B.equals("my16")) + throw new RuntimeException("preproc failed MY_STRINGNUM_B"); + + int myline2 = preproc_line_file.MYLINE2; + if (myline2 != 23) + throw new RuntimeException("preproc failure"); + } +} diff --git a/Examples/test-suite/preproc_line_file.i b/Examples/test-suite/preproc_line_file.i new file mode 100644 index 000000000..11465e0d0 --- /dev/null +++ b/Examples/test-suite/preproc_line_file.i @@ -0,0 +1,33 @@ +%module preproc_line_file +%javaconst(1); +// Test __LINE__ and __FILE__ (don't change line numbers in here else runtime tests will need modifying) +#define MYLINE __LINE__ +#define MYLINE_ADJUSTED __LINE__ + 100 + +#define MYFILE __FILE__ +#define MYFILE_ADJUSTED __FILE__ ".bak" + + +#define STRINGNUM_HELP(a,b) #a#b +#define STRINGNUM(a,b) STRINGNUM_HELP(a,b) +#define STRINGNUM_UNIQUE(a) STRINGNUM(a,__LINE__) + +#define MY_STRINGNUM_A STRINGNUM_UNIQUE(my) +#define MY_STRINGNUM_B STRINGNUM_UNIQUE(my) + + +#define NUMBER_HELP(a,b) a##b +#define NUMBER(a,b) NUMBER_HELP(a,b) +#define NUMBER_UNIQUE(a) NUMBER(a,__LINE__) + +#define MYLINE2 __LINE__ + +/* +TODO: __LINE__ is wrong +struct Struct { + static const int line_num = __LINE__; +}; +const int NUMBER_UNIQUE(thing) = 0; +const int NUMBER_UNIQUE(thingamebob) = 0; +#define MYLINE3 __LINE__ +*/ diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c index 5dd320994..63e6ab547 100644 --- a/Source/Preprocessor/cpp.c +++ b/Source/Preprocessor/cpp.c @@ -33,6 +33,9 @@ static Hash *included_files = 0; static List *dependencies = 0; static Scanner *id_scan = 0; static int error_as_warning = 0; /* Understand the cpp #error directive as a special #warning */ +static int macro_level = 0; +static int macro_start_line = 0; +static const String * macro_start_file = 0; /* Test a character to see if it starts an identifier */ #define isidentifier(c) ((isalpha(c)) || (c == '_') || (c == '$')) @@ -40,7 +43,7 @@ static int error_as_warning = 0; /* Understand the cpp #error directive as a spe /* Test a character to see if it valid in an identifier (after the first letter) */ #define isidchar(c) ((isalnum(c)) || (c == '_') || (c == '$')) -DOH *Preprocessor_replace(DOH *); +static DOH *Preprocessor_replace(DOH *); /* Skip whitespace */ static void skip_whitespace(String *s, String *out) { @@ -499,6 +502,10 @@ Hash *Preprocessor_define(const_String_or_char_ptr _str, int swigmacro) { Setattr(macro, kpp_varargs, "1"); } } + Setline(macrovalue, line); + Setfile(macrovalue, file); + Setline(macroname, line); + Setfile(macroname, file); Setattr(macro, kpp_value, macrovalue); Setline(macro, line); Setfile(macro, file); @@ -710,6 +717,14 @@ static String *expand_macro(String *name, List *args) { macro = Getattr(symbols, name); if (!macro) return 0; + + if (macro_level == 0) { + /* Store the start of the macro should the macro contain __LINE__ and __FILE__ for expansion */ + macro_start_line = Getline(args); + macro_start_file = Getfile(args); + } + macro_level++; + if (Getattr(macro, kpp_expanded)) { ns = NewStringEmpty(); Append(ns, name); @@ -725,6 +740,7 @@ static String *expand_macro(String *name, List *args) { if (i) Putc(')', ns); } + macro_level--; return ns; } @@ -764,11 +780,13 @@ static String *expand_macro(String *name, List *args) { Swig_error(Getfile(args), Getline(args), "Macro '%s' expects 1 argument\n", name); else Swig_error(Getfile(args), Getline(args), "Macro '%s' expects no arguments\n", name); + macro_level--; return 0; } /* If the macro expects arguments, but none were supplied, we leave it in place */ if (!args && (margs) && Len(margs) > 0) { + macro_level--; return NewString(name); } @@ -922,6 +940,7 @@ static String *expand_macro(String *name, List *args) { Delete(e); e = f; } + macro_level--; Delete(temp); Delete(tempa); return e; @@ -954,7 +973,7 @@ List *evaluate_args(List *x) { /* #define SWIG_PUT_BUFF */ -DOH *Preprocessor_replace(DOH *s) { +static DOH *Preprocessor_replace(DOH *s) { DOH *ns, *symbols, *m; int c, i, state = 0; @@ -999,7 +1018,7 @@ DOH *Preprocessor_replace(DOH *s) { if (Equal(kpp_defined, id)) { int lenargs = 0; DOH *args = 0; - /* See whether or not a paranthesis has been used */ + /* See whether or not a parenthesis has been used */ skip_whitespace(s, 0); c = Getc(s); if (c == '(') { @@ -1042,22 +1061,19 @@ DOH *Preprocessor_replace(DOH *s) { Delete(args); state = 0; break; - } - if (Equal(kpp_LINE, id)) { - Printf(ns, "%d", Getline(s)); + } else if (Equal(kpp_LINE, id)) { + Printf(ns, "%d", macro_level > 0 ? macro_start_line : Getline(s)); state = 0; break; - } - if (Equal(kpp_FILE, id)) { - String *fn = Copy(Getfile(s)); + } else if (Equal(kpp_FILE, id)) { + String *fn = Copy(macro_level > 0 ? macro_start_file : Getfile(s)); Replaceall(fn, "\\", "\\\\"); Printf(ns, "\"%s\"", fn); Delete(fn); state = 0; break; - } - /* See if the macro is defined in the preprocessor symbol table */ - if ((m = Getattr(symbols, id))) { + } else if ((m = Getattr(symbols, id))) { + /* See if the macro is defined in the preprocessor symbol table */ DOH *args = 0; DOH *e; /* See if the macro expects arguments */ @@ -1123,6 +1139,13 @@ DOH *Preprocessor_replace(DOH *s) { /* See if this is the special "defined" macro */ if (Equal(kpp_defined, id)) { Swig_error(Getfile(s), Getline(s), "No arguments given to defined()\n"); + } else if (Equal(kpp_LINE, id)) { + Printf(ns, "%d", macro_level > 0 ? macro_start_line : Getline(s)); + } else if (Equal(kpp_FILE, id)) { + String *fn = Copy(macro_level > 0 ? macro_start_file : Getfile(s)); + Replaceall(fn, "\\", "\\\\"); + Printf(ns, "\"%s\"", fn); + Delete(fn); } else if ((m = Getattr(symbols, id))) { DOH *e; /* Yes. There is a macro here */ @@ -1457,6 +1480,7 @@ String *Preprocessor_parse(String *s) { m = Preprocessor_define(value, 0); if ((m) && !(Getattr(m, kpp_args))) { v = Copy(Getattr(m, kpp_value)); + copy_location(m, v); if (Len(v)) { Swig_error_silent(1); v1 = Preprocessor_replace(v);