diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index 435f27297..987fb265b 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -30,6 +30,12 @@ using namespace std; static const char*library_work_path = 0; static void store_package_in_work(const Package*pack); +static string make_work_package_path(const char*name) +{ + return string(library_work_path).append("/").append(name).append(".pkg"); +} + + struct library_contents { map packages; }; @@ -66,7 +72,7 @@ void dump_libraries(ostream&file) * This function saves a package into the named library. Create the * library if necessary. */ -void library_save_package(const char*libname, Package*pack) +void library_save_package(const char*libname, Package*pack, bool parse_work) { if (libname == 0) libname = "work"; @@ -76,7 +82,9 @@ void library_save_package(const char*libname, Package*pack) lib.packages[pack->name()] = pack; - if (use_libname == "work") + // If this is a work package, and we are NOT parsing the work + // library right now, then store it in the work library. + if (use_libname == "work" && !parse_work) store_package_in_work(pack); } @@ -114,6 +122,14 @@ void library_use(const YYLTYPE&loc, ActiveScope*res, struct library_contents&lib = libraries[use_library]; Package*pack = lib.packages[use_package]; + // If the package is not found in the work library already + // parsed, then see if it exists unparsed. + if (use_library=="work" && pack == 0) { + string path = make_work_package_path(use_package.str()); + parse_source_file(path.c_str(), true); + pack = lib.packages[use_package]; + } + // If the package is still not found, then error. if (pack == 0) { errormsg(loc, "No package %s in library %s\n", use_package.str(), use_library.str()); @@ -229,7 +245,7 @@ void library_set_work_path(const char*path) static void store_package_in_work(const Package*pack) { - string path = string(library_work_path).append("/").append(pack->name()).append(".pkg"); + string path = make_work_package_path(pack->name()); ofstream file (path.c_str(), ios_base::out|ios_base::app); diff --git a/vhdlpp/main.cc b/vhdlpp/main.cc index da78eaf21..b15de59cf 100644 --- a/vhdlpp/main.cc +++ b/vhdlpp/main.cc @@ -127,19 +127,12 @@ int main(int argc, char*argv[]) for (int idx = optind ; idx < argc ; idx += 1) { parse_errors = 0; parse_sorrys = 0; - FILE*fd = fopen(argv[idx], "r"); - if (fd == 0) { - perror(argv[idx]); + rc = parse_source_file(argv[idx], false); + if (rc < 0) return 1; - } - - yyscan_t scanner = prepare_lexor(fd); - rc = yyparse(scanner, argv[idx]); - fclose(fd); - destroy_lexor(scanner); if (verbose_flag) - fprintf(stderr, "yyparse() returns %d, parse_errors=%d, parse_sorrys=%d\n", rc, parse_errors, parse_sorrys); + fprintf(stderr, "parse_source_file() returns %d, parse_errors=%d, parse_sorrys=%d\n", rc, parse_errors, parse_sorrys); if (parse_errors > 0) { fprintf(stderr, "Encountered %d errors parsing %s\n", parse_errors, argv[idx]); diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 4a2039d11..7cc694404 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -1,8 +1,9 @@ %pure-parser -%parse-param {yyscan_t yyscanner} %lex-param { yyscan_t yyscanner } +%parse-param {yyscan_t yyscanner } %parse-param {const char*file_path} +%parse-param {bool parsing_work } %{ /* * Copyright (c) 2011 Stephen Williams (steve@icarus.com) @@ -58,7 +59,7 @@ inline void FILE_NAME(LineInfo*tmp, const struct yyltype&where) (Current).first_line = (Rhs)[1].first_line; \ (Current).text = file_path; /*(Rhs)[1].text;*/ } while (0) -static void yyerror(YYLTYPE*yyllocp,yyscan_t yyscanner,const char*file_path, const char*msg); +static void yyerror(YYLTYPE*yyllocp,yyscan_t yyscanner,const char*file_path,bool, const char*msg); int parse_errors = 0; int parse_sorrys = 0; @@ -1110,7 +1111,7 @@ package_declaration if ($6) delete[]$6; pop_scope(); /* Put this package into the work library. */ - library_save_package(0, tmp); + library_save_package(0, tmp, parsing_work); } | package_declaration_start K_is error K_end K_package_opt identifier_opt ';' { errormsg(@3, "Syntax error in package clause.\n"); @@ -1651,7 +1652,7 @@ K_postponed_opt : K_postponed | ; K_is_opt : K_is | ; %% -static void yyerror(YYLTYPE*, yyscan_t, const char*, const char* /*msg*/) +static void yyerror(YYLTYPE*, yyscan_t, const char*, bool, const char* /*msg*/) { //fprintf(stderr, "%s\n", msg); parse_errors += 1; @@ -1678,3 +1679,27 @@ void sorrymsg(const YYLTYPE&loc, const char*fmt, ...) va_end(ap); parse_sorrys += 1; } + + +/* + * The reset_lexor function takes the fd and makes it the input file + * for the lexor. The path argument is used in lexor/parser error messages. + */ +extern yyscan_t prepare_lexor(FILE*fd); +extern void destroy_lexor(yyscan_t scanner); + +int parse_source_file(const char*file_path, bool work_library_flag) +{ + FILE*fd = fopen(file_path, "r"); + if (fd == 0) { + perror(file_path); + return -1; + } + + yyscan_t scanner = prepare_lexor(fd); + int rc = yyparse(scanner, file_path, work_library_flag); + fclose(fd); + destroy_lexor(scanner); + + return rc; +} diff --git a/vhdlpp/parse_api.h b/vhdlpp/parse_api.h index ac986c5ee..3ff34773a 100644 --- a/vhdlpp/parse_api.h +++ b/vhdlpp/parse_api.h @@ -37,16 +37,10 @@ struct yyltype { # define YYLTYPE struct yyltype /* - * The reset_lexor function takes the fd and makes it the input file - * for the lexor. The path argument is used in lexor/parser error messages. + * This calls the bison-generated parser with the given file path as + * the input stream. If the file cannot be opened, this returns -1. */ -extern yyscan_t prepare_lexor(FILE*fd); -extern void destroy_lexor(yyscan_t scanner); - -/* - * This is the bison-generated parser. - */ -extern int yyparse(yyscan_t scanner, const char*file_path); +extern int parse_source_file(const char*file_path, bool parse_work_library); /* * Use this function during parse to generate error messages. The "loc" diff --git a/vhdlpp/parse_misc.h b/vhdlpp/parse_misc.h index de220b4e7..720aef3ee 100644 --- a/vhdlpp/parse_misc.h +++ b/vhdlpp/parse_misc.h @@ -47,7 +47,7 @@ extern const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_n */ extern const VType* parse_type_by_name(perm_string name); -extern void library_save_package(const char*libname, Package*pack); +extern void library_save_package(const char*libname, Package*pack, bool parse_work); extern void library_import(const YYLTYPE&loc, const std::list*names);