diff --git a/CHANGES.current b/CHANGES.current
index 3bd75e26a..405789c12 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -1,6 +1,29 @@
Version 1.3.32 (in progress)
============================
+01/12/2007: beazley
+ New command line option -macroerrors. When supplied, this will force
+ the C scanner/parser to report proper location information for code contained
+ inside SWIG macros (defined with %define). By default, SWIG merely reports
+ errors on the line at which a macro is used. With this option, you
+ can expand the error back to its source---something which may simplify
+ debugging.
+01/12/2007: beazley
+ [Internals] Major overhaul of C/C++ scanning implementation. For quite
+ some time, SWIG contained two completely independent C/C++ tokenizers--
+ the legacy scanner in CParse/cscanner.c and a general purpose scanner
+ in Swig/scanner.c. SWIG still has two scanning modules, but the C parser
+ scanner (CParse/cscanner.c) now relies upon the general purpose
+ scanner found in Swig/scanner.c. As a result, it is much smaller and
+ less complicated. This change also makes it possible to maintain all
+ of the low-level C tokenizing in one central location instead of two
+ places as before.
+
+ ***POTENTIAL FLAKINESS***
+ This change may cause problems with accurate line number reporting
+ as well as error reporting more generally. I have tried to resolve this
+ as much as possible, but there might be some corner cases.
+
01/12/2007: mgossage
[Lua] Added typemap throws for std::string*, typemap for SWIGTYPE DYNAMIC,
changed the existing throws typemap to throw a string instead of making a copy of
diff --git a/Doc/Devel/scanner.html b/Doc/Devel/scanner.html
index 28bd3af52..4cfd82bcd 100644
--- a/Doc/Devel/scanner.html
+++ b/Doc/Devel/scanner.html
@@ -26,7 +26,7 @@ constant expressions.
All of these functions are declared in Source/Swig/swigscan.h. This API is considered to be stable.
-
Creation and Deletion of Scanner
+Creation and Deletion of Scanners
The following functions are used to create and destroy a scanner object. More than one scanner object can be created and used
as necessary.
@@ -118,17 +118,23 @@ Changes the current filename and line number of the scanner.<
-String *Scanner_get_file(Scanner *s)
+String *Scanner_file(Scanner *s)
Gets the current filename associated with text in the scanner.
-int Scanner_get_line(Scanner *s)
+int Scanner_line(Scanner *s)
Gets the current line number associated with text in the scanner.
+
+int Scanner_start_line(Scanner *s)
+
+Gets the starting line number of the last token returned by the scanner.
+
+
void Scanner_idstart(Scanner *s, char *idchar)
@@ -159,6 +165,13 @@ A convenience function that returns 0 or 1 depending on whether tokval
operator overloading).
+
+void Scanner_freeze_line(int val)
+
+Freezes the current line number depending upon whether or not val is 1 or 0. When the line number is frozen, newline characters will not result in
+updates to the line number. This is sometimes useful in tracking line numbers through complicated macro expansions.
+
+
Token Codes
diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h
index 309fa0811..06a901c0d 100644
--- a/Source/CParse/cparse.h
+++ b/Source/CParse/cparse.h
@@ -20,7 +20,7 @@ extern "C" {
#endif
/* cscanner.c */
- extern char *cparse_file;
+ extern String *cparse_file;
extern int cparse_line;
extern int cparse_cplusplus;
extern int cparse_start_line;
@@ -34,6 +34,8 @@ extern "C" {
extern void scanner_ignore_typedef(void);
extern void scanner_last_id(int);
extern void scanner_clear_rename(void);
+ extern void scanner_set_location(String_or_char *, int line);
+ extern void Swig_cparse_follow_locators(int);
extern void start_inline(char *, int);
extern String *scanner_ccode;
extern int yylex();
diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c
index cd76d1e06..5ee982aaf 100644
--- a/Source/CParse/cscanner.c
+++ b/Source/CParse/cscanner.c
@@ -4,7 +4,11 @@
*
* scanner.c
*
- * SWIG tokenizer.
+ * SWIG tokenizer. This file is a wrapper around the generic C scanner
+ * found in Swig/scanner.c. Extra logic is added both to accomodate the
+ * bison-based grammar and certain peculiarities of C++ parsing (e.g.,
+ * operator overloading, typedef resolution, etc.). This code also splits
+ * C identifiers up into keywords and SWIG directives.
* ----------------------------------------------------------------------------- */
char cvsroot_cscanner_c[] = "$Id$";
@@ -14,38 +18,29 @@ char cvsroot_cscanner_c[] = "$Id$";
#include
#include
-#define YYBSIZE 65536
+/* Scanner object */
+static Scanner *scan = 0;
-typedef struct InFile {
- DOHFile *f;
- int line_number;
- char *in_file;
- struct InFile *prev;
-} InFile;
+/* Global string containing C code. Used by the parser to grab code blocks */
+DOHString *scanner_ccode = 0;
-static InFile *in_head;
+/* Error reporting/location information */
+int cparse_line = 1;
+String *cparse_file = 0;
+int cparse_start_line = 0;
-DOHFile *LEX_in = 0;
-static DOHString *header = 0;
-static DOHString *comment = 0;
-DOHString *scanner_ccode = 0; /* String containing C code */
-static char *yybuffer = 0;
+/* C++ mode */
+int cparse_cplusplus = 0;
-static char yytext[YYBSIZE];
-static int yylen = 0;
-int cparse_line = 1;
-char *cparse_file;
-int cparse_start_line = 0;
-
-static int comment_start;
+/* Private vars */
static int scan_init = 0;
static int num_brace = 0;
static int last_brace = 0;
static int last_id = 0;
static int rename_active = 0;
-static int swigtemplate_active = 0;
-int cparse_cplusplus = 0;
static int expanding_macro = 0;
+static int follow_locators = 0;
+
/* -----------------------------------------------------------------------------
* Swig_cparse_cplusplus()
* ----------------------------------------------------------------------------- */
@@ -58,95 +53,96 @@ void Swig_cparse_cplusplus(int v) {
* locator()
*
* Support for locator strings. These are strings of the form
- * @filename,line,id@ emitted by the SWIG preprocessor. They
+ * @SWIG:filename,line,id@ emitted by the SWIG preprocessor. They
* are primarily used for macro line number reporting
* ---------------------------------------------------------------------- */
-#if 1
-
-/* we just use the locator to mark when active/deactive the linecounting */
-
-static void scanner_locator(String *loc) {
- if (Equal(loc, "@SWIG@")) {
- /* End locator. */
- if (expanding_macro)
- --expanding_macro;
- } else {
- /* Begin locator. */
- ++expanding_macro;
- }
-}
-
-#else
typedef struct Locator {
- char *filename;
- int line_number;
+ String *filename;
+ int line_number;
struct Locator *next;
} Locator;
static Locator *locs = 0;
+/* we just use the locator to mark when active/deactive the linecounting */
+
static void scanner_locator(String *loc) {
- int c;
- Locator *l;
- Seek(loc, 1, SEEK_SET);
- c = Getc(loc);
- if (c == '@') {
- /* Empty locator. We pop the last location off */
- if (locs) {
- cparse_file = locs->filename;
- cparse_line = locs->line_number;
- l = locs->next;
- free(locs);
- locs = l;
+ if (!follow_locators) {
+ if (Equal(loc, "/*@SWIG@*/")) {
+ /* End locator. */
+ if (expanding_macro)
+ --expanding_macro;
+ } else {
+ /* Begin locator. */
+ ++expanding_macro;
}
- /* Printf(stderr,"location: %s:%d\n",cparse_file,cparse_line); */
- return;
- }
-
- /* We're going to push a new location */
- l = (Locator *) malloc(sizeof(Locator));
- l->filename = cparse_file;
- l->line_number = cparse_line;
- l->next = locs;
- locs = l;
-
- /* Now, parse the new location out of the locator string */
- {
- String *fn = NewStringEmpty();
- Putc(c, fn);
-
- while ((c = Getc(loc)) != EOF) {
- if ((c == '@') || (c == ','))
- break;
- Putc(c, fn);
+ /* Freeze line number processing in Scanner */
+ Scanner_freeze_line(scan,expanding_macro);
+ } else {
+ int c;
+ Locator *l;
+ Seek(loc, 7, SEEK_SET);
+ c = Getc(loc);
+ if (c == '@') {
+ /* Empty locator. We pop the last location off */
+ if (locs) {
+ Scanner_set_location(scan,locs->filename,locs->line_number);
+ cparse_file = locs->filename;
+ cparse_line = locs->line_number;
+ l = locs->next;
+ free(locs);
+ locs = l;
+ }
+ return;
}
- cparse_file = Swig_copy_string(Char(fn));
- Clear(fn);
+ /* We're going to push a new location */
+ l = (Locator *) malloc(sizeof(Locator));
+ l->filename = cparse_file;
+ l->line_number = cparse_line;
+ l->next = locs;
+ locs = l;
- cparse_line = 1;
- /* Get the line number */
- while ((c = Getc(loc)) != EOF) {
- if ((c == '@') || (c == ','))
- break;
- Putc(c, fn);
+ /* Now, parse the new location out of the locator string */
+ {
+ String *fn = NewStringEmpty();
+ /* Putc(c, fn); */
+
+ while ((c = Getc(loc)) != EOF) {
+ if ((c == '@') || (c == ','))
+ break;
+ Putc(c, fn);
+ }
+ cparse_file = Swig_copy_string(Char(fn));
+ Clear(fn);
+ cparse_line = 1;
+ /* Get the line number */
+ while ((c = Getc(loc)) != EOF) {
+ if ((c == '@') || (c == ','))
+ break;
+ Putc(c, fn);
+ }
+ cparse_line = atoi(Char(fn));
+ Clear(fn);
+
+ /* Get the rest of it */
+ while ((c = Getc(loc)) != EOF) {
+ if (c == '@')
+ break;
+ Putc(c, fn);
+ }
+ /* Printf(stderr,"location: %s:%d\n",cparse_file,cparse_line); */
+ Scanner_set_location(scan,cparse_file,cparse_line);
+ Delete(fn);
}
-
- cparse_line = atoi(Char(fn));
- Clear(fn);
-
- /* Get the rest of it */
- while ((c = Getc(loc)) != EOF) {
- if (c == '@')
- break;
- Putc(c, fn);
- }
- /* Printf(stderr,"location: %s:%d\n",cparse_file,cparse_line); */
- Delete(fn);
}
}
-#endif
+
+void Swig_cparse_follow_locators(int v) {
+ follow_locators = v;
+}
+
/* ----------------------------------------------------------------------------
* scanner_init()
@@ -155,151 +151,40 @@ static void scanner_locator(String *loc) {
* ------------------------------------------------------------------------- */
void scanner_init() {
- yybuffer = (char *) malloc(YYBSIZE);
+ scan = NewScanner();
+ Scanner_idstart(scan,"%");
scan_init = 1;
- header = NewStringEmpty();
- comment = NewStringEmpty();
scanner_ccode = NewStringEmpty();
}
/* ----------------------------------------------------------------------------
- * scanner_file(FILE *f)
+ * scanner_file(DOHFile *f)
*
* Start reading from new file
* ------------------------------------------------------------------------- */
void scanner_file(DOHFile * f) {
- InFile *in;
-
- in = (InFile *) malloc(sizeof(InFile));
- in->f = f;
- in->in_file = cparse_file;
- in->line_number = 1;
- if (!in_head)
- in->prev = 0;
- else
- in->prev = in_head;
- in_head = in;
- LEX_in = f;
- cparse_line = 1;
-}
-
-/* ----------------------------------------------------------------------------
- * scanner_close()
- *
- * Close current input file and go to next
- * ------------------------------------------------------------------------- */
-
-void scanner_close() {
- InFile *p;
- if (!in_head)
- return;
- Delete(LEX_in);
- p = in_head->prev;
- if (p != 0) {
- LEX_in = p->f;
- cparse_line = p->line_number;
- cparse_file = p->in_file;
- } else {
- LEX_in = 0;
- }
- free(in_head);
- in_head = p;
-}
-
-/* ----------------------------------------------------------------------------
- * unsigned char nextchar()
- *
- * gets next character from input.
- * If we're in inlining mode, we actually retrieve a character
- * from inline_yybuffer instead.
- * Return value is unsigned char since isalpha(), etc aren't defined for the
- * negative values that we get if char is signed.
- * ------------------------------------------------------------------------- */
-
-unsigned char nextchar() {
- int c = 0;
-
- while (LEX_in) {
- c = Getc(LEX_in);
- if (c == EOF) {
- scanner_close();
- } else {
- break;
- }
- }
- if (!LEX_in)
- return 0;
- if (yylen >= YYBSIZE) {
- Printf(stderr, "** FATAL ERROR. Buffer overflow in scanner.c.\nPlease report to the SWIG developers.\n");
- exit(EXIT_FAILURE);
- }
- yytext[yylen] = c;
- yylen++;
- if (c == '\n') {
- if (!expanding_macro)
- cparse_line++;
- }
- return c;
-}
-
-void retract(int n) {
- int i;
- for (i = 0; i < n; i++) {
- yylen--;
- if (yylen >= 0) {
- Ungetc(yytext[yylen], LEX_in);
- if (yytext[yylen] == '\n') {
- if (!expanding_macro)
- cparse_line--;
- }
- }
- }
- if (yylen < 0)
- yylen = 0;
+ if (!scan_init) scanner_init();
+ Scanner_clear(scan);
+ Scanner_push(scan,f);
}
/* ----------------------------------------------------------------------------
* start_inline(char *text, int line)
*
- * This grabs a chunk of text and tries to inline it into
- * the current file. (This is kind of wild, but cool when
- * it works).
- *
- * If we're already in inlining mode, we will save the code
- * as a new fragment.
+ * Take a chunk of text and recursively feed it back into the scanner. Used
+ * by the %inline directive.
* ------------------------------------------------------------------------- */
void start_inline(char *text, int line) {
- InFile *in;
+ String *stext = NewString(text);
- if (!in_head)
- return;
- /* Save current state */
- in_head->line_number = cparse_line;
- in_head->in_file = cparse_file;
-
- in = (InFile *) malloc(sizeof(InFile));
- in->f = NewString(text);
- Seek(in->f, 0, SEEK_SET);
- in->in_file = Swig_copy_string(cparse_file);
- in->line_number = line;
- in->prev = in_head;
- in_head = in;
- LEX_in = in->f;
- cparse_line = line;
+ Seek(stext,0,SEEK_SET);
+ Setfile(stext,cparse_file);
+ Setline(stext,line);
+ Scanner_push(scan,stext);
+ Delete(stext);
}
-/* ----------------------------------------------------------------------------
- * yycomment(char *, int line)
- *
- * Inserts a comment into a documentation entry.
- * ------------------------------------------------------------------------- */
-
-/*
-void yycomment(char *a, int b, int c) {
-}
-*/
-
/* -----------------------------------------------------------------------------
* skip_balanced()
*
@@ -308,82 +193,17 @@ void yycomment(char *a, int b, int c) {
* ----------------------------------------------------------------------------- */
void skip_balanced(int startchar, int endchar) {
- int c;
- int num_levels = 1;
- int state = 0;
- int start_line = cparse_line;
-
Clear(scanner_ccode);
- Putc(startchar, scanner_ccode);
- while (num_levels > 0) {
- c = nextchar();
- if (c == 0) {
- Swig_error(cparse_file, start_line, "Missing '%c'. Reached end of input.\n", endchar);
- return;
- }
- Putc(c, scanner_ccode);
- switch (state) {
- case 0:
- if (c == startchar)
- num_levels++;
- else if (c == endchar)
- num_levels--;
- else if (c == '/')
- state = 10;
- else if (c == '\"')
- state = 20;
- else if (c == '\'')
- state = 30;
- break;
- case 10:
- if (c == '/')
- state = 11;
- else if (c == '*')
- state = 12;
- else
- state = 0;
- break;
- case 11:
- if (c == '\n')
- state = 0;
- else
- state = 11;
- break;
- case 12:
- if (c == '*')
- state = 13;
- break;
- case 13:
- if (c == '*')
- state = 13;
- else if (c == '/')
- state = 0;
- else
- state = 12;
- break;
- case 20:
- if (c == '\"')
- state = 0;
- else if (c == '\\')
- state = 21;
- break;
- case 21:
- state = 20;
- break;
- case 30:
- if (c == '\'')
- state = 0;
- else if (c == '\\')
- state = 31;
- break;
- case 31:
- state = 30;
- break;
- default:
- break;
- }
- yylen = 0;
+
+ if (Scanner_skip_balanced(scan,startchar,endchar) < 0) {
+ Swig_error(Scanner_file(scan),Scanner_errline(scan), "Missing '%c'. Reached end of input.\n", endchar);
+ return;
}
+
+ cparse_line = Scanner_line(scan);
+ cparse_file = Scanner_file(scan);
+
+ Append(scanner_ccode, Scanner_text(scan));
if (endchar == '}')
num_brace--;
return;
@@ -402,723 +222,216 @@ void skip_balanced(int startchar, int endchar) {
* ------------------------------------------------------------------------- */
void skip_decl(void) {
- int c;
+ int tok;
int done = 0;
- int start_line = cparse_line;
+ int start_line = Scanner_line(scan);
while (!done) {
- if ((c = nextchar()) == 0) {
+ tok = Scanner_token(scan);
+ if (tok == 0) {
if (!Swig_error_count()) {
- Swig_error(cparse_file, start_line - 1, "Missing semicolon. Reached end of input.\n");
+ Swig_error(cparse_file, start_line, "Missing semicolon. Reached end of input.\n");
}
-
return;
}
- if (c == '{') {
- last_brace = num_brace;
- num_brace++;
+ if (tok == SWIG_TOKEN_LBRACE) {
+ if (Scanner_skip_balanced(scan,'{','}') < 0) {
+ Swig_error(cparse_file, start_line, "Missing '}'. Reached end of input.\n");
+ }
break;
}
- yylen = 0;
- if (c == ';')
+ if (tok == SWIG_TOKEN_SEMI) {
done = 1;
- }
- if (!done) {
- while (num_brace > last_brace) {
- if ((c = nextchar()) == 0) {
- if (!Swig_error_count()) {
- Swig_error(cparse_file, start_line - 1, "Missing '}'. Reached end of input.\n");
- }
- return;
- }
- if (c == '{')
- num_brace++;
- if (c == '}')
- num_brace--;
- yylen = 0;
}
}
-}
-
-/* This function is called when a backslash is found in a string */
-static void get_escape() {
- int result = 0;
- int state = 0;
- int c;
-
- while (1) {
- c = nextchar();
- if (c == 0)
- break;
- switch (state) {
- case 0:
- if (c == 'n') {
- yytext[yylen - 1] = '\n';
- return;
- }
- if (c == 'r') {
- yytext[yylen - 1] = '\r';
- return;
- }
- if (c == 't') {
- yytext[yylen - 1] = '\t';
- return;
- }
- if (c == 'a') {
- yytext[yylen - 1] = '\a';
- return;
- }
- if (c == 'b') {
- yytext[yylen - 1] = '\b';
- return;
- }
- if (c == 'f') {
- yytext[yylen - 1] = '\f';
- return;
- }
- if (c == '\\') {
- yytext[yylen - 1] = '\\';
- return;
- }
- if (c == 'v') {
- yytext[yylen - 1] = '\v';
- return;
- }
- if (c == 'e') {
- yytext[yylen - 1] = '\033';
- return;
- }
- if (c == '\'') {
- yytext[yylen - 1] = '\'';
- return;
- }
- if (c == '\"') {
- yytext[yylen - 1] = '\"';
- return;
- }
- if (c == '\n') {
- yylen--;
- return;
- }
- if (isdigit(c)) {
- state = 10;
- result = (c - '0');
- } else if (c == 'x') {
- state = 20;
- } else {
- yytext[yylen - 1] = '\\';
- yytext[yylen] = c;
- yylen++;
- return;
- }
- break;
- case 10:
- if (!isdigit(c)) {
- retract(1);
- yytext[yylen - 1] = (char) result;
- return;
- }
- result = (result << 3) + (c - '0');
- yylen--;
- break;
- case 20:
- if (!isxdigit(c)) {
- retract(1);
- yytext[yylen - 1] = (char) result;
- return;
- }
- if (isdigit(c))
- result = (result << 4) + (c - '0');
- else
- result = (result << 4) + (10 + tolower(c) - 'a');
- yylen--;
- break;
- }
- }
- return;
+ cparse_file = Scanner_file(scan);
+ cparse_line = Scanner_line(scan);
}
/* ----------------------------------------------------------------------------
* int yylook()
*
* Lexical scanner.
- * See Aho,Sethi, and Ullman, pg. 106
* ------------------------------------------------------------------------- */
int yylook(void) {
- int state;
- int c = 0;
+ int tok = 0;
- state = 0;
- yylen = 0;
while (1) {
+ if ((tok = Scanner_token(scan)) == 0)
+ return 0;
+ if (tok == SWIG_TOKEN_ERROR) {
+ Swig_error(Scanner_file(scan), Scanner_errline(scan), Scanner_errmsg(scan));
+ continue;
+ }
+ cparse_start_line = Scanner_start_line(scan);
+ cparse_line = Scanner_line(scan);
+ cparse_file = Scanner_file(scan);
-/* printf("State = %d\n", state); */
- switch (state) {
-
- case 0:
- if ((c = nextchar()) == 0)
- return (0);
-
- /* Process delimiters */
-
- if (c == '\n') {
- state = 0;
- yylen = 0;
- /* last_id = 0; */
- } else if (isspace(c) || (c == '\\')) {
- state = 0;
- yylen = 0;
- /* last_id = 0; */
- }
-
- else if ((isalpha(c)) || (c == '_'))
- state = 7;
- else if (c == '$')
- state = 75;
-
- /* Look for single character symbols */
-
- else if (c == '(')
- return (LPAREN);
- else if (c == ')')
- return (RPAREN);
- else if (c == ';') {
- swigtemplate_active = 0;
- return (SEMI);
- }
-
- else if (c == ',')
- return (COMMA);
- else if (c == '*')
- return (STAR);
- else if (c == '}') {
- num_brace--;
- if (num_brace < 0) {
- Swig_error(cparse_file, cparse_line, "Syntax error. Extraneous '}'\n");
- state = 0;
- num_brace = 0;
- } else {
- return (RBRACE);
- }
- } else if (c == '{') {
- cparse_start_line = cparse_line;
- last_brace = num_brace;
- num_brace++;
- return (LBRACE);
- } else if (c == '=')
- state = 63;
- else if (c == '+')
- return (PLUS);
- else if (c == '-')
- return (MINUS);
- else if (c == '&') {
- state = 300;
- } else if (c == '|') {
- state = 301;
- } else if (c == '^')
- return (XOR);
- else if (c == '<')
- state = 60;
- else if (c == '>')
- state = 61;
- else if (c == '~') {
- return (NOT);
- } else if (c == '!')
- state = 62;
- else if (c == '\\') {
- state = 99;
- } else if (c == '[')
- return (LBRACKET);
- else if (c == ']')
- return (RBRACKET);
-
- /* Look for multi-character sequences */
-
- else if (c == '/')
- state = 1; /* Comment (maybe) */
- else if (c == '\"')
- state = 2; /* Possibly a string */
- else if (c == '#')
- state = 3; /* CPP */
- else if (c == '%')
- state = 4; /* Directive */
- else if (c == '@')
- state = 4; /* Objective C keyword */
- else if (c == ':')
- state = 5; /* maybe double colon */
- else if (c == '0')
- state = 83; /* An octal or hex value */
- else if (c == '\'')
- state = 9; /* A character constant */
- else if (c == '.')
- state = 100; /* Maybe a number, maybe just a period */
- else if (c == '?')
- return (QUESTIONMARK); /* Ternary conditional operator */
- else if (c == '`') {
- state = 200; /* Back-tick type */
- yylen = 0;
- } else if (isdigit(c))
- state = 8; /* A numerical value */
-
- else
- state = 99;
- break;
- case 1: /* Comment block */
- if ((c = nextchar()) == 0)
- return (0);
- if (c == '/') {
- comment_start = cparse_line;
- Clear(comment);
- state = 10; /* C++ style comment */
- } else if (c == '*') {
- comment_start = cparse_line;
- Clear(comment);
- state = 12; /* C style comment */
+ switch(tok) {
+ case SWIG_TOKEN_ID:
+ return ID;
+ case SWIG_TOKEN_LPAREN:
+ return LPAREN;
+ case SWIG_TOKEN_RPAREN:
+ return RPAREN;
+ case SWIG_TOKEN_SEMI:
+ return SEMI;
+ case SWIG_TOKEN_COMMA:
+ return COMMA;
+ case SWIG_TOKEN_STAR:
+ return STAR;
+ case SWIG_TOKEN_RBRACE:
+ num_brace--;
+ if (num_brace < 0) {
+ Swig_error(cparse_file, cparse_line, "Syntax error. Extraneous '}'\n");
+ num_brace = 0;
} else {
- retract(1);
- return (SLASH);
+ return RBRACE;
}
break;
- case 300: /* & or && */
- if ((c = nextchar()) == 0)
- return (AND);
- if (c == '&')
- return (LAND);
- else {
- retract(1);
- return (AND);
- }
-
- case 301: /* | or || */
- if ((c = nextchar()) == 0)
- return (OR);
- if (c == '|')
- return (LOR);
- else {
- retract(1);
- return (OR);
- }
- case 10: /* C++ style comment */
- if ((c = nextchar()) == 0) {
- Swig_error(cparse_file, -1, "Unterminated comment detected.\n");
- return 0;
- }
- if (c == '\n') {
- Putc(c, comment);
- /* Add the comment to documentation */
- /* yycomment(Char(comment),comment_start, column_start); */
- yylen = 0;
- state = 0;
- } else {
- state = 10;
- Putc(c, comment);
- yylen = 0;
- }
- break;
-
- case 12: /* C style comment block */
- if ((c = nextchar()) == 0) {
- Swig_error(cparse_file, -1, "Unterminated comment detected.\n");
- return 0;
- }
- if (c == '*') {
- state = 13;
- } else {
- Putc(c, comment);
- yylen = 0;
- state = 12;
- }
- break;
- case 13: /* Still in C style comment */
- if ((c = nextchar()) == 0) {
- Swig_error(cparse_file, -1, "Unterminated comment detected.\n");
- return 0;
- }
- if (c == '*') {
- Putc(c, comment);
- state = 13;
- } else if (c == '/') {
- /* Look for locator markers */
- char *loc = Char(comment);
- if (loc && (strncmp(loc, "@SWIG", 4) == 0) && (*(loc + Len(comment) - 1) == '@')) {
- /* Locator */
- scanner_locator(comment);
- yylen = 0;
- state = 0;
- } else {
- yylen = 0;
- state = 0;
- }
- } else {
- Putc('*', comment);
- Putc(c, comment);
- yylen = 0;
- state = 12;
- }
- break;
-
- case 2: /* Processing a string */
- if ((c = nextchar()) == 0) {
- Swig_error(cparse_file, -1, "Unterminated string detected.\n");
- return 0;
- }
- if (c == '\"') {
- yytext[yylen - 1] = 0;
- yylval.id = Swig_copy_string(yytext + 1);
- return (STRING);
- } else if (c == '\\') {
- yylen--;
- get_escape();
- break;
- } else
- state = 2;
- break;
-
- case 3: /* a CPP directive */
- if ((c = nextchar()) == 0)
- return 0;
- if (c == '\n') {
- retract(1);
- yytext[yylen] = 0;
- yylval.id = yytext;
- return (POUND);
- }
- break;
-
- case 4: /* A wrapper generator directive (maybe) */
- if ((c = nextchar()) == 0)
- return 0;
- if (c == '{') {
- state = 40; /* Include block */
- Clear(header);
- cparse_start_line = cparse_line;
- } else if ((isalpha(c)) || (c == '_'))
- state = 7;
- else if (c == '}') {
- Swig_error(cparse_file, cparse_line, "Misplaced %%}.\n");
- return 0;
- } else {
- retract(1);
- return (MODULO);
- }
- break;
-
- case 40: /* Process an include block */
- if ((c = nextchar()) == 0) {
- Swig_error(cparse_file, -1, "Unterminated include block detected.\n");
- return 0;
- }
- yylen = 0;
- if (c == '%')
- state = 41;
- else {
- Putc(c, header);
- yylen = 0;
- state = 40;
- }
- break;
- case 41: /* Still processing include block */
- if ((c = nextchar()) == 0) {
- Swig_error(cparse_file, -1, "Unterminated include block detected.\n");
- return 0;
- }
- if (c == '}') {
- yylval.str = NewString(header);
- return (HBLOCK);
- } else {
- Putc('%', header);
- Putc(c, header);
- yylen = 0;
- state = 40;
- }
- break;
-
- case 5: /* Maybe a double colon */
-
- if ((c = nextchar()) == 0)
- return 0;
- if (c == ':') {
- state = 51;
- } else {
- retract(1);
- return COLON;
- }
- break;
- case 51: /* Maybe a ::*, ::~, or :: */
- if ((c = nextchar()) == 0)
- return 0;
- if (c == '*') {
- return DSTAR;
- } else if (c == '~') {
- return DCNOT;
- } else if (isspace(c)) {
- /* Keep scanning ahead. Might be :: * or :: ~ */
- } else {
- retract(1);
- if (!last_id) {
- retract(2);
- return NONID;
- } else {
- return DCOLON;
- }
- }
- break;
-
- case 60: /* < - less than or less than or equal to or left shift operator */
- if ((c = nextchar()) == 0)
- return (0);
- if (c == '<')
- return LSHIFT;
- if (c == '=')
- return LESSTHANOREQUALTO;
- else {
- retract(1);
- return LESSTHAN;
- }
- case 61: /* > - greater than or greater or equal to or right shift operator */
- if ((c = nextchar()) == 0)
- return (0);
- if (c == '>')
- return RSHIFT;
- if (c == '=')
- return GREATERTHANOREQUALTO;
- else {
- retract(1);
- return GREATERTHAN;
- }
- case 62: /* ! - logical not or not equal to */
- if ((c = nextchar()) == 0)
- return (0);
- if (c == '=')
- return NOTEQUALTO;
- retract(1);
- return LNOT;
- case 63: /* = - equal (assignment) or equal to */
- if ((c = nextchar()) == 0)
- return (0);
- if (c == '=')
- return EQUALTO;
- retract(1);
+ case SWIG_TOKEN_LBRACE:
+ last_brace = num_brace;
+ num_brace++;
+ return LBRACE;
+ case SWIG_TOKEN_EQUAL:
return EQUAL;
- case 7: /* Identifier */
- if ((c = nextchar()) == 0)
- return (0);
- if (isalnum(c) || (c == '_') || (c == '.') || (c == '$')) {
- state = 7;
- } else {
- retract(1);
- return (ID);
- }
- break;
- case 75: /* Special identifier $ */
- if ((c = nextchar()) == 0)
- return (0);
- if (isalnum(c) || (c == '_') || (c == '*') || (c == '&')) {
- state = 7;
- } else {
- retract(1);
- return (ID);
- }
- break;
-
- case 8: /* A numerical digit */
- if ((c = nextchar()) == 0)
- return (0);
- if (c == '.') {
- state = 81;
- } else if ((c == 'e') || (c == 'E')) {
- state = 86;
- } else if ((c == 'f') || (c == 'F')) {
- return (NUM_FLOAT);
- } else if (isdigit(c)) {
- state = 8;
- } else if ((c == 'l') || (c == 'L')) {
- state = 87;
- } else if ((c == 'u') || (c == 'U')) {
- state = 88;
- } else {
- retract(1);
- return (NUM_INT);
- }
- break;
- case 81: /* A floating pointer number of some sort */
- if ((c = nextchar()) == 0)
- return (0);
- if (isdigit(c))
- state = 81;
- else if ((c == 'e') || (c == 'E'))
- state = 82;
- else if ((c == 'f') || (c == 'F') || (c == 'l') || (c == 'L')) {
- return (NUM_FLOAT);
- } else {
- retract(1);
- return (NUM_FLOAT);
- }
- break;
- case 82:
- if ((c = nextchar()) == 0)
- return (0);
- if ((isdigit(c)) || (c == '-') || (c == '+'))
- state = 86;
- else {
- retract(2);
- yytext[yylen - 1] = 0;
- return (NUM_INT);
- }
- break;
- case 83:
- /* Might be a hexadecimal or octal number */
- if ((c = nextchar()) == 0)
- return (0);
- if (isdigit(c))
- state = 84;
- else if ((c == 'x') || (c == 'X'))
- state = 85;
- else if (c == '.')
- state = 81;
- else if ((c == 'l') || (c == 'L')) {
- state = 87;
- } else if ((c == 'u') || (c == 'U')) {
- state = 88;
- } else {
- retract(1);
- return (NUM_INT);
- }
- break;
- case 84:
- /* This is an octal number */
- if ((c = nextchar()) == 0)
- return (0);
- if (isdigit(c))
- state = 84;
- else if ((c == 'l') || (c == 'L')) {
- state = 87;
- } else if ((c == 'u') || (c == 'U')) {
- state = 88;
- } else {
- retract(1);
- return (NUM_INT);
- }
- break;
- case 85:
- /* This is an hex number */
- if ((c = nextchar()) == 0)
- return (0);
- if (isxdigit(c))
- state = 85;
- else if ((c == 'l') || (c == 'L')) {
- state = 87;
- } else if ((c == 'u') || (c == 'U')) {
- state = 88;
- } else {
- retract(1);
- return (NUM_INT);
- }
- break;
-
- case 86:
- /* Rest of floating point number */
-
- if ((c = nextchar()) == 0)
- return (0);
- if (isdigit(c))
- state = 86;
- else if ((c == 'f') || (c == 'F') || (c == 'l') || (c == 'L')) {
- return (NUM_FLOAT);
- } else {
- retract(1);
- return (NUM_FLOAT);
- }
- break;
-
- case 87:
- /* A long integer of some sort */
- if ((c = nextchar()) == 0)
- return (NUM_LONG);
- if ((c == 'u') || (c == 'U')) {
- return (NUM_ULONG);
- } else if ((c == 'l') || (c == 'L')) {
- state = 870;
- } else {
- retract(1);
- return (NUM_LONG);
- }
- break;
-
- case 870:
- if ((c = nextchar()) == 0)
- return (NUM_LONGLONG);
- if ((c == 'u') || (c == 'U')) {
- return (NUM_ULONGLONG);
- } else {
- retract(1);
- return (NUM_LONGLONG);
- }
-
- case 88:
- /* An unsigned integer of some sort */
- if ((c = nextchar()) == 0)
- return (NUM_UNSIGNED);
- if ((c == 'l') || (c == 'L')) {
- state = 880;
- } else {
- retract(1);
- return (NUM_UNSIGNED);
- }
- break;
-
- case 880:
- if ((c = nextchar()) == 0)
- return (NUM_ULONG);
- if ((c == 'l') || (c == 'L'))
- return (NUM_ULONGLONG);
- else {
- retract(1);
- return (NUM_ULONG);
- }
-
- case 9:
- /* Parse a character constant. ie. 'a' */
- if ((c = nextchar()) == 0)
- return (0);
- if (c == '\\') {
- yylen--;
- get_escape();
- } else if (c == '\'') {
- yytext[yylen - 1] = 0;
- yylval.str = NewString(yytext + 1);
- if (yylen == 2) {
- Swig_error(cparse_file, cparse_line, "Empty character constant\n");
+ case SWIG_TOKEN_EQUALTO:
+ return EQUALTO;
+ case SWIG_TOKEN_PLUS:
+ return PLUS;
+ case SWIG_TOKEN_MINUS:
+ return MINUS;
+ case SWIG_TOKEN_SLASH:
+ return SLASH;
+ case SWIG_TOKEN_AND:
+ return AND;
+ case SWIG_TOKEN_LAND:
+ return LAND;
+ case SWIG_TOKEN_OR:
+ return OR;
+ case SWIG_TOKEN_LOR:
+ return LOR;
+ case SWIG_TOKEN_XOR:
+ return XOR;
+ case SWIG_TOKEN_NOT:
+ return NOT;
+ case SWIG_TOKEN_LNOT:
+ return LNOT;
+ case SWIG_TOKEN_NOTEQUAL:
+ return NOTEQUALTO;
+ case SWIG_TOKEN_LBRACKET:
+ return LBRACKET;
+ case SWIG_TOKEN_RBRACKET:
+ return RBRACKET;
+ case SWIG_TOKEN_QUESTION:
+ return QUESTIONMARK;
+ case SWIG_TOKEN_LESSTHAN:
+ return LESSTHAN;
+ case SWIG_TOKEN_LTEQUAL:
+ return LESSTHANOREQUALTO;
+ case SWIG_TOKEN_LSHIFT:
+ return LSHIFT;
+ case SWIG_TOKEN_GREATERTHAN:
+ return GREATERTHAN;
+ case SWIG_TOKEN_GTEQUAL:
+ return GREATERTHANOREQUALTO;
+ case SWIG_TOKEN_RSHIFT:
+ return RSHIFT;
+ case SWIG_TOKEN_PERIOD:
+ return PERIOD;
+ case SWIG_TOKEN_MODULO:
+ return MODULO;
+ case SWIG_TOKEN_COLON:
+ return COLON;
+ case SWIG_TOKEN_DCOLONSTAR:
+ return DSTAR;
+
+ case SWIG_TOKEN_DCOLON:
+ {
+ int nexttok = Scanner_token(scan);
+ if (nexttok == SWIG_TOKEN_STAR) {
+ return DSTAR;
+ } else if (nexttok == SWIG_TOKEN_NOT) {
+ return DCNOT;
+ } else {
+ Scanner_pushtoken(scan,nexttok,Scanner_text(scan));
+ if (!last_id) {
+ scanner_next_token(DCOLON);
+ return NONID;
+ } else {
+ return DCOLON;
+ }
}
- return (CHARCONST);
}
break;
-
- case 100:
- if ((c = nextchar()) == 0)
- return (0);
- if (isdigit(c))
- state = 81;
- else {
- retract(1);
- return (PERIOD);
+
+ /* Look for multi-character sequences */
+
+ case SWIG_TOKEN_RSTRING:
+ yylval.type = NewString(Scanner_text(scan));
+ return TYPE_RAW;
+
+ case SWIG_TOKEN_STRING:
+ yylval.id = Swig_copy_string(Char(Scanner_text(scan)));
+ return STRING;
+
+ case SWIG_TOKEN_CHAR:
+ yylval.str = NewString(Scanner_text(scan));
+ if (Len(yylval.str) == 0) {
+ Swig_error(cparse_file, cparse_line, "Empty character constant\n");
+ Printf(stdout,"%d\n", Len(Scanner_text(scan)));
+ }
+ return CHARCONST;
+
+ /* Numbers */
+
+ case SWIG_TOKEN_INT:
+ return NUM_INT;
+
+ case SWIG_TOKEN_UINT:
+ return NUM_UNSIGNED;
+
+ case SWIG_TOKEN_LONG:
+ return NUM_LONG;
+
+ case SWIG_TOKEN_ULONG:
+ return NUM_ULONG;
+
+ case SWIG_TOKEN_LONGLONG:
+ return NUM_LONGLONG;
+
+ case SWIG_TOKEN_ULONGLONG:
+ return NUM_ULONGLONG;
+
+ case SWIG_TOKEN_DOUBLE:
+ case SWIG_TOKEN_FLOAT:
+ return NUM_FLOAT;
+
+ case SWIG_TOKEN_POUND:
+ Scanner_skip_line(scan);
+ yylval.id = Swig_copy_string(Char(Scanner_text(scan)));
+ return POUND;
+ break;
+
+ case SWIG_TOKEN_CODEBLOCK:
+ yylval.str = NewString(Scanner_text(scan));
+ return HBLOCK;
+
+ case SWIG_TOKEN_COMMENT:
+ {
+ String *cmt = Scanner_text(scan);
+ char *loc = Char(cmt);
+ if ((strncmp(loc,"/*@SWIG@",6) == 0) && (loc[Len(cmt)-3] == '@')) {
+ scanner_locator(cmt);
+ }
}
break;
- case 200:
- if ((c = nextchar()) == 0)
- return (0);
- if (c == '`') {
- yytext[yylen - 1] = 0;
- yylval.type = NewString(yytext);
- return (TYPE_RAW);
- }
+ case SWIG_TOKEN_ENDLINE:
break;
-
default:
- Swig_error(cparse_file, cparse_line, "Illegal character '%c'=%d.\n", c, c);
- state = 0;
+ Swig_error(cparse_file, cparse_line, "Illegal token '%s'.\n", Scanner_text(scan));
return (ILLEGAL);
}
}
@@ -1126,6 +439,10 @@ int yylook(void) {
static int check_typedef = 0;
+void scanner_set_location(String_or_char *file, int line) {
+ Scanner_set_location(scan,file,line-1);
+}
+
void scanner_check_typedef() {
check_typedef = 1;
}
@@ -1135,7 +452,6 @@ void scanner_ignore_typedef() {
}
void scanner_last_id(int x) {
- /* printf("Setting last_id = %d\n", x); */
last_id = x;
}
@@ -1143,6 +459,7 @@ void scanner_clear_rename() {
rename_active = 0;
}
+/* Used to push a ficticious token into the scanner */
static int next_token = 0;
void scanner_next_token(int tok) {
next_token = tok;
@@ -1157,6 +474,7 @@ void scanner_next_token(int tok) {
int yylex(void) {
int l;
+ char *yytext;
if (!scan_init) {
scanner_init();
@@ -1167,18 +485,16 @@ int yylex(void) {
next_token = 0;
return l;
}
- /* Printf(stdout,"%d\n", last_id); */
+
l = yylook();
+ /* Printf(stdout, "%s:%d:::%d: '%s'\n", cparse_file, cparse_line, l, Scanner_text(scan)); */
+
if (l == NONID) {
last_id = 1;
} else {
last_id = 0;
}
- /*
- yytext[yylen]= 0;
- Printf(stdout,"%d '%s' %d\n", l, yytext, last_id);
- */
/* We got some sort of non-white space object. We set the start_line
variable unless it has already been set */
@@ -1189,7 +505,6 @@ int yylex(void) {
/* Copy the lexene */
- yytext[yylen] = 0;
switch (l) {
case NUM_INT:
@@ -1213,13 +528,13 @@ int yylex(void) {
yylval.dtype.type = T_LONGLONG;
if (l == NUM_ULONGLONG)
yylval.dtype.type = T_ULONGLONG;
- yylval.dtype.val = NewString(yytext);
+ yylval.dtype.val = NewString(Scanner_text(scan));
yylval.dtype.bitfield = 0;
yylval.dtype.throws = 0;
return (l);
case ID:
-
+ yytext = Char(Scanner_text(scan));
if (yytext[0] != '%') {
/* Look for keywords now */
@@ -1307,105 +622,124 @@ int yylex(void) {
if (strcmp(yytext, "virtual") == 0)
return (VIRTUAL);
if (strcmp(yytext, "operator") == 0) {
- String *s = NewString("operator");
- int c;
- int state = 0;
- int sticky = 0;
- int isconversion = 0;
- int count = 0;
- int start_template = 0;
- int end_template = 0;
- while ((c = nextchar())) {
- if (((c == '(') || (c == ';')) && state) {
- retract(1);
- break;
- }
- if ((c == '<') && !start_template) {
- int fcount = 1;
- int c2 = nextchar();
- while (isspace(c2)) {
- c2 = nextchar();
- ++fcount;
- }
- if (isalpha(c2) || c2 == ':') {
- start_template = count;
- }
- retract(fcount);
- }
- if ((c == '>') && start_template)
- end_template = count;
- count++;
- if (!isspace(c)) {
- if ((!state) && (isalpha(c))) {
- isconversion = 1;
- }
+ int nexttok;
+ String *s = NewString("operator ");
- if (!state && !sticky)
- Putc(' ', s);
- Putc(c, s);
- sticky = 0;
- state = 1;
+ /* If we have an operator, we have to collect the operator symbol and attach it to
+ the operator identifier. To do this, we need to scan ahead by several tokens.
+ Cases include:
+
+ (1) If the next token is an operator as determined by Scanner_isoperator(),
+ it means that the operator applies to one of the standard C++ mathematical,
+ assignment, or logical operator symbols (e.g., '+','<=','==','&', etc.)
+ In this case, we merely append the symbol text to the operator string above.
+
+ (2) If the next token is (, we look for ). This is operator ().
+ (3) If the next token is [, we look for ]. This is operator [].
+ (4) If the next token is an identifier. The operator is possibly a conversion operator.
+ (a) Must check for special case new[] and delete[]
+
+ Error handling is somewhat tricky here. We'll try to back out gracefully if we can.
+
+ */
+
+ nexttok = Scanner_token(scan);
+ if (Scanner_isoperator(nexttok)) {
+ /* One of the standard C/C++ symbolic operators */
+ Append(s,Scanner_text(scan));
+ yylval.str = s;
+ return OPERATOR;
+ } else if (nexttok == SWIG_TOKEN_LPAREN) {
+ /* Function call operator. The next token MUST be a RPAREN */
+ nexttok = Scanner_token(scan);
+ if (nexttok != SWIG_TOKEN_RPAREN) {
+ Swig_error(Scanner_file(scan),Scanner_line(scan),"Syntax error. Bad operator name.\n");
} else {
- if (!sticky)
- Putc(' ', s);
- sticky = 1;
+ Append(s,"()");
+ yylval.str = s;
+ return OPERATOR;
}
- }
- Chop(s);
- if (swigtemplate_active && start_template && end_template) {
- /*
- Manage the case:
-
- %template(foo) operator();
-
- ie, don't count as part of the operator.
- */
- int len = Len(s);
- char *end = Char(s);
- int tlen = end_template - start_template + 1;
- int nlen = len - tlen;
- if (nlen) {
- String *ns = 0;
- while (isspace((unsigned char) end[--nlen]));
- ns = NewStringWithSize(s, nlen + 1);
- retract(count - start_template);
- Delete(s);
- s = ns;
- count = start_template;
- isconversion = 0;
+ } else if (nexttok == SWIG_TOKEN_LBRACKET) {
+ /* Array access operator. The next token MUST be a RBRACKET */
+ nexttok = Scanner_token(scan);
+ if (nexttok != SWIG_TOKEN_RBRACKET) {
+ Swig_error(Scanner_file(scan),Scanner_line(scan),"Syntax error. Bad operator name.\n");
+ } else {
+ Append(s,"[]");
+ yylval.str = s;
+ return OPERATOR;
}
- }
+ } else if (nexttok == SWIG_TOKEN_ID) {
+ /* We have an identifier. This could be any number of things. It could be a named version of
+ an operator (e.g., 'and_eq') or it could be a conversion operator. To deal with this, we're
+ going to read tokens until we encounter a ( or ;. Some care is needed for formatting. */
+ int needspace = 1;
+ int termtoken = 0;
+ const char *termvalue = 0;
- yylval.str = s;
- while (Replaceall(s, "[ ", "["));
- if (isconversion) {
- String *ns = Swig_symbol_string_qualify(s, 0);
- yylval.str = ns;
- }
- if (isconversion && !rename_active) {
- char *t = Char(s) + 9;
- if (!((strcmp(t, "new") == 0)
- || (strcmp(t, "delete") == 0)
- || (strcmp(t, "new[]") == 0)
- || (strcmp(t, "delete[]") == 0)
- || (strcmp(t, "and") == 0)
- || (strcmp(t, "and_eq") == 0)
- || (strcmp(t, "bitand") == 0)
- || (strcmp(t, "bitor") == 0)
- || (strcmp(t, "compl") == 0)
- || (strcmp(t, "not") == 0)
- || (strcmp(t, "not_eq") == 0)
- || (strcmp(t, "or") == 0)
- || (strcmp(t, "or_eq") == 0)
- || (strcmp(t, "xor") == 0)
- || (strcmp(t, "xor_eq") == 0)
- )) {
- /* retract(strlen(t)); */
- retract(count);
- return COPERATOR;
+ Append(s,Scanner_text(scan));
+ while (1) {
+
+ nexttok = Scanner_token(scan);
+ if (nexttok <= 0) {
+ Swig_error(Scanner_file(scan),Scanner_line(scan),"Syntax error. Bad operator name.\n");
+ }
+ if (nexttok == SWIG_TOKEN_LPAREN) {
+ termtoken = SWIG_TOKEN_LPAREN;
+ termvalue = "(";
+ break;
+ } else if (nexttok == SWIG_TOKEN_SEMI) {
+ termtoken = SWIG_TOKEN_SEMI;
+ termvalue = ";";
+ break;
+ } else if (nexttok == SWIG_TOKEN_ID) {
+ if (needspace) {
+ Append(s," ");
+ }
+ Append(s,Scanner_text(scan));
+ } else {
+ Append(s,Scanner_text(scan));
+ needspace = 0;
+ }
}
+ yylval.str = Swig_symbol_string_qualify(s,0);
+ /* Printf(stdout,"OPERATOR '%s'\n", yylval.str); */
+ if (!rename_active) {
+ String *cs;
+ char *t = Char(s) + 9;
+ if (!((strcmp(t, "new") == 0)
+ || (strcmp(t, "delete") == 0)
+ || (strcmp(t, "new[]") == 0)
+ || (strcmp(t, "delete[]") == 0)
+ || (strcmp(t, "and") == 0)
+ || (strcmp(t, "and_eq") == 0)
+ || (strcmp(t, "bitand") == 0)
+ || (strcmp(t, "bitor") == 0)
+ || (strcmp(t, "compl") == 0)
+ || (strcmp(t, "not") == 0)
+ || (strcmp(t, "not_eq") == 0)
+ || (strcmp(t, "or") == 0)
+ || (strcmp(t, "or_eq") == 0)
+ || (strcmp(t, "xor") == 0)
+ || (strcmp(t, "xor_eq") == 0)
+ )) {
+ /* retract(strlen(t)); */
+
+ /* The operator is a conversion operator. In order to deal with this, we need to feed the
+ type information back into the parser. For now this is a hack. Needs to be cleaned up later. */
+ cs = NewString(t);
+ if (termtoken) Append(cs,termvalue);
+ Seek(cs,0,SEEK_SET);
+ Setline(cs,cparse_line);
+ Setfile(cs,cparse_file);
+ Scanner_push(scan,cs);
+ Delete(cs);
+ return COPERATOR;
+ }
+ }
+ if (termtoken) Scanner_pushtoken(scan, termtoken, termvalue);
+ return (OPERATOR);
}
- return (OPERATOR);
}
if (strcmp(yytext, "throw") == 0)
return (THROW);
@@ -1448,28 +782,6 @@ int yylex(void) {
}
}
- /* Objective-C keywords */
-#ifdef OBJECTIVEC
- if ((ObjC) && (yytext[0] == '@')) {
- if (strcmp(yytext, "@interface") == 0)
- return (OC_INTERFACE);
- if (strcmp(yytext, "@end") == 0)
- return (OC_END);
- if (strcmp(yytext, "@public") == 0)
- return (OC_PUBLIC);
- if (strcmp(yytext, "@private") == 0)
- return (OC_PRIVATE);
- if (strcmp(yytext, "@protected") == 0)
- return (OC_PROTECTED);
- if (strcmp(yytext, "@class") == 0)
- return (OC_CLASS);
- if (strcmp(yytext, "@implementation") == 0)
- return (OC_IMPLEMENT);
- if (strcmp(yytext, "@protocol") == 0)
- return (OC_PROTOCOL);
- }
-#endif
-
/* Misc keywords */
if (strcmp(yytext, "extern") == 0)
@@ -1566,10 +878,8 @@ int yylex(void) {
if (strcmp(yytext, "%varargs") == 0)
return (VARARGS);
if (strcmp(yytext, "%template") == 0) {
- swigtemplate_active = 1;
return (SWIGTEMPLATE);
}
-
if (strcmp(yytext, "%warn") == 0)
return (WARN);
}
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index c216cd97f..1a13f010c 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -1547,9 +1547,8 @@ declaration : swig_directive { $$ = $1; }
| SEMI { $$ = 0; }
| error {
$$ = 0;
- if (!Swig_error_count()) {
- Swig_error(cparse_file, cparse_line,"Syntax error in input(1).\n");
- }
+ Swig_error(cparse_file, cparse_line,"Syntax error in input(1).\n");
+ exit(1);
}
/* Out of class constructor/destructor declarations */
| c_constructor_decl {
@@ -1864,13 +1863,11 @@ fragment_directive: FRAGMENT LPAREN fname COMMA kwargs RPAREN HBLOCK {
include_directive: includetype options string LBRACKET {
$1.filename = Swig_copy_string(cparse_file);
$1.line = cparse_line;
- cparse_file = Swig_copy_string($3);
- cparse_line = 0;
+ scanner_set_location($3,1);
} interface RBRACKET {
String *mname = 0;
$$ = $6;
- cparse_file = $1.filename;
- cparse_line = $1.line;
+ scanner_set_location($1.filename,$1.line);
if (strcmp($1.type,"include") == 0) set_nodeType($$,"include");
if (strcmp($1.type,"import") == 0) {
mname = $2 ? Getattr($2,"module") : 0;
@@ -3103,9 +3100,8 @@ c_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
}
}
if (err) {
- if (!Swig_error_count()) {
- Swig_error(cparse_file,cparse_line,"Syntax error in input(2).\n");
- }
+ Swig_error(cparse_file,cparse_line,"Syntax error in input(2).\n");
+ exit(1);
}
}
;
@@ -3954,12 +3950,11 @@ cpp_members : cpp_member cpp_members {
| error {
int start_line = cparse_line;
skip_decl();
- if (!Swig_error_count()) {
- Swig_error(cparse_file,start_line,"Syntax error in input(3).\n");
- }
- } cpp_members {
- $$ = $3;
- }
+ Swig_error(cparse_file,start_line,"Syntax error in input(3).\n");
+ exit(1);
+ } cpp_members {
+ $$ = $3;
+ }
;
/* ======================================================================
diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx
index 4889319d1..db4b9983e 100644
--- a/Source/Modules/main.cxx
+++ b/Source/Modules/main.cxx
@@ -81,6 +81,7 @@ static const char *usage2 = (const char *) "\
-importall - Follow all #include statements as imports\n\
-includeall - Follow all #include statements\n\
-l - Include SWIG library file \n\
+ -macroerrors - Report errors inside macros\n\
-makedefault - Create default constructors/destructors (the default)\n\
-M - List all dependencies\n\
-MD - Is equivalent to `-M -MF ', except `-E' is not implied\n\
@@ -502,6 +503,9 @@ void SWIG_getoptions(int argc, char *argv[]) {
} else if (strcmp(argv[i], "-notemplatereduce") == 0) {
SWIG_cparse_template_reduce(0);
Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-macroerrors") == 0) {
+ Swig_cparse_follow_locators(1);
+ Swig_mark_arg(i);
} else if (strcmp(argv[i], "-swiglib") == 0) {
if (SwigLibWin)
printf("%s\n", Char(SwigLibWin));
diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c
index e0c36a6f9..816fcd406 100644
--- a/Source/Preprocessor/cpp.c
+++ b/Source/Preprocessor/cpp.c
@@ -909,7 +909,10 @@ static String *expand_macro(String *name, List *args) {
#else
/* Use simplified around markers to properly count lines in cscanner.c */
if (strchr(Char(g), '\n')) {
+ Printf(f, "/*@SWIG:%s,%d,%s@*/%s/*@SWIG@*/", Getfile(macro), Getline(macro), name, g);
+#if 0
Printf(f, "/*@SWIG:%s@*/%s/*@SWIG@*/", name, g);
+#endif
} else {
Append(f, g);
}
diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c
index d41e0a1f4..a5000c445 100644
--- a/Source/Swig/scanner.c
+++ b/Source/Swig/scanner.c
@@ -22,12 +22,12 @@ struct Scanner {
char *idstart; /* Optional identifier start characters */
int nexttoken; /* Next token to be returned */
int start_line; /* Starting line of certain declarations */
- int string_start;
int line;
int yylen; /* Length of text pushed into text */
String *file;
String *error; /* Last error message (if any) */
int error_line; /* Error line number */
+ int freeze_line; /* Suspend line number updates */
};
/* -----------------------------------------------------------------------------
@@ -43,13 +43,13 @@ Scanner *NewScanner() {
s->file = 0;
s->nexttoken = -1;
s->start_line = 1;
- s->string_start = 0;
s->yylen = 0;
s->idstart = "";
s->scanobjs = NewList();
s->text = NewStringEmpty();
s->str = 0;
s->error = 0;
+ s->freeze_line = 0;
return s;
}
@@ -85,7 +85,6 @@ void Scanner_clear(Scanner * s) {
s->line = 1;
s->nexttoken = -1;
s->start_line = 0;
- s->string_start = 0;
s->yylen = 0;
}
@@ -99,8 +98,10 @@ void Scanner_clear(Scanner * s) {
void Scanner_push(Scanner * s, String *txt) {
assert(s && txt);
Push(s->scanobjs, txt);
- if (s->str)
+ if (s->str) {
+ Setline(s->str,s->line);
Delete(s->str);
+ }
s->str = txt;
DohIncref(s->str);
s->line = Getline(txt);
@@ -113,12 +114,14 @@ void Scanner_push(Scanner * s, String *txt) {
* call to Scanner_token().
* ----------------------------------------------------------------------------- */
-void Scanner_pushtoken(Scanner * s, int nt, String_or_char *val) {
+void Scanner_pushtoken(Scanner * s, int nt, const String_or_char *val) {
assert(s);
assert((nt >= 0) && (nt < SWIG_MAXTOKENS));
s->nexttoken = nt;
- Clear(s->text);
- Append(s->text,val);
+ if (val != s->text) {
+ Clear(s->text);
+ Append(s->text,val);
+ }
}
/* -----------------------------------------------------------------------------
@@ -130,25 +133,35 @@ void Scanner_pushtoken(Scanner * s, int nt, String_or_char *val) {
void Scanner_set_location(Scanner * s, String *file, int line) {
Setline(s->str, line);
Setfile(s->str, file);
+ s->line = line;
}
/* -----------------------------------------------------------------------------
- * Scanner_get_file()
+ * Scanner_file()
*
* Get the current file.
* ----------------------------------------------------------------------------- */
-String *Scanner_get_file(Scanner * s) {
+String *Scanner_file(Scanner * s) {
return Getfile(s->str);
}
/* -----------------------------------------------------------------------------
- * Scanner_get_line()
+ * Scanner_line()
*
* Get the current line number
* ----------------------------------------------------------------------------- */
-int Scanner_get_line(Scanner * s) {
- return Getline(s->str);
+int Scanner_line(Scanner * s) {
+ return s->line;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_start_line()
+ *
+ * Get the line number on which the current token starts
+ * ----------------------------------------------------------------------------- */
+int Scanner_start_line(Scanner * s) {
+ return s->start_line;
}
/* -----------------------------------------------------------------------------
@@ -167,7 +180,6 @@ void Scanner_idstart(Scanner * s, char *id) {
* Returns the next character from the scanner or 0 if end of the string.
* ----------------------------------------------------------------------------- */
static char nextchar(Scanner * s) {
- char c[2] = { 0, 0 };
int nc;
if (!s->str)
return 0;
@@ -183,12 +195,10 @@ static char nextchar(Scanner * s) {
DohIncref(s->str);
}
}
- if (nc == '\n')
+ if ((nc == '\n') && (!s->freeze_line))
s->line++;
- c[0] = (char) nc;
- c[1] = 0;
- Append(s->text, c);
- return c[0];
+ Putc(nc,s->text);
+ return nc;
}
/* -----------------------------------------------------------------------------
@@ -219,6 +229,17 @@ Scanner_errline(Scanner *s) {
return s->error_line;
}
+/* -----------------------------------------------------------------------------
+ * Scanner_freeze_line()
+ *
+ * Freezes the current line number.
+ * ----------------------------------------------------------------------------- */
+
+void
+Scanner_freeze_line(Scanner *s, int val) {
+ s->freeze_line = val;
+}
+
/* -----------------------------------------------------------------------------
* retract()
*
@@ -233,7 +254,7 @@ static void retract(Scanner * s, int n) {
assert(n <= l);
for (i = 0; i < n; i++) {
if (str[l - 1] == '\n') {
- s->line--;
+ if (!s->freeze_line) s->line--;
}
Seek(s->str, -1, SEEK_CUR);
Delitem(s->text, DOH_END);
@@ -335,11 +356,8 @@ static void get_escape(Scanner *s) {
break;
case 10:
if (!isdigit(c)) {
- char tmp[2];
retract(s,1);
- tmp[0] = (char) result;
- tmp[1] = 0;
- Append(s->text, tmp);
+ Putc((char)result,s->text);
return;
}
result = (result << 3) + (c - '0');
@@ -347,11 +365,8 @@ static void get_escape(Scanner *s) {
break;
case 20:
if (!isxdigit(c)) {
- char tmp[2];
retract(s,1);
- tmp[0] = (char) result;
- tmp[1] = 0;
- Append(s->text,tmp);
+ Putc((char)result, s->text);
return;
}
if (isdigit(c))
@@ -374,11 +389,10 @@ static void get_escape(Scanner *s) {
static int look(Scanner * s) {
int state;
int c = 0;
- int comment_start = 0;
state = 0;
Clear(s->text);
- Setline(s->text, Getline(s->str));
+ s->start_line = s->line;
Setfile(s->text, Getfile(s->str));
while (1) {
switch (state) {
@@ -394,7 +408,7 @@ static int look(Scanner * s) {
retract(s, 1);
state = 1000;
Clear(s->text);
- Setline(s->text, Getline(s->str));
+ Setline(s->text, s->line);
Setfile(s->text, Getfile(s->str));
}
break;
@@ -455,7 +469,7 @@ static int look(Scanner * s) {
else if (c == '@')
return SWIG_TOKEN_AT;
else if (c == '$')
- return SWIG_TOKEN_DOLLAR;
+ state = 75;
else if (c == '#')
return SWIG_TOKEN_POUND;
else if (c == '?')
@@ -465,11 +479,12 @@ static int look(Scanner * s) {
else if (c == '/') {
state = 1; /* Comment (maybe) */
- comment_start = s->line;
+ s->start_line = s->line;
}
else if (c == '\"') {
state = 2; /* Possibly a string */
- s->string_start = s->line;
+ s->start_line = s->line;
+ Clear(s->text);
}
else if (c == ':')
@@ -477,10 +492,12 @@ static int look(Scanner * s) {
else if (c == '0')
state = 83; /* An octal or hex value */
else if (c == '\'') {
- s->string_start = s->line;
+ s->start_line = s->line;
+ Clear(s->text);
state = 9; /* A character constant */
} else if (c == '`') {
- s->string_start = s->line;
+ s->start_line = s->line;
+ Clear(s->text);
state = 900;
}
@@ -516,7 +533,7 @@ static int look(Scanner * s) {
break;
case 10: /* C++ style comment */
if ((c = nextchar(s)) == 0) {
- set_error(s,comment_start,"Unterminated comment");
+ set_error(s,s->start_line,"Unterminated comment");
return SWIG_TOKEN_ERROR;
}
if (c == '\n') {
@@ -528,7 +545,7 @@ static int look(Scanner * s) {
break;
case 11: /* C style comment block */
if ((c = nextchar(s)) == 0) {
- set_error(s,comment_start,"Unterminated comment");
+ set_error(s,s->start_line,"Unterminated comment");
return SWIG_TOKEN_ERROR;
}
if (c == '*') {
@@ -539,7 +556,7 @@ static int look(Scanner * s) {
break;
case 12: /* Still in C style comment */
if ((c = nextchar(s)) == 0) {
- set_error(s,comment_start,"Unterminated comment");
+ set_error(s,s->start_line,"Unterminated comment");
return SWIG_TOKEN_ERROR;
}
if (c == '*') {
@@ -553,12 +570,14 @@ static int look(Scanner * s) {
case 2: /* Processing a string */
if ((c = nextchar(s)) == 0) {
- set_error(s,s->string_start, "Unterminated string");
+ set_error(s,s->start_line, "Unterminated string");
return SWIG_TOKEN_ERROR;
}
if (c == '\"') {
+ Delitem(s->text, DOH_END);
return SWIG_TOKEN_STRING;
} else if (c == '\\') {
+ Delitem(s->text, DOH_END);
get_escape(s);
} else
state = 2;
@@ -647,6 +666,7 @@ static int look(Scanner * s) {
if (c == '}') {
Delitem(s->text, DOH_END);
Delitem(s->text, DOH_END);
+ Seek(s->text,0,SEEK_SET);
return SWIG_TOKEN_CODEBLOCK;
} else {
state = 40;
@@ -710,6 +730,19 @@ static int look(Scanner * s) {
return SWIG_TOKEN_ID;
}
break;
+
+ case 75: /* Special identifier $ */
+ if ((c = nextchar(s)) == 0)
+ return SWIG_TOKEN_DOLLAR;
+ if (isalnum(c) || (c == '_') || (c == '*') || (c == '&')) {
+ state = 7;
+ } else {
+ retract(s,1);
+ if (Len(s->text) == 1) return SWIG_TOKEN_DOLLAR;
+ return SWIG_TOKEN_ID;
+ }
+ break;
+
case 8: /* A numerical digit */
if ((c = nextchar(s)) == 0)
return SWIG_TOKEN_INT;
@@ -880,12 +913,14 @@ static int look(Scanner * s) {
/* A character constant */
case 9:
if ((c = nextchar(s)) == 0) {
- set_error(s,s->string_start,"Unterminated character constant");
+ set_error(s,s->start_line,"Unterminated character constant");
return SWIG_TOKEN_ERROR;
}
if (c == '\'') {
+ Delitem(s->text, DOH_END);
return (SWIG_TOKEN_CHAR);
} else if (c == '\\') {
+ Delitem(s->text, DOH_END);
get_escape(s);
}
break;
@@ -919,7 +954,7 @@ static int look(Scanner * s) {
case 210: /* MINUS, MINUSMINUS, MINUSEQUAL, ARROW */
if ((c = nextchar(s)) == 0)
return SWIG_TOKEN_MINUS;
- else if (c == '+')
+ else if (c == '-')
return SWIG_TOKEN_MINUSMINUS;
else if (c == '=')
return SWIG_TOKEN_MINUSEQUAL;
@@ -993,10 +1028,11 @@ static int look(Scanner * s) {
/* Reverse string */
case 900:
if ((c = nextchar(s)) == 0) {
- set_error(s,s->string_start,"Unterminated character constant");
+ set_error(s,s->start_line,"Unterminated character constant");
return SWIG_TOKEN_ERROR;
}
if (c == '`') {
+ Delitem(s->text, DOH_END);
return (SWIG_TOKEN_RSTRING);
}
break;
@@ -1021,8 +1057,13 @@ int Scanner_token(Scanner * s) {
s->nexttoken = -1;
return t;
}
- Clear(s->text);
+ s->start_line = 0;
t = look(s);
+ if (!s->start_line) {
+ Setline(s->text,s->line);
+ } else {
+ Setline(s->text,s->start_line);
+ }
return t;
}
@@ -1047,14 +1088,15 @@ void Scanner_skip_line(Scanner * s) {
int done = 0;
Clear(s->text);
Setfile(s->text, Getfile(s->str));
- Setline(s->text, Getline(s->str));
+ Setline(s->text, s->line);
while (!done) {
if ((c = nextchar(s)) == 0)
return;
- if (c == '\\')
+ if (c == '\\') {
c = nextchar(s);
- else if (c == '\n')
+ } else if (c == '\n') {
done = 1;
+ }
}
return;
}
@@ -1076,7 +1118,7 @@ int Scanner_skip_balanced(Scanner * s, int startchar, int endchar) {
temp[0] = (char) startchar;
Clear(s->text);
Setfile(s->text, Getfile(s->str));
- Setline(s->text, Getline(s->str));
+ Setline(s->text, s->line);
Append(s->text, temp);
while (num_levels > 0) {
diff --git a/Source/Swig/swigscan.h b/Source/Swig/swigscan.h
index 49ed99763..88ce95636 100644
--- a/Source/Swig/swigscan.h
+++ b/Source/Swig/swigscan.h
@@ -15,18 +15,20 @@ extern Scanner *NewScanner();
extern void DelScanner(Scanner *);
extern void Scanner_clear(Scanner *);
extern void Scanner_push(Scanner *, String *);
-extern void Scanner_pushtoken(Scanner *, int, String_or_char *value);
+extern void Scanner_pushtoken(Scanner *, int, const String_or_char *value);
extern int Scanner_token(Scanner *);
extern String *Scanner_text(Scanner *);
extern void Scanner_skip_line(Scanner *);
extern int Scanner_skip_balanced(Scanner *, int startchar, int endchar);
extern void Scanner_set_location(Scanner *, String *file, int line);
-extern String *Scanner_get_file(Scanner *);
-extern int Scanner_get_line(Scanner *);
+extern String *Scanner_file(Scanner *);
+extern int Scanner_line(Scanner *);
+extern int Scanner_start_line(Scanner *);
extern void Scanner_idstart(Scanner *, char *idchar);
extern String *Scanner_errmsg(Scanner *);
extern int Scanner_errline(Scanner *);
extern int Scanner_isoperator(int tokval);
+extern void Scanner_freeze_line(Scanner *s, int val);
/* Note: Tokens in range 100+ are for C/C++ operators */