From 9b43f1d5f4220f9bf0b1a167296ba2a8dd9f83f5 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 24 Jan 2019 14:54:39 -0600 Subject: [PATCH] GH-167: improve error message for unclosed function at EOF --- src/parse.y | 31 +++++++++++++------ src/scan.l | 9 +++++- .../language.eof-parse-errors/output1 | 1 + .../language.eof-parse-errors/output2 | 1 + testing/btest/language/eof-parse-errors.bro | 21 +++++++++++++ 5 files changed, 52 insertions(+), 11 deletions(-) create mode 100644 testing/btest/Baseline/language.eof-parse-errors/output1 create mode 100644 testing/btest/Baseline/language.eof-parse-errors/output2 create mode 100644 testing/btest/language/eof-parse-errors.bro diff --git a/src/parse.y b/src/parse.y index a9f8d4b260..db7e0f846f 100644 --- a/src/parse.y +++ b/src/parse.y @@ -94,6 +94,9 @@ #include extern const char* filename; // Absolute path of file currently being parsed. +extern const char* last_filename; // Absolute path of last file parsed. +extern const char* last_tok_filename; +extern const char* last_last_tok_filename; YYLTYPE GetCurrentLocation(); extern int yyerror(const char[]); @@ -1723,19 +1726,27 @@ opt_deprecated: int yyerror(const char msg[]) { - char* msgbuf = new char[strlen(msg) + strlen(last_tok) + 128]; - - if ( last_tok[0] == '\n' ) - sprintf(msgbuf, "%s, on previous line", msg); - else if ( last_tok[0] == '\0' ) - sprintf(msgbuf, "%s, at end of file", msg); - else - sprintf(msgbuf, "%s, at or near \"%s\"", msg, last_tok); - if ( in_debug ) g_curr_debug_error = copy_string(msg); - reporter->Error("%s", msgbuf); + if ( last_tok[0] == '\n' ) + reporter->Error("%s, on previous line", msg); + else if ( last_tok[0] == '\0' ) + { + if ( last_filename ) + reporter->Error("%s, at end of file %s", msg, last_filename); + else + reporter->Error("%s, at end of file", msg); + } + else + { + if ( last_last_tok_filename && last_tok_filename && + ! streq(last_last_tok_filename, last_tok_filename) ) + reporter->Error("%s, at or near \"%s\" or end of file %s", + msg, last_tok, last_last_tok_filename); + else + reporter->Error("%s, at or near \"%s\"", msg, last_tok); + } return 0; } diff --git a/src/scan.l b/src/scan.l index 763ee2d86d..c2be426044 100644 --- a/src/scan.l +++ b/src/scan.l @@ -43,11 +43,16 @@ int_list if_stack; int line_number = 1; const char* filename = 0; // Absolute path of file currently being parsed. +const char* last_filename = 0; // Absolute path of last file parsed. static const char* last_id_tok = 0; +const char* last_tok_filename = 0; +const char* last_last_tok_filename = 0; char last_tok[128]; -#define YY_USER_ACTION strncpy(last_tok, yytext, sizeof(last_tok) - 1); +#define YY_USER_ACTION strncpy(last_tok, yytext, sizeof(last_tok) - 1); \ + last_last_tok_filename = last_tok_filename; \ + last_tok_filename = ::filename; #define YY_USER_INIT last_tok[0] = '\0'; // We define our own YY_INPUT because we want to trap the case where @@ -899,6 +904,8 @@ void add_to_name_list(char* s, char delim, name_list& nl) int yywrap() { + last_filename = ::filename; + if ( reporter->Errors() > 0 ) return 1; diff --git a/testing/btest/Baseline/language.eof-parse-errors/output1 b/testing/btest/Baseline/language.eof-parse-errors/output1 new file mode 100644 index 0000000000..47a1c328e3 --- /dev/null +++ b/testing/btest/Baseline/language.eof-parse-errors/output1 @@ -0,0 +1 @@ +error: syntax error, at end of file ./a.bro diff --git a/testing/btest/Baseline/language.eof-parse-errors/output2 b/testing/btest/Baseline/language.eof-parse-errors/output2 new file mode 100644 index 0000000000..6f382c2a12 --- /dev/null +++ b/testing/btest/Baseline/language.eof-parse-errors/output2 @@ -0,0 +1 @@ +error in ./b.bro, line 1: syntax error, at or near "module" or end of file ./a.bro diff --git a/testing/btest/language/eof-parse-errors.bro b/testing/btest/language/eof-parse-errors.bro new file mode 100644 index 0000000000..a2c6edc66d --- /dev/null +++ b/testing/btest/language/eof-parse-errors.bro @@ -0,0 +1,21 @@ +# @TEST-EXEC-FAIL: bro -b a.bro >output1 2>&1 +# @TEST-EXEC-FAIL: bro -b a.bro b.bro >output2 2>&1 +# @TEST-EXEC: btest-diff output1 +# @TEST-EXEC: btest-diff output2 + +@TEST-START-FILE a.bro +module A; + +event bro_init() + { + print "a"; +@TEST-END-FILE + +@TEST-START-FILE b.bro +module B; + +event bro_init() + { + print "b"; + } +@TEST-END-FILE