From 5de0c6180fc5c06f8c189790f0c0bfce5ebcf908 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Mon, 25 Sep 2023 17:34:16 -0700 Subject: [PATCH 1/2] Verilog preprocessor: fix include buffering To prevent scanning beyond an `include directive, we abort read-ahead whenever we see a newline. --- regression/verilog/preprocessor/include1.desc | 16 ++++++++++++++++ regression/verilog/preprocessor/include1.v | 3 +++ regression/verilog/preprocessor/include1b.v | 2 ++ src/verilog/verilog_preprocessor_tokenizer.cpp | 14 ++++++++++---- 4 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 regression/verilog/preprocessor/include1.desc create mode 100644 regression/verilog/preprocessor/include1.v create mode 100644 regression/verilog/preprocessor/include1b.v diff --git a/regression/verilog/preprocessor/include1.desc b/regression/verilog/preprocessor/include1.desc new file mode 100644 index 000000000..dca79f457 --- /dev/null +++ b/regression/verilog/preprocessor/include1.desc @@ -0,0 +1,16 @@ +CORE +include1.v +--preprocess +// Enable multi-line checking +activate-multi-line-match +`line 1 "include1.v" 0 +`line 1 "include1b.v" 1 +line b 1 +line b 2 +`line 1 "include1.v" 2 + +line 2 +line 3 +^EXIT=0$ +^SIGNAL=0$ +-- diff --git a/regression/verilog/preprocessor/include1.v b/regression/verilog/preprocessor/include1.v new file mode 100644 index 000000000..b7ee716d9 --- /dev/null +++ b/regression/verilog/preprocessor/include1.v @@ -0,0 +1,3 @@ +`include "include1b.v" +line 2 +line 3 diff --git a/regression/verilog/preprocessor/include1b.v b/regression/verilog/preprocessor/include1b.v new file mode 100644 index 000000000..255fd89de --- /dev/null +++ b/regression/verilog/preprocessor/include1b.v @@ -0,0 +1,2 @@ +line b 1 +line b 2 diff --git a/src/verilog/verilog_preprocessor_tokenizer.cpp b/src/verilog/verilog_preprocessor_tokenizer.cpp index 1e70f1468..e9ae9c5bb 100644 --- a/src/verilog/verilog_preprocessor_tokenizer.cpp +++ b/src/verilog/verilog_preprocessor_tokenizer.cpp @@ -88,13 +88,19 @@ verilog_preprocessor_tokenizert::verilog_preprocessor_tokenizert( std::size_t verilog_preprocessor_tokenizert::yy_input(char *buffer, std::size_t max_size) { - std::size_t result; - for(result = 0; result < max_size; result++) + std::size_t result = 0; + while(result < max_size) { char ch; if(!in.get(ch)) - return result; // eof - buffer[result] = ch; + break; // eof + buffer[result++] = ch; + if(ch == '\n') + { + // We need to abort prematurely to enable + // switching input streams on `include. + break; + } } return result; } From a339806b9e5d114d45578600c635885ff1b092cb Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Mon, 25 Sep 2023 17:54:24 -0700 Subject: [PATCH 2/2] Verilog preprocessor: fix line number reporting when including This changes reporting of the line numbers when including to a more idiomatic variant that avoids repeating the same line number for the file that contains the include directive. --- regression/verilog/preprocessor/include1.desc | 3 +- src/verilog/verilog_preprocessor.cpp | 55 ++++++++----------- src/verilog/verilog_preprocessor.h | 2 +- 3 files changed, 24 insertions(+), 36 deletions(-) diff --git a/regression/verilog/preprocessor/include1.desc b/regression/verilog/preprocessor/include1.desc index dca79f457..f62a87cae 100644 --- a/regression/verilog/preprocessor/include1.desc +++ b/regression/verilog/preprocessor/include1.desc @@ -7,8 +7,7 @@ activate-multi-line-match `line 1 "include1b.v" 1 line b 1 line b 2 -`line 1 "include1.v" 2 - +`line 2 "include1.v" 2 line 2 line 3 ^EXIT=0$ diff --git a/src/verilog/verilog_preprocessor.cpp b/src/verilog/verilog_preprocessor.cpp index 6bdc2681d..7b5072708 100644 --- a/src/verilog/verilog_preprocessor.cpp +++ b/src/verilog/verilog_preprocessor.cpp @@ -98,45 +98,19 @@ Function: verilog_preprocessort::include \*******************************************************************/ -void verilog_preprocessort::include(const std::string &filename) +std::string +verilog_preprocessort::find_include_file(const std::string &filename) { // first try filename as is - { -#ifdef _MSC_VER - auto in = new std::ifstream(widen(filename)); -#else - auto in = new std::ifstream(filename); -#endif - - if(*in) - { - context_stack.emplace_back(true, in, filename); - context().print_line_directive(out, 1); // 'enter' - return; // done - } - else - delete in; - } + if(file_exists(filename)) + return filename; // done // try include paths in given order for(const auto &path : config.verilog.include_paths) { auto full_name = concat_dir_file(path, filename); - -#ifdef _MSC_VER - auto in = new std::ifstream(widen(full_name)); -#else - auto in = new std::ifstream(full_name); -#endif - - if(*in) - { - context_stack.emplace_back(true, in, filename); - context().print_line_directive(out, 1); // 'enter' - return; // done - } - - delete in; + if(file_exists(full_name)) + return full_name; // done } throw verilog_preprocessor_errort() @@ -486,8 +460,23 @@ void verilog_preprocessort::directive() // strip quotes off string literal, escaping, etc. auto filename = file_token.string_literal_value(); + auto full_path = find_include_file(filename); + +#ifdef _MSC_VER + auto in = new std::ifstream(widen(full_path)); +#else + auto in = new std::ifstream(full_path); +#endif + + if(!*in) + throw verilog_preprocessor_errort() << "failed to open an include file"; + tokenizer().skip_until_eol(); - include(filename); + tokenizer().next_token(); // eat the \n + + context_stack.emplace_back(true, in, filename); + context().print_line_directive(out, 1); // 'enter' + // we now continue in the new context } else if(text=="resetall") { diff --git a/src/verilog/verilog_preprocessor.h b/src/verilog/verilog_preprocessor.h index ed55645f1..7ed75f45b 100644 --- a/src/verilog/verilog_preprocessor.h +++ b/src/verilog/verilog_preprocessor.h @@ -44,7 +44,7 @@ class verilog_preprocessort:public preprocessort definest defines; void directive(); - void include(const std::string &filename); + std::string find_include_file(const std::string &filename); definet::parameterst parse_define_parameters(); using define_argumentst = std::map>;