From 7c6aca2ebc2c55cb9c7e25d8201e5b4bdb0907b2 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 2 Sep 2009 22:33:04 +0000 Subject: [PATCH] true and false supported in constant expressions (C++ only). && || == != < > <= >= operators now return type bool (C++ only) and type int for C as per C/C++ standards. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@11677 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- CHANGES.current | 17 ++++ Examples/test-suite/common.mk | 2 + .../csharp/preproc_constants_c_runme.cs | 68 +++++++++++++++ .../csharp/preproc_constants_runme.cs | 67 +++++++++++++++ Examples/test-suite/preproc_constants.i | 82 +++++++++++++++++++ Examples/test-suite/preproc_constants_c.i | 6 ++ Source/CParse/cscanner.c | 8 +- Source/CParse/parser.y | 19 +++-- Source/Swig/scanner.c | 21 +++-- Source/Swig/swigscan.h | 1 + 10 files changed, 276 insertions(+), 15 deletions(-) create mode 100644 Examples/test-suite/csharp/preproc_constants_c_runme.cs create mode 100644 Examples/test-suite/csharp/preproc_constants_runme.cs create mode 100644 Examples/test-suite/preproc_constants.i create mode 100644 Examples/test-suite/preproc_constants_c.i diff --git a/CHANGES.current b/CHANGES.current index 8414f06c9..26f1434e1 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,5 +1,22 @@ Version 1.3.41 (in progress) ============================ +2009-09-02: wsfulton + The following operators in constant expressions now result in type bool for C++ + wrappers and remain as type int for C wrappers, as per each standard: + + && || == != < > <= >= (Actually the last 4 are still broken). For example: + + #define A 10 + #define B 10 + #define A_EQ_B A == B // now wrapped as type bool for C++ + #define A_AND_B A && B // now wrapped as type bool for C++ + +2009-09-02: wsfulton + Fix #2845746. true and false are now recognised keywords (only when wrapping C++). + Constants such as the following are now wrapped (as type bool): + #define FOO true + #define BAR FOO && false + 2009-08-29: olly [Perl] Remove bogus assertion (patch from David Fletcher). diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index f98067c5d..4bbf74525 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -257,6 +257,7 @@ CPP_TEST_CASES += \ overload_template \ overload_template_fast \ pointer_reference \ + preproc_constants \ primitive_ref \ private_assign \ protected_rename \ @@ -456,6 +457,7 @@ C_TEST_CASES += \ overload_extend \ overload_extendc \ preproc \ + preproc_constants_c \ ret_by_value \ simple_array \ sizeof_pointer \ diff --git a/Examples/test-suite/csharp/preproc_constants_c_runme.cs b/Examples/test-suite/csharp/preproc_constants_c_runme.cs new file mode 100644 index 000000000..71cf697f7 --- /dev/null +++ b/Examples/test-suite/csharp/preproc_constants_c_runme.cs @@ -0,0 +1,68 @@ +using System; +using System.Reflection; +using preproc_constants_cNamespace; + +// Same as preproc_constants_c.i testcase, but bool types are int instead +public class runme { + static void Main() { + assert( typeof(int) == preproc_constants_c.CONST_INT1.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_INT2.GetType() ); + assert( typeof(uint) == preproc_constants_c.CONST_UINT1.GetType() ); + assert( typeof(uint) == preproc_constants_c.CONST_UINT2.GetType() ); + assert( typeof(uint) == preproc_constants_c.CONST_UINT3.GetType() ); + assert( typeof(uint) == preproc_constants_c.CONST_UINT4.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_LONG1.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_LONG2.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_LONG3.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_LONG4.GetType() ); + assert( typeof(long) == preproc_constants_c.CONST_LLONG1.GetType() ); + assert( typeof(long) == preproc_constants_c.CONST_LLONG2.GetType() ); + assert( typeof(long) == preproc_constants_c.CONST_LLONG3.GetType() ); + assert( typeof(long) == preproc_constants_c.CONST_LLONG4.GetType() ); + assert( typeof(ulong) == preproc_constants_c.CONST_ULLONG1.GetType() ); + assert( typeof(ulong) == preproc_constants_c.CONST_ULLONG2.GetType() ); + assert( typeof(ulong) == preproc_constants_c.CONST_ULLONG3.GetType() ); + assert( typeof(ulong) == preproc_constants_c.CONST_ULLONG4.GetType() ); + assert( typeof(double) == preproc_constants_c.CONST_DOUBLE1.GetType() ); + assert( typeof(double) == preproc_constants_c.CONST_DOUBLE2.GetType() ); + assert( typeof(double) == preproc_constants_c.CONST_DOUBLE3.GetType() ); + assert( typeof(double) == preproc_constants_c.CONST_DOUBLE4.GetType() ); + assert( typeof(double) == preproc_constants_c.CONST_DOUBLE5.GetType() ); + assert( typeof(double) == preproc_constants_c.CONST_DOUBLE6.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_BOOL1.GetType() ); + assert( typeof(int) == preproc_constants_c.CONST_BOOL2.GetType() ); + assert( typeof(char) == preproc_constants_c.CONST_CHAR.GetType() ); + assert( typeof(string) == preproc_constants_c.CONST_STRING1.GetType() ); + assert( typeof(string) == preproc_constants_c.CONST_STRING2.GetType() ); + + assert( typeof(int) == preproc_constants_c.INT_AND_BOOL.GetType() ); +// assert( typeof(int) == preproc_constants_c.INT_AND_CHAR.GetType() ); + assert( typeof(int) == preproc_constants_c.INT_AND_INT.GetType() ); + assert( typeof(uint) == preproc_constants_c.INT_AND_UINT.GetType() ); + assert( typeof(int) == preproc_constants_c.INT_AND_LONG.GetType() ); + assert( typeof(uint) == preproc_constants_c.INT_AND_ULONG.GetType() ); + assert( typeof(long) == preproc_constants_c.INT_AND_LLONG.GetType() ); + assert( typeof(ulong) == preproc_constants_c.INT_AND_ULLONG.GetType() ); + assert( typeof(int ) == preproc_constants_c.BOOL_AND_BOOL.GetType() ); + + assert( typeof(int) == preproc_constants_c.EXPR_MULTIPLY.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_DIVIDE.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_PLUS.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_MINUS.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_LSHIFT.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_RSHIFT.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_INEQUALITY.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_EQUALITY.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_AND.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_XOR.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_OR.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_LAND.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_LOR.GetType() ); + assert( typeof(double) == preproc_constants_c.EXPR_CONDITIONAL.GetType() ); + + } + static void assert(bool assertion) { + if (!assertion) + throw new ApplicationException("test failed"); + } +} diff --git a/Examples/test-suite/csharp/preproc_constants_runme.cs b/Examples/test-suite/csharp/preproc_constants_runme.cs new file mode 100644 index 000000000..b2c6c62ae --- /dev/null +++ b/Examples/test-suite/csharp/preproc_constants_runme.cs @@ -0,0 +1,67 @@ +using System; +using System.Reflection; +using preproc_constantsNamespace; + +public class runme { + static void Main() { + assert( typeof(int) == preproc_constants.CONST_INT1.GetType() ); + assert( typeof(int) == preproc_constants.CONST_INT2.GetType() ); + assert( typeof(uint) == preproc_constants.CONST_UINT1.GetType() ); + assert( typeof(uint) == preproc_constants.CONST_UINT2.GetType() ); + assert( typeof(uint) == preproc_constants.CONST_UINT3.GetType() ); + assert( typeof(uint) == preproc_constants.CONST_UINT4.GetType() ); + assert( typeof(int) == preproc_constants.CONST_LONG1.GetType() ); + assert( typeof(int) == preproc_constants.CONST_LONG2.GetType() ); + assert( typeof(int) == preproc_constants.CONST_LONG3.GetType() ); + assert( typeof(int) == preproc_constants.CONST_LONG4.GetType() ); + assert( typeof(long) == preproc_constants.CONST_LLONG1.GetType() ); + assert( typeof(long) == preproc_constants.CONST_LLONG2.GetType() ); + assert( typeof(long) == preproc_constants.CONST_LLONG3.GetType() ); + assert( typeof(long) == preproc_constants.CONST_LLONG4.GetType() ); + assert( typeof(ulong) == preproc_constants.CONST_ULLONG1.GetType() ); + assert( typeof(ulong) == preproc_constants.CONST_ULLONG2.GetType() ); + assert( typeof(ulong) == preproc_constants.CONST_ULLONG3.GetType() ); + assert( typeof(ulong) == preproc_constants.CONST_ULLONG4.GetType() ); + assert( typeof(double) == preproc_constants.CONST_DOUBLE1.GetType() ); + assert( typeof(double) == preproc_constants.CONST_DOUBLE2.GetType() ); + assert( typeof(double) == preproc_constants.CONST_DOUBLE3.GetType() ); + assert( typeof(double) == preproc_constants.CONST_DOUBLE4.GetType() ); + assert( typeof(double) == preproc_constants.CONST_DOUBLE5.GetType() ); + assert( typeof(double) == preproc_constants.CONST_DOUBLE6.GetType() ); + assert( typeof(bool) == preproc_constants.CONST_BOOL1.GetType() ); + assert( typeof(bool) == preproc_constants.CONST_BOOL2.GetType() ); + assert( typeof(char) == preproc_constants.CONST_CHAR.GetType() ); + assert( typeof(string) == preproc_constants.CONST_STRING1.GetType() ); + assert( typeof(string) == preproc_constants.CONST_STRING2.GetType() ); + + assert( typeof(int) == preproc_constants.INT_AND_BOOL.GetType() ); +// assert( typeof(int) == preproc_constants.INT_AND_CHAR.GetType() ); + assert( typeof(int) == preproc_constants.INT_AND_INT.GetType() ); + assert( typeof(uint) == preproc_constants.INT_AND_UINT.GetType() ); + assert( typeof(int) == preproc_constants.INT_AND_LONG.GetType() ); + assert( typeof(uint) == preproc_constants.INT_AND_ULONG.GetType() ); + assert( typeof(long) == preproc_constants.INT_AND_LLONG.GetType() ); + assert( typeof(ulong) == preproc_constants.INT_AND_ULLONG.GetType() ); + assert( typeof(int ) == preproc_constants.BOOL_AND_BOOL.GetType() ); + + assert( typeof(int) == preproc_constants.EXPR_MULTIPLY.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_DIVIDE.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_PLUS.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_MINUS.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_LSHIFT.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_RSHIFT.GetType() ); + assert( typeof(bool) == preproc_constants.EXPR_INEQUALITY.GetType() ); + assert( typeof(bool) == preproc_constants.EXPR_EQUALITY.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_AND.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_XOR.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_OR.GetType() ); + assert( typeof(bool) == preproc_constants.EXPR_LAND.GetType() ); + assert( typeof(bool) == preproc_constants.EXPR_LOR.GetType() ); + assert( typeof(double) == preproc_constants.EXPR_CONDITIONAL.GetType() ); + + } + static void assert(bool assertion) { + if (!assertion) + throw new ApplicationException("test failed"); + } +} diff --git a/Examples/test-suite/preproc_constants.i b/Examples/test-suite/preproc_constants.i new file mode 100644 index 000000000..b759d8a75 --- /dev/null +++ b/Examples/test-suite/preproc_constants.i @@ -0,0 +1,82 @@ +%module preproc_constants + +// Note: C types are slightly different to C++ types as (a && b) is int in C and bool in C++ + +// Simple constants +#define CONST_INT1 10 +#define CONST_INT2 0xFF + +#define CONST_UINT1 10u +#define CONST_UINT2 10U +#define CONST_UINT3 0xFFu +#define CONST_UINT4 0xFFU + +#define CONST_LONG1 10l +#define CONST_LONG2 10L +#define CONST_LONG3 0xFFl +#define CONST_LONG4 0xFFL + +#define CONST_LLONG1 10LL +#define CONST_LLONG2 10ll +#define CONST_LLONG3 0xFFll +#define CONST_LLONG4 0xFFLL + +#define CONST_ULLONG1 10ull +#define CONST_ULLONG2 10ULL +#define CONST_ULLONG3 0xFFull +#define CONST_ULLONG4 0xFFULL + +#define CONST_DOUBLE1 10e1 +#define CONST_DOUBLE2 10E1 +#define CONST_DOUBLE3 12.3 +#define CONST_DOUBLE4 12. +#define CONST_DOUBLE5 12.3f +#define CONST_DOUBLE6 12.3F + +#define CONST_BOOL1 true +#define CONST_BOOL2 false + +#define CONST_CHAR 'x' +#define CONST_STRING1 "const string" +#define CONST_STRING2 "const" " string" + +// Expressions - runtime tests check the type for any necessary type promotions of the expressions + +#define INT_AND_BOOL 0xFF & true +//#define INT_AND_CHAR 0xFF & 'A' /* FIXME compile error */ +#define INT_AND_INT 0xFF & 2 +#define INT_AND_UINT 0xFF & 2u +#define INT_AND_LONG 0xFF & 2l +#define INT_AND_ULONG 0xFF & 2ul +#define INT_AND_LLONG 0xFF & 2ll +#define INT_AND_ULLONG 0xFF & 2ull + +#define BOOL_AND_BOOL true & true // Note integral promotion to type int +//#define CHAR_AND_CHAR 'A' & 'B' // Note integral promotion to type int +/* FIXME ABOVE */ + + +#define EXPR_MULTIPLY 0xFF * 2 +#define EXPR_DIVIDE 0xFF / 2 +//FIXME #define EXPR_MOD 0xFF % 2 + +#define EXPR_PLUS 0xFF + 2 +#define EXPR_MINUS 0xFF + 2 + +#define EXPR_LSHIFT 0xFF << 2 +#define EXPR_RSHIFT 0xFF >> 2 +/* FIXME +#define EXPR_LT 0xFF < 255 +#define EXPR_GT 0xFF > 255 +#define EXPR_LTE 0xFF <= 255 +#define EXPR_LGE 0xFF >= 255 +*/ +#define EXPR_INEQUALITY 0xFF != 255 +#define EXPR_EQUALITY 0xFF == 255 +#define EXPR_AND 0xFF & 1 +#define EXPR_XOR 0xFF ^ 1 +#define EXPR_OR 0xFF | 1 +#define EXPR_LAND 0xFF && 1 +#define EXPR_LOR 0xFF || 1 +#define EXPR_CONDITIONAL true ? 2 : 2.2 + diff --git a/Examples/test-suite/preproc_constants_c.i b/Examples/test-suite/preproc_constants_c.i new file mode 100644 index 000000000..e27d1f508 --- /dev/null +++ b/Examples/test-suite/preproc_constants_c.i @@ -0,0 +1,6 @@ +%module preproc_constants_c + +%define true 1 %enddef +%define false 0 %enddef + +%include "preproc_constants.i" diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index 8734c7d0e..b5c485f5d 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -257,7 +257,7 @@ void skip_decl(void) { * Lexical scanner. * ------------------------------------------------------------------------- */ -int yylook(void) { +static int yylook(void) { int tok = 0; @@ -410,6 +410,9 @@ int yylook(void) { case SWIG_TOKEN_FLOAT: return NUM_FLOAT; + case SWIG_TOKEN_BOOL: + return NUM_BOOL; + case SWIG_TOKEN_POUND: Scanner_skip_line(scan); yylval.id = Swig_copy_string(Char(Scanner_text(scan))); @@ -525,6 +528,7 @@ int yylex(void) { case NUM_UNSIGNED: case NUM_LONGLONG: case NUM_ULONGLONG: + case NUM_BOOL: if (l == NUM_INT) yylval.dtype.type = T_INT; if (l == NUM_FLOAT) @@ -539,6 +543,8 @@ int yylex(void) { yylval.dtype.type = T_LONGLONG; if (l == NUM_ULONGLONG) yylval.dtype.type = T_ULONGLONG; + if (l == NUM_BOOL) + yylval.dtype.type = T_BOOL; yylval.dtype.val = NewString(Scanner_text(scan)); yylval.dtype.bitfield = 0; yylval.dtype.throws = 0; diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 7c33e5459..88e6a2005 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -1486,7 +1486,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) { %token STRING %token INCLUDE IMPORT INSERT %token CHARCONST -%token NUM_INT NUM_FLOAT NUM_UNSIGNED NUM_LONG NUM_ULONG NUM_LONGLONG NUM_ULONGLONG +%token NUM_INT NUM_FLOAT NUM_UNSIGNED NUM_LONG NUM_ULONG NUM_LONGLONG NUM_ULONGLONG NUM_BOOL %token TYPEDEF %token TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_WCHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_COMPLEX TYPE_TYPEDEF TYPE_RAW TYPE_NON_ISO_INT8 TYPE_NON_ISO_INT16 TYPE_NON_ISO_INT32 TYPE_NON_ISO_INT64 %token LPAREN RPAREN COMMA SEMI EXTERN INIT LBRACE RBRACE PERIOD @@ -5547,6 +5547,7 @@ exprnum : NUM_INT { $$ = $1; } | NUM_ULONG { $$ = $1; } | NUM_LONGLONG { $$ = $1; } | NUM_ULONGLONG { $$ = $1; } + | NUM_BOOL { $$ = $1; } ; exprcompound : expr PLUS expr { @@ -5591,28 +5592,28 @@ exprcompound : expr PLUS expr { } | expr LAND expr { $$.val = NewStringf("%s&&%s",$1.val,$3.val); - $$.type = T_INT; + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr LOR expr { $$.val = NewStringf("%s||%s",$1.val,$3.val); - $$.type = T_INT; + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr EQUALTO expr { $$.val = NewStringf("%s==%s",$1.val,$3.val); - $$.type = T_INT; + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr NOTEQUALTO expr { $$.val = NewStringf("%s!=%s",$1.val,$3.val); - $$.type = T_INT; + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } /* Sadly this causes 2 reduce-reduce conflicts with templates. FIXME resolve these. | expr GREATERTHAN expr { $$.val = NewStringf("%s SWIG_LT %s", $1.val, $3.val); - $$.type = T_INT; + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr LESSTHAN expr { $$.val = NewStringf("%s SWIG_GT %s", $1.val, $3.val); - $$.type = T_INT; + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } */ | expr GREATERTHANOREQUALTO expr { @@ -5620,11 +5621,11 @@ exprcompound : expr PLUS expr { * loop somewhere in the type system. Just workaround for now * - SWIG_GE is defined in swiglabels.swg. */ $$.val = NewStringf("%s SWIG_GE %s", $1.val, $3.val); - $$.type = T_INT; + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr LESSTHANOREQUALTO expr { $$.val = NewStringf("%s SWIG_LE %s", $1.val, $3.val); - $$.type = T_INT; + $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr QUESTIONMARK expr COLON expr %prec QUESTIONMARK { $$.val = NewStringf("%s?%s:%s", $1.val, $3.val, $5.val); diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c index 3de794fdc..507c8c748 100644 --- a/Source/Swig/scanner.c +++ b/Source/Swig/scanner.c @@ -16,7 +16,8 @@ char cvsroot_scanner_c[] = "$Id$"; #include extern String *cparse_file; -extern int cparse_start_line; +extern int cparse_cplusplus; +extern int cparse_start_line; struct Scanner { String *text; /* Current token value */ @@ -730,15 +731,25 @@ static int look(Scanner * s) { break; case 7: /* Identifier */ if ((c = nextchar(s)) == 0) - return SWIG_TOKEN_ID; - if (isalnum(c) || (c == '_') || (c == '$')) { + state = 71; + else if (isalnum(c) || (c == '_') || (c == '$')) { state = 7; } else { retract(s, 1); - return SWIG_TOKEN_ID; + state = 71; } break; + case 71: /* Identifier or true/false */ + if (cparse_cplusplus) { + if (Strcmp(s->text, "true") == 0) + return SWIG_TOKEN_BOOL; + else if (Strcmp(s->text, "false") == 0) + return SWIG_TOKEN_BOOL; + } + return SWIG_TOKEN_ID; + break; + case 75: /* Special identifier $ */ if ((c = nextchar(s)) == 0) return SWIG_TOKEN_DOLLAR; @@ -747,7 +758,7 @@ static int look(Scanner * s) { } else { retract(s,1); if (Len(s->text) == 1) return SWIG_TOKEN_DOLLAR; - return SWIG_TOKEN_ID; + state = 71; } break; diff --git a/Source/Swig/swigscan.h b/Source/Swig/swigscan.h index 3403098df..2adf7b2be 100644 --- a/Source/Swig/swigscan.h +++ b/Source/Swig/swigscan.h @@ -64,6 +64,7 @@ extern void Scanner_freeze_line(Scanner *s, int val); #define SWIG_TOKEN_ULONGLONG 29 /* 314ULL */ #define SWIG_TOKEN_QUESTION 30 /* ? */ #define SWIG_TOKEN_COMMENT 31 /* C or C++ comment */ +#define SWIG_TOKEN_BOOL 32 /* true or false */ #define SWIG_TOKEN_ILLEGAL 99 #define SWIG_TOKEN_ERROR -1