aboutsummaryrefslogtreecommitdiff
path: root/Source/CParse/cscanner.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CParse/cscanner.c')
-rw-r--r--Source/CParse/cscanner.c183
1 files changed, 113 insertions, 70 deletions
diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c
index cb2fdb5dd..03cc8c3a5 100644
--- a/Source/CParse/cscanner.c
+++ b/Source/CParse/cscanner.c
@@ -4,7 +4,7 @@
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
- * and at http://www.swig.org/legal.html.
+ * and at https://www.swig.org/legal.html.
*
* scanner.c
*
@@ -46,7 +46,6 @@ String *cparse_unknown_directive = 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;
@@ -93,7 +92,7 @@ int isStructuralDoxygen(String *s) {
const size_t len = strlen(structuralTags[n]);
if (strncmp(slashPointer, structuralTags[n], len) == 0) {
/* Take care to avoid false positives with prefixes of other tags. */
- if (slashPointer[len] == '\0' || isspace(slashPointer[len]))
+ if (slashPointer[len] == '\0' || isspace((int)slashPointer[len]))
return 1;
}
}
@@ -123,7 +122,7 @@ void Swig_cparse_cplusplusout(int v) {
* Initialize buffers
* ------------------------------------------------------------------------- */
-void scanner_init() {
+void scanner_init(void) {
scan = NewScanner();
Scanner_idstart(scan,"%");
scan_init = 1;
@@ -163,15 +162,17 @@ void start_inline(char *text, int line) {
*
* Skips a piece of code enclosed in begin/end symbols such as '{...}' or
* (...). Ignores symbols inside comments or strings.
+ *
+ * Returns 0 if successfully skipped, -1 if EOF found first.
* ----------------------------------------------------------------------------- */
-void skip_balanced(int startchar, int endchar) {
+int skip_balanced(int startchar, int endchar) {
int start_line = Scanner_line(scan);
Clear(scanner_ccode);
if (Scanner_skip_balanced(scan,startchar,endchar) < 0) {
Swig_error(cparse_file, start_line, "Missing '%c'. Reached end of input.\n", endchar);
- return;
+ return -1;
}
cparse_line = Scanner_line(scan);
@@ -180,7 +181,7 @@ void skip_balanced(int startchar, int endchar) {
Append(scanner_ccode, Scanner_text(scan));
if (endchar == '}')
num_brace--;
- return;
+ return 0;
}
/* -----------------------------------------------------------------------------
@@ -214,13 +215,13 @@ void skip_decl(void) {
tok = Scanner_token(scan);
if (tok == 0) {
if (!Swig_error_count()) {
- Swig_error(cparse_file, start_line, "Missing semicolon. Reached end of input.\n");
+ 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");
+ Swig_error(cparse_file, start_line, "Missing closing brace ('}'). Reached end of input.\n");
}
break;
}
@@ -267,14 +268,13 @@ static int yylook(void) {
case SWIG_TOKEN_RBRACE:
num_brace--;
if (num_brace < 0) {
- Swig_error(cparse_file, cparse_line, "Syntax error. Extraneous '}'\n");
+ Swig_error(cparse_file, cparse_line, "Syntax error. Extraneous closing brace ('}')\n");
num_brace = 0;
} else {
return RBRACE;
}
break;
case SWIG_TOKEN_LBRACE:
- last_brace = num_brace;
num_brace++;
return LBRACE;
case SWIG_TOKEN_EQUAL:
@@ -325,12 +325,14 @@ static int yylook(void) {
return ARROW;
case SWIG_TOKEN_PERIOD:
return PERIOD;
- case SWIG_TOKEN_MODULO:
+ case SWIG_TOKEN_PERCENT:
return MODULO;
case SWIG_TOKEN_COLON:
return COLON;
case SWIG_TOKEN_DCOLONSTAR:
return DSTAR;
+ case SWIG_TOKEN_LTEQUALGT:
+ return LESSEQUALGREATER;
case SWIG_TOKEN_DCOLON:
{
@@ -351,6 +353,23 @@ static int yylook(void) {
}
break;
+ case SWIG_TOKEN_ELLIPSIS:
+ return ELLIPSIS;
+
+ case SWIG_TOKEN_LLBRACKET:
+ do {
+ tok = Scanner_token(scan);
+ } while ((tok != SWIG_TOKEN_RRBRACKET) && (tok > 0));
+ if (tok <= 0) {
+ Swig_error(cparse_file, cparse_line, "Unbalanced double brackets, missing closing (']]'). Reached end of input.\n");
+ }
+ break;
+
+ case SWIG_TOKEN_RRBRACKET:
+ /* Turn an unmatched ]] back into two ] - e.g. `a[a[0]]` */
+ scanner_next_token(RBRACKET);
+ return RBRACKET;
+
/* Look for multi-character sequences */
case SWIG_TOKEN_RSTRING:
@@ -400,9 +419,14 @@ static int yylook(void) {
return NUM_ULONGLONG;
case SWIG_TOKEN_DOUBLE:
+ return NUM_DOUBLE;
+
case SWIG_TOKEN_FLOAT:
return NUM_FLOAT;
+ case SWIG_TOKEN_LONGDOUBLE:
+ return NUM_LONGDOUBLE;
+
case SWIG_TOKEN_BOOL:
return NUM_BOOL;
@@ -410,7 +434,6 @@ static int yylook(void) {
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));
@@ -428,17 +451,32 @@ static int yylook(void) {
/* Concatenate or skip all consecutive comments at once. */
do {
String *cmt = Scanner_text(scan);
+ String *cmt_modified = 0;
char *loc = Char(cmt);
if ((strncmp(loc, "/*@SWIG", 7) == 0) && (loc[Len(cmt)-3] == '@')) {
Scanner_locator(scan, cmt);
}
if (scan_doxygen_comments) { /* else just skip this node, to avoid crashes in parser module*/
+
+ int slashStyle = 0; /* Flag for "///" style doxygen comments */
+ if (strncmp(loc, "///", 3) == 0) {
+ slashStyle = 1;
+ if (Len(cmt) == 3) {
+ /* Modify to make length=4 to ensure that the empty comment does
+ get processed to preserve the newlines in the original comments. */
+ cmt_modified = NewStringf("%s ", cmt);
+ cmt = cmt_modified;
+ loc = Char(cmt);
+ }
+ }
+
/* Check for all possible Doxygen comment start markers while ignoring
comments starting with a row of asterisks or slashes just as
- Doxygen itself does. */
+ Doxygen itself does. Also skip empty comment (slash-star-star-slash),
+ which causes a crash due to begin > end. */
if (Len(cmt) > 3 && loc[0] == '/' &&
((loc[1] == '/' && ((loc[2] == '/' && loc[3] != '/') || loc[2] == '!')) ||
- (loc[1] == '*' && ((loc[2] == '*' && loc[3] != '*') || loc[2] == '!')))) {
+ (loc[1] == '*' && ((loc[2] == '*' && loc[3] != '*' && loc[3] != '/') || loc[2] == '!')))) {
comment_kind_t this_comment = loc[3] == '<' ? DOX_COMMENT_POST : DOX_COMMENT_PRE;
if (existing_comment != DOX_COMMENT_NONE && this_comment != existing_comment) {
/* We can't concatenate together Doxygen pre- and post-comments. */
@@ -461,6 +499,13 @@ static int yylook(void) {
Setline(yylval.str, Scanner_start_line(scan));
Setfile(yylval.str, Scanner_file(scan));
} else {
+ if (slashStyle) {
+ /* Add a newline to the end of each doxygen "///" comment,
+ since they are processed individually, unlike the
+ slash-star style, which gets processed as a block with
+ newlines included. */
+ Append(yylval.str, "\n");
+ }
Append(yylval.str, str);
}
@@ -471,6 +516,7 @@ static int yylook(void) {
do {
tok = Scanner_token(scan);
} while (tok == SWIG_TOKEN_ENDLINE);
+ Delete(cmt_modified);
} while (tok == SWIG_TOKEN_COMMENT);
Scanner_pushtoken(scan, tok, Scanner_text(scan));
@@ -496,25 +542,15 @@ static int yylook(void) {
}
}
-static int check_typedef = 0;
-
void scanner_set_location(String *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() {
+void scanner_clear_rename(void) {
rename_active = 0;
}
@@ -528,7 +564,7 @@ void scanner_set_main_input_file(String *file) {
main_input_file = file;
}
-String *scanner_get_main_input_file() {
+String *scanner_get_main_input_file(void) {
return main_input_file;
}
@@ -547,6 +583,9 @@ int yylex(void) {
scanner_init();
}
+ Delete(cparse_unknown_directive);
+ cparse_unknown_directive = NULL;
+
if (next_token) {
l = next_token;
next_token = 0;
@@ -575,29 +614,36 @@ int yylex(void) {
switch (l) {
case NUM_INT:
+ yylval.dtype.type = T_INT;
+ goto num_common;
+ case NUM_DOUBLE:
+ yylval.dtype.type = T_DOUBLE;
+ goto num_common;
case NUM_FLOAT:
+ yylval.dtype.type = T_FLOAT;
+ goto num_common;
+ case NUM_LONGDOUBLE:
+ yylval.dtype.type = T_LONGDOUBLE;
+ goto num_common;
case NUM_ULONG:
+ yylval.dtype.type = T_ULONG;
+ goto num_common;
case NUM_LONG:
+ yylval.dtype.type = T_LONG;
+ goto num_common;
case NUM_UNSIGNED:
+ yylval.dtype.type = T_UINT;
+ goto num_common;
case NUM_LONGLONG:
+ yylval.dtype.type = T_LONGLONG;
+ goto num_common;
case NUM_ULONGLONG:
+ yylval.dtype.type = T_ULONGLONG;
+ goto num_common;
case NUM_BOOL:
- 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;
- if (l == NUM_BOOL)
- yylval.dtype.type = T_BOOL;
+ yylval.dtype.type = T_BOOL;
+num_common:
+ yylval.dtype.unary_arg_type = 0;
yylval.dtype.val = NewString(Scanner_text(scan));
yylval.dtype.bitfield = 0;
yylval.dtype.throws = 0;
@@ -873,15 +919,19 @@ int yylex(void) {
return (USING);
if (strcmp(yytext, "namespace") == 0)
return (NAMESPACE);
- if (strcmp(yytext, "override") == 0)
+ if (strcmp(yytext, "override") == 0) {
+ last_id = 1;
return (OVERRIDE);
- if (strcmp(yytext, "final") == 0)
+ }
+ if (strcmp(yytext, "final") == 0) {
+ last_id = 1;
return (FINAL);
+ }
} 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) {
+ if (strcmp(yytext, "_Complex") == 0) {
yylval.type = NewSwigType(T_COMPLEX);
return (TYPE_COMPLEX);
}
@@ -921,16 +971,12 @@ int yylex(void) {
return (yylex());
} else {
- Delete(cparse_unknown_directive);
- cparse_unknown_directive = NULL;
-
/* SWIG directives */
+ String *stext = 0;
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);
@@ -945,14 +991,6 @@ int yylex(void) {
return (BEGINFILE);
if (strcmp(yytext, "%endoffile") == 0)
return (ENDOFFILE);
- 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) {
@@ -979,8 +1017,6 @@ int yylex(void) {
rename_active = 1;
return (FEATURE);
}
- if (strcmp(yytext, "%except") == 0)
- return (EXCEPT);
if (strcmp(yytext, "%importfile") == 0)
return (IMPORT);
if (strcmp(yytext, "%echo") == 0)
@@ -1001,18 +1037,25 @@ int yylex(void) {
if (strcmp(yytext, "%warn") == 0)
return (WARN);
- /* Note down the apparently unknown directive for error reporting. */
+ /* Note down the apparently unknown directive for error reporting - if
+ * we end up reporting a generic syntax error we'll instead report an
+ * error for this as an unknown directive. Then we treat it as MODULO
+ * (`%`) followed by an identifier and if that parses OK then
+ * `cparse_unknown_directive` doesn't get used.
+ *
+ * This allows `a%b` to be handled in expressions without a space after
+ * the operator.
+ */
cparse_unknown_directive = NewString(yytext);
+ stext = NewString(yytext + 1);
+ Seek(stext,0,SEEK_SET);
+ Setfile(stext,cparse_file);
+ Setline(stext,cparse_line);
+ Scanner_push(scan,stext);
+ Delete(stext);
+ return (MODULO);
}
- /* 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);