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; }