https://swig.svn.sourceforge.net/svnroot/swig/trunk ........ r10498 | talby | 2008-05-26 22:09:56 +0200 (Pn, 26 maj 2008) | 2 lines run test cases in the Perl set by the --with-perl5 configure option. ........ r10499 | talby | 2008-05-26 23:04:06 +0200 (Pn, 26 maj 2008) | 3 lines The perl5 minherit runtime test will work better if the classes are actually built under SWIGPERL. ........ r10503 | wsfulton | 2008-05-28 11:44:37 +0200 (Śr, 28 maj 2008) | 1 line Fix variable wrappers when using -proxy. Patch from Jan Jezabek ........ r10504 | bhy | 2008-05-28 19:27:48 +0200 (Śr, 28 maj 2008) | 2 lines Fixed SF #1971977: typo in pycontainer.swg (related to -extranative option) ........ r10506 | wsfulton | 2008-05-29 02:45:28 +0200 (Cz, 29 maj 2008) | 1 line Fix variable wrappers when using -noproxy ........ r10508 | bhy | 2008-05-30 15:53:33 +0200 (Pt, 30 maj 2008) | 1 line Fixed SF #1976978, apply the macros for primitive types to std::wstring ........ r10511 | olly | 2008-05-30 18:11:27 +0200 (Pt, 30 maj 2008) | 4 lines Fix typo in handling of /*@SWIG[...]*/ comments in the scanner. This just meant we were only actually looking for /*@SWI at the start of the comment, so was pretty harmless in practice. ........ r10515 | wsfulton | 2008-06-02 22:10:40 +0200 (Pn, 02 cze 2008) | 1 line Fix samename testcase for c# and java ........ r10516 | wsfulton | 2008-06-02 22:15:39 +0200 (Pn, 02 cze 2008) | 1 line Fix enums when using -noproxy ........ r10518 | bhy | 2008-06-07 13:20:07 +0200 (So, 07 cze 2008) | 4 lines Added a test case for keyword renaming. Now it works for Python in SWIG's -c++ mode, but in C mode it doesn't work! (you can try with make keyword_rename.ctest) ........ r10519 | bhy | 2008-06-07 15:40:51 +0200 (So, 07 cze 2008) | 1 line fixed keyword_rename.ctest tese case, caused by a mistake in Swig/naming.c ........ r10527 | mgossage | 2008-06-17 04:57:15 +0200 (Wt, 17 cze 2008) | 1 line [lua] bugfix 1938142 (bool& and bool* support) ........ r10530 | wsfulton | 2008-06-19 22:02:13 +0200 (Cz, 19 cze 2008) | 1 line Add R keyword support. Rename keywords for successful compilation of Java and C# code. More consistent keyword warnings across the different languages. ........ r10531 | wsfulton | 2008-06-19 23:15:48 +0200 (Cz, 19 cze 2008) | 1 line add complete list of R reserved words ........ r10536 | wsfulton | 2008-06-21 13:35:33 +0200 (So, 21 cze 2008) | 1 line better terminology for static types ........ r10537 | wsfulton | 2008-06-21 13:42:48 +0200 (So, 21 cze 2008) | 1 line remove raise as keyword test- it conflicts with _raise in LIBCMT on windows ........ r10539 | wsfulton | 2008-06-21 17:21:29 +0200 (So, 21 cze 2008) | 1 line Lua example warning removal fixes for vc++ ........ r10540 | wsfulton | 2008-06-21 17:23:02 +0200 (So, 21 cze 2008) | 1 line Remove some vc++ /W4 warnings ........ r10541 | wsfulton | 2008-06-21 18:04:55 +0200 (So, 21 cze 2008) | 1 line minor vc++ /W4 warning fixes ........ r10542 | wsfulton | 2008-06-21 21:07:51 +0200 (So, 21 cze 2008) | 1 line 'byte' is already used in Ruby on windows, so use another keyword ........ r10543 | wsfulton | 2008-06-21 22:45:32 +0200 (So, 21 cze 2008) | 1 line Fix crashing in the Ruby reject method in the STL wrappers ........ r10544 | wsfulton | 2008-06-21 22:48:28 +0200 (So, 21 cze 2008) | 1 line Fix crashing in the Ruby reject method in the STL wrappers ........ r10545 | wsfulton | 2008-06-21 22:49:10 +0200 (So, 21 cze 2008) | 1 line remove unnecessary variable int the char **STRING_ARRAY out typemap ........ r10546 | wsfulton | 2008-06-21 23:07:49 +0200 (So, 21 cze 2008) | 1 line Fix Ruby C++ example dependencies in dsp files ........ r10547 | wsfulton | 2008-06-22 00:25:36 +0200 (N, 22 cze 2008) | 1 line Fix unused parameter warnings in python when using gcc's -W -Wall options ........ r10548 | wsfulton | 2008-06-22 00:26:35 +0200 (N, 22 cze 2008) | 1 line Fix virtual destructor ........ r10549 | wsfulton | 2008-06-22 01:25:20 +0200 (N, 22 cze 2008) | 1 line various warning fixes ........ r10550 | wsfulton | 2008-06-22 02:09:11 +0200 (N, 22 cze 2008) | 1 line Another fix for the JVM hanging on exit problem when using directors ........ r10551 | wsfulton | 2008-06-22 02:09:51 +0200 (N, 22 cze 2008) | 1 line documentation sections update ........ r10552 | wsfulton | 2008-06-22 02:18:10 +0200 (N, 22 cze 2008) | 1 line more docs on defining macros for the thread hanging problem ........ r10558 | wsfulton | 2008-06-22 23:30:20 +0200 (N, 22 cze 2008) | 1 line fix unused parms in last commit for C code ........ r10559 | wsfulton | 2008-06-23 00:12:43 +0200 (Pn, 23 cze 2008) | 1 line Suppress unused methods warning for VC++ ........ r10560 | wsfulton | 2008-06-23 22:26:07 +0200 (Pn, 23 cze 2008) | 1 line fix partialcheck-test-suite and parallel make for r, chicken, tcl and php ........ r10561 | wsfulton | 2008-06-23 22:39:41 +0200 (Pn, 23 cze 2008) | 1 line correct message display when running the partialcheck-test-suite make target ........ r10562 | wsfulton | 2008-06-23 23:14:53 +0200 (Pn, 23 cze 2008) | 1 line fix typo ........ r10563 | olly | 2008-06-23 23:23:54 +0200 (Pn, 23 cze 2008) | 3 lines Fix bad use of Python API (untested, since I can't even compile this code on x86-64!) ........ r10564 | olly | 2008-06-24 00:58:03 +0200 (Wt, 24 cze 2008) | 3 lines [PHP] Fix segfault when wrapping a non-class function marked with %newobject (testcase char_strings). ........ r10565 | olly | 2008-06-24 02:27:34 +0200 (Wt, 24 cze 2008) | 3 lines [PHP] Fix assertion failure when handling %typemap(in,numinputs=0) (testcase ignore_parameter). ........ r10566 | olly | 2008-06-24 02:33:08 +0200 (Wt, 24 cze 2008) | 2 lines [PHP] Fix typemap_namespace.i to not try to copy a non-existent typemap. ........ r10567 | olly | 2008-06-24 02:41:07 +0200 (Wt, 24 cze 2008) | 3 lines Clean up dead and unused code in SwigToPhpType(), and rename to GetShadowReturnType(). ........ r10568 | olly | 2008-06-24 02:42:29 +0200 (Wt, 24 cze 2008) | 2 lines Fix cosmetic typo in string constant. ........ r10574 | wsfulton | 2008-06-24 22:10:28 +0200 (Wt, 24 cze 2008) | 1 line zap last entry ........ r10575 | wsfulton | 2008-06-24 22:11:46 +0200 (Wt, 24 cze 2008) | 1 line variable name changes to remove php keywords ........ r10576 | wsfulton | 2008-06-24 22:12:08 +0200 (Wt, 24 cze 2008) | 1 line variable name hiding fix ........ r10577 | wsfulton | 2008-06-24 22:12:43 +0200 (Wt, 24 cze 2008) | 1 line More info about numobjects added ........ r10578 | wsfulton | 2008-06-24 22:13:41 +0200 (Wt, 24 cze 2008) | 1 line update for 1.3.36 release ........ r10579 | wsfulton | 2008-06-24 23:48:46 +0200 (Wt, 24 cze 2008) | 1 line remove deprecated -c commandline option (runtime library generation) ........ r10580 | wsfulton | 2008-06-24 23:53:12 +0200 (Wt, 24 cze 2008) | 1 line correct comment about deprecated option ........ r10582 | wsfulton | 2008-06-25 01:00:27 +0200 (Śr, 25 cze 2008) | 1 line use rsync and ssh to upload releases to SourceForge as ftp no longer works ........ r10584 | wsfulton | 2008-06-25 01:24:48 +0200 (Śr, 25 cze 2008) | 1 line correction for 1.3.36 ........ r10588 | wsfulton | 2008-06-25 02:16:04 +0200 (Śr, 25 cze 2008) | 1 line section update ........ r10589 | wsfulton | 2008-06-25 02:16:40 +0200 (Śr, 25 cze 2008) | 1 line bump version to 1.3.37 ........ r10594 | wsfulton | 2008-06-26 20:33:06 +0200 (Cz, 26 cze 2008) | 1 line correct typo in first entry about %fragment ........ git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2008-maciekd@10606 626c5289-ae23-0410-ae9c-e8d60b6d4f22
903 lines
24 KiB
C
903 lines
24 KiB
C
/* -----------------------------------------------------------------------------
|
|
* See the LICENSE file for information on copyright, usage and redistribution
|
|
* of SWIG, and the README file for authors - http://www.swig.org/release.html.
|
|
*
|
|
* scanner.c
|
|
*
|
|
* 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$";
|
|
|
|
#include "cparse.h"
|
|
#include "parser.h"
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
/* Scanner object */
|
|
static Scanner *scan = 0;
|
|
|
|
/* Global string containing C code. Used by the parser to grab code blocks */
|
|
DOHString *scanner_ccode = 0;
|
|
|
|
/* Error reporting/location information */
|
|
int cparse_line = 1;
|
|
String *cparse_file = 0;
|
|
int cparse_start_line = 0;
|
|
|
|
/* C++ mode */
|
|
int cparse_cplusplus = 0;
|
|
|
|
/* 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 expanding_macro = 0;
|
|
static int follow_locators = 0;
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_cparse_cplusplus()
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void Swig_cparse_cplusplus(int v) {
|
|
cparse_cplusplus = v;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
* locator()
|
|
*
|
|
* Support for locator strings. These are strings of the form
|
|
* @SWIG:filename,line,id@ emitted by the SWIG preprocessor. They
|
|
* are primarily used for macro line number reporting
|
|
* ---------------------------------------------------------------------- */
|
|
|
|
typedef struct Locator {
|
|
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) {
|
|
if (!follow_locators) {
|
|
if (Equal(loc, "/*@SWIG@*/")) {
|
|
/* End locator. */
|
|
if (expanding_macro)
|
|
--expanding_macro;
|
|
} else {
|
|
/* Begin locator. */
|
|
++expanding_macro;
|
|
}
|
|
/* 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;
|
|
}
|
|
|
|
/* 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);
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Swig_cparse_follow_locators(int v) {
|
|
follow_locators = v;
|
|
}
|
|
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* scanner_init()
|
|
*
|
|
* Initialize buffers
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
void scanner_init() {
|
|
scan = NewScanner();
|
|
Scanner_idstart(scan,"%");
|
|
scan_init = 1;
|
|
scanner_ccode = NewStringEmpty();
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* scanner_file(DOHFile *f)
|
|
*
|
|
* Start reading from new file
|
|
* ------------------------------------------------------------------------- */
|
|
void scanner_file(DOHFile * f) {
|
|
if (!scan_init) scanner_init();
|
|
Scanner_clear(scan);
|
|
Scanner_push(scan,f);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* start_inline(char *text, int line)
|
|
*
|
|
* 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) {
|
|
String *stext = NewString(text);
|
|
|
|
Seek(stext,0,SEEK_SET);
|
|
Setfile(stext,cparse_file);
|
|
Setline(stext,line);
|
|
Scanner_push(scan,stext);
|
|
Delete(stext);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* skip_balanced()
|
|
*
|
|
* Skips a piece of code enclosed in begin/end symbols such as '{...}' or
|
|
* (...). Ignores symbols inside comments or strings.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void skip_balanced(int startchar, int endchar) {
|
|
Clear(scanner_ccode);
|
|
|
|
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;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* void skip_decl(void)
|
|
*
|
|
* This tries to skip over an entire declaration. For example
|
|
*
|
|
* friend ostream& operator<<(ostream&, const char *s);
|
|
*
|
|
* or
|
|
* friend ostream& operator<<(ostream&, const char *s) { };
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
void skip_decl(void) {
|
|
int tok;
|
|
int done = 0;
|
|
int start_line = Scanner_line(scan);
|
|
|
|
while (!done) {
|
|
tok = Scanner_token(scan);
|
|
if (tok == 0) {
|
|
if (!Swig_error_count()) {
|
|
Swig_error(cparse_file, start_line, "Missing semicolon. Reached end of input.\n");
|
|
}
|
|
return;
|
|
}
|
|
if (tok == SWIG_TOKEN_LBRACE) {
|
|
if (Scanner_skip_balanced(scan,'{','}') < 0) {
|
|
Swig_error(cparse_file, start_line, "Missing '}'. Reached end of input.\n");
|
|
}
|
|
break;
|
|
}
|
|
if (tok == SWIG_TOKEN_SEMI) {
|
|
done = 1;
|
|
}
|
|
}
|
|
cparse_file = Scanner_file(scan);
|
|
cparse_line = Scanner_line(scan);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* int yylook()
|
|
*
|
|
* Lexical scanner.
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
int yylook(void) {
|
|
|
|
int tok = 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);
|
|
|
|
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 {
|
|
return RBRACE;
|
|
}
|
|
break;
|
|
case SWIG_TOKEN_LBRACE:
|
|
last_brace = num_brace;
|
|
num_brace++;
|
|
return LBRACE;
|
|
case SWIG_TOKEN_EQUAL:
|
|
return EQUAL;
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
/* 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",7) == 0) && (loc[Len(cmt)-3] == '@')) {
|
|
scanner_locator(cmt);
|
|
}
|
|
}
|
|
break;
|
|
case SWIG_TOKEN_ENDLINE:
|
|
break;
|
|
case SWIG_TOKEN_BACKSLASH:
|
|
break;
|
|
default:
|
|
Swig_error(cparse_file, cparse_line, "Illegal token '%s'.\n", Scanner_text(scan));
|
|
return (ILLEGAL);
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void scanner_ignore_typedef() {
|
|
check_typedef = 0;
|
|
}
|
|
|
|
void scanner_last_id(int x) {
|
|
last_id = x;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* int yylex()
|
|
*
|
|
* Gets the lexene and returns tokens.
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
int yylex(void) {
|
|
|
|
int l;
|
|
char *yytext;
|
|
|
|
if (!scan_init) {
|
|
scanner_init();
|
|
}
|
|
|
|
if (next_token) {
|
|
l = next_token;
|
|
next_token = 0;
|
|
return l;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/* We got some sort of non-white space object. We set the start_line
|
|
variable unless it has already been set */
|
|
|
|
if (!cparse_start_line) {
|
|
cparse_start_line = cparse_line;
|
|
}
|
|
|
|
/* Copy the lexene */
|
|
|
|
switch (l) {
|
|
|
|
case NUM_INT:
|
|
case NUM_FLOAT:
|
|
case NUM_ULONG:
|
|
case NUM_LONG:
|
|
case NUM_UNSIGNED:
|
|
case NUM_LONGLONG:
|
|
case NUM_ULONGLONG:
|
|
if (l == NUM_INT)
|
|
yylval.dtype.type = T_INT;
|
|
if (l == NUM_FLOAT)
|
|
yylval.dtype.type = T_DOUBLE;
|
|
if (l == NUM_ULONG)
|
|
yylval.dtype.type = T_ULONG;
|
|
if (l == NUM_LONG)
|
|
yylval.dtype.type = T_LONG;
|
|
if (l == NUM_UNSIGNED)
|
|
yylval.dtype.type = T_UINT;
|
|
if (l == NUM_LONGLONG)
|
|
yylval.dtype.type = T_LONGLONG;
|
|
if (l == NUM_ULONGLONG)
|
|
yylval.dtype.type = T_ULONGLONG;
|
|
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 */
|
|
|
|
if (strcmp(yytext, "int") == 0) {
|
|
yylval.type = NewSwigType(T_INT);
|
|
return (TYPE_INT);
|
|
}
|
|
if (strcmp(yytext, "double") == 0) {
|
|
yylval.type = NewSwigType(T_DOUBLE);
|
|
return (TYPE_DOUBLE);
|
|
}
|
|
if (strcmp(yytext, "void") == 0) {
|
|
yylval.type = NewSwigType(T_VOID);
|
|
return (TYPE_VOID);
|
|
}
|
|
if (strcmp(yytext, "char") == 0) {
|
|
yylval.type = NewSwigType(T_CHAR);
|
|
return (TYPE_CHAR);
|
|
}
|
|
if (strcmp(yytext, "wchar_t") == 0) {
|
|
yylval.type = NewSwigType(T_WCHAR);
|
|
return (TYPE_WCHAR);
|
|
}
|
|
if (strcmp(yytext, "short") == 0) {
|
|
yylval.type = NewSwigType(T_SHORT);
|
|
return (TYPE_SHORT);
|
|
}
|
|
if (strcmp(yytext, "long") == 0) {
|
|
yylval.type = NewSwigType(T_LONG);
|
|
return (TYPE_LONG);
|
|
}
|
|
if (strcmp(yytext, "float") == 0) {
|
|
yylval.type = NewSwigType(T_FLOAT);
|
|
return (TYPE_FLOAT);
|
|
}
|
|
if (strcmp(yytext, "signed") == 0) {
|
|
yylval.type = NewSwigType(T_INT);
|
|
return (TYPE_SIGNED);
|
|
}
|
|
if (strcmp(yytext, "unsigned") == 0) {
|
|
yylval.type = NewSwigType(T_UINT);
|
|
return (TYPE_UNSIGNED);
|
|
}
|
|
if (strcmp(yytext, "bool") == 0) {
|
|
yylval.type = NewSwigType(T_BOOL);
|
|
return (TYPE_BOOL);
|
|
}
|
|
|
|
/* Non ISO (Windows) C extensions */
|
|
if (strcmp(yytext, "__int8") == 0) {
|
|
yylval.type = NewString(yytext);
|
|
return (TYPE_NON_ISO_INT8);
|
|
}
|
|
if (strcmp(yytext, "__int16") == 0) {
|
|
yylval.type = NewString(yytext);
|
|
return (TYPE_NON_ISO_INT16);
|
|
}
|
|
if (strcmp(yytext, "__int32") == 0) {
|
|
yylval.type = NewString(yytext);
|
|
return (TYPE_NON_ISO_INT32);
|
|
}
|
|
if (strcmp(yytext, "__int64") == 0) {
|
|
yylval.type = NewString(yytext);
|
|
return (TYPE_NON_ISO_INT64);
|
|
}
|
|
|
|
/* C++ keywords */
|
|
if (cparse_cplusplus) {
|
|
if (strcmp(yytext, "and") == 0)
|
|
return (LAND);
|
|
if (strcmp(yytext, "or") == 0)
|
|
return (LOR);
|
|
if (strcmp(yytext, "not") == 0)
|
|
return (LNOT);
|
|
if (strcmp(yytext, "class") == 0)
|
|
return (CLASS);
|
|
if (strcmp(yytext, "private") == 0)
|
|
return (PRIVATE);
|
|
if (strcmp(yytext, "public") == 0)
|
|
return (PUBLIC);
|
|
if (strcmp(yytext, "protected") == 0)
|
|
return (PROTECTED);
|
|
if (strcmp(yytext, "friend") == 0)
|
|
return (FRIEND);
|
|
if (strcmp(yytext, "virtual") == 0)
|
|
return (VIRTUAL);
|
|
if (strcmp(yytext, "operator") == 0) {
|
|
int nexttok;
|
|
String *s = NewString("operator ");
|
|
|
|
/* 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 {
|
|
Append(s,"()");
|
|
yylval.str = s;
|
|
return OPERATOR;
|
|
}
|
|
} 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;
|
|
|
|
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 = s;
|
|
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);
|
|
}
|
|
}
|
|
if (strcmp(yytext, "throw") == 0)
|
|
return (THROW);
|
|
if (strcmp(yytext, "try") == 0)
|
|
return (yylex());
|
|
if (strcmp(yytext, "catch") == 0)
|
|
return (CATCH);
|
|
if (strcmp(yytext, "inline") == 0)
|
|
return (yylex());
|
|
if (strcmp(yytext, "mutable") == 0)
|
|
return (yylex());
|
|
if (strcmp(yytext, "explicit") == 0)
|
|
return (EXPLICIT);
|
|
if (strcmp(yytext, "export") == 0)
|
|
return (yylex());
|
|
if (strcmp(yytext, "typename") == 0)
|
|
return (TYPENAME);
|
|
if (strcmp(yytext, "template") == 0) {
|
|
yylval.ivalue = cparse_line;
|
|
return (TEMPLATE);
|
|
}
|
|
if (strcmp(yytext, "delete") == 0) {
|
|
return (DELETE_KW);
|
|
}
|
|
if (strcmp(yytext, "using") == 0) {
|
|
return (USING);
|
|
}
|
|
if (strcmp(yytext, "namespace") == 0) {
|
|
return (NAMESPACE);
|
|
}
|
|
} else {
|
|
if (strcmp(yytext, "class") == 0) {
|
|
Swig_warning(WARN_PARSE_CLASS_KEYWORD, cparse_file, cparse_line, "class keyword used, but not in C++ mode.\n");
|
|
}
|
|
if (strcmp(yytext, "complex") == 0) {
|
|
yylval.type = NewSwigType(T_COMPLEX);
|
|
return (TYPE_COMPLEX);
|
|
}
|
|
if (strcmp(yytext, "restrict") == 0)
|
|
return (yylex());
|
|
}
|
|
|
|
/* Misc keywords */
|
|
|
|
if (strcmp(yytext, "extern") == 0)
|
|
return (EXTERN);
|
|
if (strcmp(yytext, "const") == 0)
|
|
return (CONST_QUAL);
|
|
if (strcmp(yytext, "static") == 0)
|
|
return (STATIC);
|
|
if (strcmp(yytext, "struct") == 0)
|
|
return (STRUCT);
|
|
if (strcmp(yytext, "union") == 0)
|
|
return (UNION);
|
|
if (strcmp(yytext, "enum") == 0)
|
|
return (ENUM);
|
|
if (strcmp(yytext, "sizeof") == 0)
|
|
return (SIZEOF);
|
|
|
|
if (strcmp(yytext, "typedef") == 0) {
|
|
yylval.ivalue = 0;
|
|
return (TYPEDEF);
|
|
}
|
|
|
|
/* Ignored keywords */
|
|
|
|
if (strcmp(yytext, "volatile") == 0)
|
|
return (VOLATILE);
|
|
if (strcmp(yytext, "register") == 0)
|
|
return (REGISTER);
|
|
if (strcmp(yytext, "inline") == 0)
|
|
return (yylex());
|
|
|
|
/* SWIG directives */
|
|
} else {
|
|
if (strcmp(yytext, "%module") == 0)
|
|
return (MODULE);
|
|
if (strcmp(yytext, "%insert") == 0)
|
|
return (INSERT);
|
|
if (strcmp(yytext, "%name") == 0)
|
|
return (NAME);
|
|
if (strcmp(yytext, "%rename") == 0) {
|
|
rename_active = 1;
|
|
return (RENAME);
|
|
}
|
|
if (strcmp(yytext, "%namewarn") == 0) {
|
|
rename_active = 1;
|
|
return (NAMEWARN);
|
|
}
|
|
if (strcmp(yytext, "%includefile") == 0)
|
|
return (INCLUDE);
|
|
if (strcmp(yytext, "%val") == 0) {
|
|
Swig_warning(WARN_DEPRECATED_VAL, cparse_file, cparse_line, "%%val directive deprecated (ignored).\n");
|
|
return (yylex());
|
|
}
|
|
if (strcmp(yytext, "%out") == 0) {
|
|
Swig_warning(WARN_DEPRECATED_OUT, cparse_file, cparse_line, "%%out directive deprecated (ignored).\n");
|
|
return (yylex());
|
|
}
|
|
if (strcmp(yytext, "%constant") == 0)
|
|
return (CONSTANT);
|
|
if (strcmp(yytext, "%typedef") == 0) {
|
|
yylval.ivalue = 1;
|
|
return (TYPEDEF);
|
|
}
|
|
if (strcmp(yytext, "%native") == 0)
|
|
return (NATIVE);
|
|
if (strcmp(yytext, "%pragma") == 0)
|
|
return (PRAGMA);
|
|
if (strcmp(yytext, "%extend") == 0)
|
|
return (EXTEND);
|
|
if (strcmp(yytext, "%fragment") == 0)
|
|
return (FRAGMENT);
|
|
if (strcmp(yytext, "%inline") == 0)
|
|
return (INLINE);
|
|
if (strcmp(yytext, "%typemap") == 0)
|
|
return (TYPEMAP);
|
|
if (strcmp(yytext, "%feature") == 0)
|
|
return (FEATURE);
|
|
if (strcmp(yytext, "%except") == 0)
|
|
return (EXCEPT);
|
|
if (strcmp(yytext, "%importfile") == 0)
|
|
return (IMPORT);
|
|
if (strcmp(yytext, "%echo") == 0)
|
|
return (ECHO);
|
|
if (strcmp(yytext, "%apply") == 0)
|
|
return (APPLY);
|
|
if (strcmp(yytext, "%clear") == 0)
|
|
return (CLEAR);
|
|
if (strcmp(yytext, "%types") == 0)
|
|
return (TYPES);
|
|
if (strcmp(yytext, "%parms") == 0)
|
|
return (PARMS);
|
|
if (strcmp(yytext, "%varargs") == 0)
|
|
return (VARARGS);
|
|
if (strcmp(yytext, "%template") == 0) {
|
|
return (SWIGTEMPLATE);
|
|
}
|
|
if (strcmp(yytext, "%warn") == 0)
|
|
return (WARN);
|
|
}
|
|
/* Have an unknown identifier, as a last step, we'll do a typedef lookup on it. */
|
|
|
|
/* Need to fix this */
|
|
if (check_typedef) {
|
|
if (SwigType_istypedef(yytext)) {
|
|
yylval.type = NewString(yytext);
|
|
return (TYPE_TYPEDEF);
|
|
}
|
|
}
|
|
yylval.id = Swig_copy_string(yytext);
|
|
last_id = 1;
|
|
return (ID);
|
|
case POUND:
|
|
return yylex();
|
|
default:
|
|
return (l);
|
|
}
|
|
}
|