Ok this is an embarrassing one. A source file that is either empty or that contains just blanks, characters and/or pragmats, is not a proper particular program nor a prelude packet. This patch makes ga68 to emit an error mesage rather than ICEing.
Signed-off-by: Jose E. Marchesi <[email protected]> gcc/algol68/ChangeLog * a68-parser-scanner.cc (a68_lexical_analyser): New argument empty_program. * a68.h: Update prototype of a68_lexical_analyser. * a68-parser.cc (a68_parser): Emit error for empty input files. --- gcc/algol68/a68-parser-scanner.cc | 27 +++++++++++++++++++-------- gcc/algol68/a68-parser.cc | 12 +++++------- gcc/algol68/a68.h | 2 +- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/gcc/algol68/a68-parser-scanner.cc b/gcc/algol68/a68-parser-scanner.cc index 966ebdf6ed1..8c0694de9ba 100644 --- a/gcc/algol68/a68-parser-scanner.cc +++ b/gcc/algol68/a68-parser-scanner.cc @@ -328,12 +328,7 @@ read_source_file (const char *filename) fatal_error (UNKNOWN_LOCATION, "specified file %s is a directory", filename); - if ((source_file_size = get_source_size ()) == 0) - { - /* The source file is empty. */ - ret = false; - goto done; - } + source_file_size = get_source_size (); /* Allocate A68_PARSER (scan_buf), which is an auxiliary buffer used by the scanner known to be big enough to hold any string contained in the source @@ -395,7 +390,6 @@ read_source_file (const char *filename) /* Include files. */ include_files (TOP_LINE (&A68_JOB)); - done: if (fclose (FILE_SOURCE_FD (&A68_JOB)) != 0) gcc_unreachable (); return ret; @@ -2279,7 +2273,7 @@ tokenise_source (NODE_T **root, int level, bool in_format, /* Tokenise source file, build initial syntax tree. */ bool -a68_lexical_analyser (const char *filename) +a68_lexical_analyser (const char *filename, bool *empty_program) { LINE_T *l = NO_LINE, *start_l = NO_LINE; char *s = NO_TEXT, *start_c = NO_TEXT; @@ -2295,6 +2289,23 @@ a68_lexical_analyser (const char *filename) s = STRING (l); tokenise_source (&root, 0, false, &l, &s, &start_l, &start_c); + /* Detemine whether the actual file contents resulted in some token. This is + used in order to provide better diagnostics for empty source files or + files containing only comments or pragmats. These are not valid Algol 68 + packets. */ + + *empty_program = true; + for (NODE_T *p = TOP_NODE (&A68_JOB); p != NO_NODE; FORWARD (p)) + { + LINE_T *l = LINE (INFO (p)); + if (strcmp (FILENAME (l), "prelude") != 0 + && strcmp (FILENAME (l), "postlude") != 0) + { + *empty_program = false; + break; + } + } + /* If the source is a prelude packet then we should remove the prelude and postlude nodes from the token stream. We distinguish these nodes by location. diff --git a/gcc/algol68/a68-parser.cc b/gcc/algol68/a68-parser.cc index f01ecbee434..c43efe3ba19 100644 --- a/gcc/algol68/a68-parser.cc +++ b/gcc/algol68/a68-parser.cc @@ -454,17 +454,15 @@ a68_parser (const char *filename) /* Tokeniser. */ if (ERROR_COUNT (&A68_JOB) == 0) { - bool ok = a68_lexical_analyser (filename); + bool empty_program; + bool ok = a68_lexical_analyser (filename, &empty_program); if (!ok) return; - /* An empty file is not a valid program. */ - if (TOP_NODE (&A68_JOB) == NO_NODE) - { - a68_error (NO_NODE, "file is empty, expected a program"); - return; - } + if (empty_program) + a68_error (NO_NODE, + "particular program or prelude packet not found in source file"); TREE_LISTING_SAFE (&A68_JOB) = true; renum = 0; diff --git a/gcc/algol68/a68.h b/gcc/algol68/a68.h index 92dc28e222f..40ceec9ddc3 100644 --- a/gcc/algol68/a68.h +++ b/gcc/algol68/a68.h @@ -280,7 +280,7 @@ void a68_scan_error (LINE_T *u, char *v, const char *txt, ...); /* a68-parser-scanner.cc */ -bool a68_lexical_analyser (const char *filename); +bool a68_lexical_analyser (const char *filename, bool *empty_file); /* a68-parser.cc */ -- 2.30.2
