# HG changeset patch # User mjsousa # Date 1354361416 0 # Node ID 7b52623a2f3740da32dd55d3ff0f9af852f41c94 # Parent d736dc9e9e51fc5ebc24909e29ce1913c9f583e2 Allow bison to ask for an END_OF_INPUT token multiple times! diff -r d736dc9e9e51 -r 7b52623a2f37 stage1_2/iec_bison.yy --- a/stage1_2/iec_bison.yy Sat Dec 01 11:27:48 2012 +0000 +++ b/stage1_2/iec_bison.yy Sat Dec 01 11:30:16 2012 +0000 @@ -8265,8 +8265,9 @@ fprintf (stderr, "Out of memory. Bailing out!\n"); return -1; } - - if(parse_file(libfilename) < 0) { + + FILE *libfile = NULL; + if((libfile = parse_file(libfilename)) == NULL) { char *errmsg = strdup2("Error opening library file ", libfilename); perror(errmsg); free(errmsg); @@ -8279,7 +8280,8 @@ full_token_loc = full_token_loc_; if (yyparse() != 0) ERROR; - + fclose(libfile); + if (yynerrs > 0) { fprintf (stderr, "\n%d error(s) found in %s. Bailing out!\n", yynerrs /* global variable */, libfilename); ERROR; @@ -8299,8 +8301,8 @@ #if YYDEBUG yydebug = 1; #endif - - if(parse_file(filename) < 0) { + FILE *mainfile = NULL; + if ((mainfile = parse_file(filename)) == NULL) { char *errmsg = strdup2("Error opening main file ", filename); perror(errmsg); free(errmsg); @@ -8315,7 +8317,8 @@ fprintf (stderr, "\nParsing failed because of too many consecutive syntax errors. Bailing out!\n"); exit(EXIT_FAILURE); } - + fclose(mainfile); + if (yynerrs > 0) { fprintf (stderr, "\n%d error(s) found. Bailing out!\n", yynerrs /* global variable */); exit(EXIT_FAILURE); diff -r d736dc9e9e51 -r 7b52623a2f37 stage1_2/iec_flex.ll --- a/stage1_2/iec_flex.ll Sat Dec 01 11:27:48 2012 +0000 +++ b/stage1_2/iec_flex.ll Sat Dec 01 11:30:16 2012 +0000 @@ -884,17 +884,28 @@ } -<> { /* NOTE: We must not change the value of include_stack_ptr - * just yet. We must only decrement it if we are NOT - * at the end of the main file. - * If we have finished parsing the main file, then we - * must leave include_stack_ptr at 0, in case the - * parser is called once again with a new file. - * (In fact, we currently do just that!) +<> { /* NOTE: Currently bison is incorrectly using END_OF_INPUT in many rules + * when checking for syntax errors in the input source code. + * This means that in reality flex will be asked to carry on reading the input + * even after it has reached the end of all (including the main) input files. + * In other owrds, we will be called to return more tokens, even after we have + * already returned an END_OF_INPUT token. In this case, we must carry on returning + * more END_OF_INPUT tokens. + * + * However, in the above case we will be asked to carry on reading more tokens + * from the main input file, after we have reached the end. For this to work + * correctly, we cannot close the main input file! + * + * This is why we WILL be called with include_stack_ptr == 0 multiple times, + * and why we must handle it as a special case + * that leaves the include_stack_ptr unchanged, and returns END_OF_INPUT once again. + * + * As a corollory, flex can never safely close the main input file, and we must ask + * bison to close it! */ - fclose(yyin); - free(current_tracking); if (include_stack_ptr == 0) { + // fclose(yyin); // Must not do this!! + // free(current_tracking); // Must not do this!! /* yyterminate() terminates the scanner and returns a 0 to the * scanner's caller, indicating "all done". * @@ -905,6 +916,8 @@ */ yyterminate(); } else { + fclose(yyin); + free(current_tracking); --include_stack_ptr; yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer((include_stack[include_stack_ptr]).buffer_state); @@ -1864,18 +1877,18 @@ /* Tell flex which file to parse. This function will not imediately start parsing the file. * To parse the file, you then need to call yyparse() * - * Returns -1 on error opening the file (and a valid errno), or 0 on success. - */ -int parse_file(const char *filename) { + * Returns NULL on error opening the file (and a valid errno), or 0 on success. + * Caller must close the file! + */ +FILE *parse_file(const char *filename) { FILE *filehandle = NULL; - if((filehandle = fopen(filename, "r")) == NULL) - return -1; - - yyin = filehandle; - current_filename = strdup(filename); - current_tracking = GetNewTracking(yyin); - return 0; + if((filehandle = fopen(filename, "r")) != NULL) { + yyin = filehandle; + current_filename = strdup(filename); + current_tracking = GetNewTracking(yyin); + } + return filehandle; } diff -r d736dc9e9e51 -r 7b52623a2f37 stage1_2/stage1_2_priv.hh --- a/stage1_2/stage1_2_priv.hh Sat Dec 01 11:27:48 2012 +0000 +++ b/stage1_2/stage1_2_priv.hh Sat Dec 01 11:30:16 2012 +0000 @@ -126,10 +126,10 @@ /* Tell flex which file to parse. This function will not imediately start parsing the file. * To parse the file, you then need to call yyparse() * - * Returns -1 on error opening the file (and a valid errno), or 0 on success. - */ -int parse_file(const char *filename); - + * Returns NULL on error opening the file (and a valid errno), or 0 on success. + * Caller must close the file! + */ +FILE *parse_file(const char *filename);