diff options
Diffstat (limited to 'Source/CParse/cscanner.c')
-rw-r--r-- | Source/CParse/cscanner.c | 183 |
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); |