From 05122d3e2c572382fd80072238c75d924f0a9165 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 19 Dec 2010 13:33:04 +0200 Subject: [PATCH] Add VHDLPP support to ivlpp program The ivlpp program is a good place to detect that the source file is VHDL, and pass the source file to the vhdlpp program. Do so automatically. --- ivlpp/globals.h | 2 ++ ivlpp/ivlpp.txt | 45 +++++++++++++++++++++++++++++++- ivlpp/lexor.lex | 65 +++++++++++++++++++++++++++++++++++++++++++--- ivlpp/main.c | 10 ++++++- vhdlpp/Makefile.in | 10 +++++++ vhdlpp/main.cc | 6 ++++- 6 files changed, 131 insertions(+), 7 deletions(-) diff --git a/ivlpp/globals.h b/ivlpp/globals.h index c30991b06..236659684 100644 --- a/ivlpp/globals.h +++ b/ivlpp/globals.h @@ -33,6 +33,8 @@ extern void dump_precompiled_defines(FILE*out); an include directive in encountered. */ extern char**include_dir; extern unsigned include_cnt; +/* Program to use for VHDL processing. */ +extern char*vhdlpp_path; extern int relative_include; diff --git a/ivlpp/ivlpp.txt b/ivlpp/ivlpp.txt index 84ca39781..d8b7d7506 100644 --- a/ivlpp/ivlpp.txt +++ b/ivlpp/ivlpp.txt @@ -42,6 +42,15 @@ valid options include: This option does *not* override existing `define directives in the source file. + -F + Read ivlpp options from a FLAGS FILE. This is not the same + as a file list. This file contains flags, not source + files. There may be multiple flags files. + + -f + Read ivlpp input files from a file list. There can be no + more then one file list. + -I Add a directory to the include path. Normally, only "." is in the search path. The -I flag causes other directories @@ -59,8 +68,42 @@ valid options include: output. -v - Print version and copyright information + Print version and copyright information before processing + input files. + -V + Print version and copyright information, then exit WITHOUT + processing any input files. + +FLAGS FILE + +A flags file contains flags for use by ivlpp. This is a convenient way +for programs to pass complex sets of flags to the ivlpp program. + +Blank lines and lines that start with "#" are ignored. The latter can +be used as comment lines. All other lines are flag lines. Leading and +trailing white space are removed before the lines are interpreted. + +Other lines have the simple format: + + : + +The colon character separates a key from the value. The supported +keys, with their corresponding values, are: + + D:name= + This is exactly the same as the "-Dname=" described above. + + I: + This is exctly the same as "-I". + + relative include: + The can be "true" or "false". This enables "relative + includes" nesting behavior. + + vhdlpp: + Give the path to the vhdlpp program. This program is used to + process VHDL input files. LOCATING INCLUDED FILES diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 335c92920..313011ada 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -59,6 +59,7 @@ struct include_stack_t /* If the current input is from a file, this member is set. */ FILE* file; + int (*file_close)(FILE*); /* If we are reparsing a macro expansion, file is 0 and this * member points to the string in progress @@ -1614,8 +1615,10 @@ static void do_include() { /* standby is defined by include_filename() */ if (standby->path[0] == '/') { - if ((standby->file = fopen(standby->path, "r"))) + if ((standby->file = fopen(standby->path, "r"))) { + standby->file_close = fclose; goto code_that_switches_buffers; + } } else { unsigned idx, start = 1; char path[4096]; @@ -1644,6 +1647,7 @@ static void do_include() sprintf(path, "%s/%s", include_dir[idx], standby->path); if ((standby->file = fopen(path, "r"))) { + standby->file_close = fclose; /* Free the original path before we overwrite it. */ free(standby->path); standby->path = strdup(path); @@ -1750,6 +1754,58 @@ static void lexor_done() } } +/* + * Use this function to open a source file that is to be + * processed. Do NOT use this function for opening include files, + * instead only use this file for opening base source files. + */ +static void open_input_file(struct include_stack_t*isp) +{ + char*cp; + int is_vhdl = 0; + + isp->file = 0; + + /* look for a suffix for the input file. If the suffix + indicates that this is a VHDL source file, then invoke + vhdlpp to get a data stream. */ + cp = strrchr(isp->path, '.'); + if (cp && vhdlpp_path) { + if (strcmp(cp, ".vhd") == 0) { + is_vhdl = 1; + } else if (strcmp(cp, ".vhdl") == 0) { + is_vhdl = 1; + } + } + + if (is_vhdl == 0) { + isp->file = fopen(isp->path, "r"); + isp->file_close = fclose; + return; + } + + size_t cmdlen = strlen(vhdlpp_path); + cmdlen += strlen(isp->path); + cmdlen += 32; + + char*cmd = malloc(cmdlen); + snprintf(cmd, cmdlen, "%s %s", vhdlpp_path, isp->path); + + isp->file = popen(cmd, "r"); + isp->file_close = pclose; + + free(cmd); + return; +} + +/* + * The load_next_input() function is called by the lexical analyzer + * when the current file runs out. When the EOF of the current input + * file is matched, this function figures out if this is the end of an + * included file (in which case the including file is resumed) or the + * end of a base file, in which case the next base source file is + * opened. + */ static int load_next_input() { int line_mask_flag = 0; @@ -1773,7 +1829,8 @@ static int load_next_input() if (isp->file) { free(isp->path); - fclose(isp->file); + assert(isp->file_close); + isp->file_close(isp->file); } else { @@ -1813,7 +1870,7 @@ static int load_next_input() istack->next = 0; istack->lineno = 0; - istack->file = fopen(istack->path, "r"); + open_input_file(istack); if (istack->file == 0) { @@ -1966,7 +2023,7 @@ void reset_lexor(FILE* out, char* paths[]) isp = malloc(sizeof(struct include_stack_t)); isp->next = 0; isp->path = strdup(paths[0]); - isp->file = fopen(paths[0], "r"); + open_input_file(isp); isp->str = 0; isp->lineno = 0; isp->stringify_flag = 0; diff --git a/ivlpp/main.c b/ivlpp/main.c index 3b8d1857d..8a92da3e1 100644 --- a/ivlpp/main.c +++ b/ivlpp/main.c @@ -57,7 +57,8 @@ extern const char*optarg; char *dep_path = NULL; /* Dependency file output mode */ char dep_mode = 'a'; - +/* Path to vhdlpp */ +char *vhdlpp_path = 0; /* * Keep in source_list an array of pointers to file names. The array @@ -166,6 +167,13 @@ static int flist_read_flags(const char*path) relative_include = 0; } + } else if (strcmp(cp,"vhdlpp") == 0) { + if (vhdlpp_path) { + fprintf(stderr, "Ignore multiple vhdlpp flags\n"); + } else { + vhdlpp_path = strdup(arg); + } + } else { fprintf(stderr, "%s: Invalid keyword %s\n", path, cp); } diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index 55e272257..61ffd575c 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -92,6 +92,16 @@ lexor_keyword.o: lexor_keyword.cc parse.h lexor_keyword.cc: $(srcdir)/lexor_keyword.gperf gperf -o -i 7 --ignore-case -C -k 1-4,6,9,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false) +install: all installdirs $(libdir)/ivl$(suffix)/vhdlpp@EXEEXT@ + +$(libdir)/ivl$(suffix)/vhdlpp@EXEEXT@: vhdlpp@EXEEXT@ + $(INSTALL_PROGRAM) ./vhdlpp@EXEEXT@ "$(DESTDIR)$(libdir)/ivl$(suffix)/vhdlpp@EXEEXT@" + +installdirs: $(srcdir)/../mkinstalldirs + $(srcdir)/../mkinstalldirs "$(DESTDIR)$(libdir)/ivl$(suffix)" + +uninstall: + rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/ivhdlpp@EXEEXT@" stamp-vhdlpp_config-h: $(srcdir)/vhdlpp_config.h.in ../config.status @rm -f $@ diff --git a/vhdlpp/main.cc b/vhdlpp/main.cc index 7beedc93f..1f0d5debc 100644 --- a/vhdlpp/main.cc +++ b/vhdlpp/main.cc @@ -46,6 +46,8 @@ const char NOTICE[] = # include #endif +bool verbose_flag = false; + static void process_debug_token(const char*word) { if (strcmp(word, "yydebug") == 0) { @@ -71,6 +73,7 @@ int main(int argc, char*argv[]) VERSION " (" VERSION_TAG ")\n\n"); fprintf(stderr, "%s\n\n", COPYRIGHT); fputs(NOTICE, stderr); + verbose_flag = true; break; case 'V': @@ -92,7 +95,8 @@ int main(int argc, char*argv[]) reset_lexor(fd, argv[idx]); rc = yyparse(); - fprintf(stderr, "yyparse() returns %d, parse_errors=%d\n", rc, parse_errors); + if (verbose_flag) + fprintf(stderr, "yyparse() returns %d, parse_errors=%d\n", rc, parse_errors); if (parse_errors > 0) { fprintf(stderr, "%d errors parsing %s\n", parse_errors, argv[idx]);