From 95ea159e758f82763c57184ccc16870d968ca6d3 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 3 Nov 2008 11:29:34 -0800 Subject: [PATCH 1/4] Print `include comment after included text. The inline comment text that appears after an `include directive should appear after the included text not before. --- ivlpp/lexor.lex | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index a25e4dc5a..244ece196 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -78,6 +78,9 @@ struct include_stack_t YY_BUFFER_STATE yybs; struct include_stack_t* next; + + /* A single line comment can be associated with this include. */ + char* comment; }; static void emit_pathline(struct include_stack_t* isp); @@ -295,9 +298,10 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif) /* Catch single-line comments that share the line with an include * directive. And while I'm at it, I might as well preserve the - * comment in the output stream. + * comment in the output stream. This will be printed after the + * file has been included. */ -"//"[^\r\n]* { ECHO; } +"//"[^\r\n]* { standby->comment = strdup(yytext); } /* These finish the include directive (EOF or EOL) so I revert the * lexor state and execute the inclusion. @@ -1418,6 +1422,7 @@ static void include_filename() standby->path = strdup(yytext+1); standby->path[strlen(standby->path)-1] = 0; standby->lineno = 0; + standby->comment = NULL; } static void do_include() @@ -1530,6 +1535,17 @@ static int load_next_input() /* Delete the current input buffers, and free the cell. */ yy_delete_buffer(YY_CURRENT_BUFFER); + /* If there was a comment for this include print it before we + * return to the previous input stream. This technically belongs + * to the previous stream, but it should not create any problems + * since it is only a comment. + */ + if (isp->comment) { + fprintf(yyout, "%s\n", isp->comment); + free(isp->comment); + isp->comment = NULL; + } + if (isp->file) { free(isp->path); @@ -1726,6 +1742,7 @@ void reset_lexor(FILE* out, char* paths[]) isp->ebs = 0; isp->lineno = 0; isp->stringify_flag = 0; + isp->comment = NULL; if (isp->file == 0) { @@ -1756,6 +1773,7 @@ void reset_lexor(FILE* out, char* paths[]) isp->next = 0; isp->lineno = 0; isp->stringify_flag = 0; + isp->comment = NULL; if (tail) tail->next = isp; From 4c67bd0b35c43be2ead805ac9e69731a356c5ca8 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 3 Nov 2008 11:16:16 -0800 Subject: [PATCH 2/4] Fix memory leak and free temp. file names to make valgrind happy. There was a memory leak in the preprocess_only code (cmd was not being freed when the command completed successfully. Valgrind was also marking the temporary file names as still reachable, so they are not memory leaks, but freeing them makes valgrind happier. --- driver/main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/driver/main.c b/driver/main.c index fbd8de4df..8d26cf1b2 100644 --- a/driver/main.c +++ b/driver/main.c @@ -263,6 +263,7 @@ static const char*my_tempfile(const char*str, FILE**fout) static int t_version_only(void) { remove(source_path); + free(source_path); fflush(0); snprintf(tmp, sizeof tmp, "%s%civlpp -V", pbase, sep); @@ -275,8 +276,11 @@ static int t_version_only(void) if ( ! getenv("IVERILOG_ICONFIG")) { remove(iconfig_path); + free(iconfig_path); remove(defines_path); + free(defines_path); remove(compiled_defines_path); + free(compiled_defines_path); } return 0; @@ -314,11 +318,15 @@ static int t_preprocess_only(void) rc = system(cmd); remove(source_path); + free(source_path); if ( ! getenv("IVERILOG_ICONFIG")) { remove(iconfig_path); + free(iconfig_path); remove(defines_path); + free(defines_path); remove(compiled_defines_path); + free(compiled_defines_path); } if (rc != 0) { @@ -332,6 +340,7 @@ static int t_preprocess_only(void) return -1; } + free(cmd); return 0; } @@ -410,9 +419,13 @@ static int t_compile() rc = system(cmd); if ( ! getenv("IVERILOG_ICONFIG")) { remove(source_path); + free(source_path); remove(iconfig_path); + free(iconfig_path); remove(defines_path); + free(defines_path); remove(compiled_defines_path); + free(compiled_defines_path); } #ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */ free(cmd); From 049290d0fc686d7d68165f941ef528225a716f7b Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 4 Nov 2008 10:53:30 -0800 Subject: [PATCH 3/4] Fix a memory leak and release all dynamically allocated memory (ivlpp) This patch fixes a minor memory leak in ivlpp and releases all dynamically allocated memory before the program exits. Other than the dynamically allocated push state buffer in flex, ivlpp has no valgrind memory errors or warnings. --- ivlpp/globals.h | 3 ++- ivlpp/lexor.lex | 20 ++++++++++++++++++++ ivlpp/main.c | 14 ++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/ivlpp/globals.h b/ivlpp/globals.h index bd3ab933b..3c2b95865 100644 --- a/ivlpp/globals.h +++ b/ivlpp/globals.h @@ -1,7 +1,7 @@ #ifndef __globals_H #define __globals_H /* - * Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -25,6 +25,7 @@ extern void reset_lexor(FILE*out, char*paths[]); extern void load_precompiled_defines(FILE*src); extern void define_macro(const char*name, const char*value, int keyword, int argc); +extern void free_macros(); extern void dump_precompiled_defines(FILE*out); /* These variables contain the include directories to be searched when diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 244ece196..6e780f69d 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -833,6 +833,21 @@ void define_macro(const char* name, const char* value, int keyword, int argc) } } +static void free_macro(struct define_t* def) +{ + if (def == 0) return; + free_macro(def->left); + free_macro(def->right); + free(def->name); + free(def->value); + free(def); +} + +void free_macros() +{ + free_macro(def_table); +} + /* * The do_define function accumulates the defined value in these * variables. When the define is over, the def_finish() function @@ -1462,6 +1477,8 @@ static void do_include() if ((standby->file = fopen(path, "r"))) { + /* Free the original path before we overwrite it. */ + free(standby->path); standby->path = strdup(path); goto code_that_switches_buffers; } @@ -1473,6 +1490,9 @@ static void do_include() code_that_switches_buffers: + /* Clear the current files path from the search list. */ + include_dir[0] = 0; + if(depend_file) fprintf(depend_file, "%s\n", standby->path); diff --git a/ivlpp/main.c b/ivlpp/main.c index cdf4e4297..af7e66719 100644 --- a/ivlpp/main.c +++ b/ivlpp/main.c @@ -189,12 +189,14 @@ static int flist_read_names(const char*path) add_source_file(cp); } + fclose(fd); return 0; } int main(int argc, char*argv[]) { int opt, idx; + unsigned lp; const char*flist_path = 0; unsigned flag_errors = 0; char*out_path = 0; @@ -378,5 +380,17 @@ int main(int argc, char*argv[]) fclose(precomp_out); } + /* Free the source and include directory lists. */ + for (lp = 0; lp < source_cnt; lp += 1) { + free(source_list[lp]); + } + free(source_list); + for (lp = 0; lp < include_cnt; lp += 1) { + free(include_dir[lp]); + } + free(include_dir); + + free_macros(); + return error_count; } From 1e06a2ddef15a8377b8b46d6d20b4e5dbf718030 Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 4 Nov 2008 14:47:32 -0800 Subject: [PATCH 4/4] ivlpp - clear lexor dynamic state information for flex >= 2.5.9 For flex version 2.5.9 and later there is a function "yylex_destroy()" that clears any space dynamically allocated by the scanner. --- ivlpp/globals.h | 1 + ivlpp/lexor.lex | 14 ++++++++++++++ ivlpp/main.c | 1 + 3 files changed, 16 insertions(+) diff --git a/ivlpp/globals.h b/ivlpp/globals.h index 3c2b95865..623baa54a 100644 --- a/ivlpp/globals.h +++ b/ivlpp/globals.h @@ -22,6 +22,7 @@ # include extern void reset_lexor(FILE*out, char*paths[]); +extern void destroy_lexor(); extern void load_precompiled_defines(FILE*src); extern void define_macro(const char*name, const char*value, int keyword, int argc); diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 6e780f69d..d0a086e2e 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -1803,3 +1803,17 @@ void reset_lexor(FILE* out, char* paths[]) tail = isp; } } + +/* + * Modern version of flex (>=2.5.9) can clean up the scanner data. + */ +void destroy_lexor() +{ +# ifdef FLEX_SCANNER +# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5 +# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 + yylex_destroy(); +# endif +# endif +# endif +} diff --git a/ivlpp/main.c b/ivlpp/main.c index af7e66719..a8d761ebc 100644 --- a/ivlpp/main.c +++ b/ivlpp/main.c @@ -370,6 +370,7 @@ int main(int argc, char*argv[]) start scanning. */ reset_lexor(out, source_list); if (yylex()) return -1; + destroy_lexor(); if(depend_file) { fclose(depend_file);