From 0505c604e70c6d9621eb6ace6a9d8a3a5ac71eaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Tue, 30 Mar 2021 01:15:49 +0200 Subject: preproc: Fix up conditional handling. Fixes #2710. Fixes #2711. --- frontends/verilog/preproc.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'frontends/verilog/preproc.cc') diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index 84966e501..568224da2 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -726,8 +726,16 @@ frontend_verilog_preproc(std::istream &f, defines.merge(global_defines_cache); std::vector filename_stack; + // We are inside pass_level levels of satisfied ifdefs, and then within + // fail_level levels of unsatisfied ifdefs. The unsatisfied ones are + // always within satisfied ones — even if some condition within is true, + // the parent condition failing renders it moot. int ifdef_fail_level = 0; int ifdef_pass_level = 0; + // For the outermost unsatisfied ifdef, true iff that ifdef already + // had a satisfied branch, and further elsif/else branches should be + // considered unsatisfied even if the condition is true. + // Meaningless if ifdef_fail_level == 0. bool ifdef_already_satisfied = false; output_code.clear(); @@ -745,7 +753,7 @@ frontend_verilog_preproc(std::istream &f, if (ifdef_fail_level > 0) ifdef_fail_level--; else if (ifdef_pass_level > 0) - ifdef_already_satisfied = --ifdef_pass_level; + ifdef_pass_level--; else log_error("Found %s outside of macro conditional branch!\n", tok.c_str()); continue; @@ -755,8 +763,9 @@ frontend_verilog_preproc(std::istream &f, if (ifdef_fail_level == 0) { if (ifdef_pass_level == 0) log_error("Found %s outside of macro conditional branch!\n", tok.c_str()); - log_assert(ifdef_already_satisfied); + ifdef_pass_level--; ifdef_fail_level = 1; + ifdef_already_satisfied = true; } else if (ifdef_fail_level == 1 && !ifdef_already_satisfied) { ifdef_fail_level = 0; ifdef_pass_level++; @@ -771,8 +780,9 @@ frontend_verilog_preproc(std::istream &f, if (ifdef_fail_level == 0) { if (ifdef_pass_level == 0) log_error("Found %s outside of macro conditional branch!\n", tok.c_str()); - log_assert(ifdef_already_satisfied); + ifdef_pass_level--; ifdef_fail_level = 1; + ifdef_already_satisfied = true; } else if (ifdef_fail_level == 1 && !ifdef_already_satisfied && defines.find(name)) { ifdef_fail_level = 0; ifdef_pass_level++; @@ -931,6 +941,10 @@ frontend_verilog_preproc(std::istream &f, output_code.push_back(tok); } + if (ifdef_fail_level > 0 || ifdef_pass_level > 0) { + log_error("Unterminated preprocessor conditional!\n"); + } + std::string output; for (auto &str : output_code) output += str; -- cgit v1.2.3 From 72787f52fc31954e4b7dc3dc34d86705fc4e9dd1 Mon Sep 17 00:00:00 2001 From: Claire Xenia Wolf Date: Tue, 8 Jun 2021 00:39:36 +0200 Subject: Fixing old e-mail addresses and deadnames s/((Claire|Xen|Xenia|Clifford)\s+)+(Wolf|Xen)\s+<(claire|clifford)@(symbioticeda.com|clifford.at|yosyshq.com)>/Claire Xenia Wolf /gi; s/((Nina|Nak|N\.)\s+)+Engelhardt\s+/N. Engelhardt /gi; s/((David)\s+)+Shah\s+<(dave|david)@(symbioticeda.com|yosyshq.com|ds0.me)>/David Shah /gi; s/((Miodrag)\s+)+Milanovic\s+<(miodrag|micko)@(symbioticeda.com|yosyshq.com)>/Miodrag Milanovic /gi; s,https?://www.clifford.at/yosys/,http://yosyshq.net/yosys/,g; --- frontends/verilog/preproc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends/verilog/preproc.cc') diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index 568224da2..4b9ebe0aa 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -1,7 +1,7 @@ /* * yosys -- Yosys Open SYnthesis Suite * - * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2012 Claire Xenia Wolf * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above -- cgit v1.2.3 From 3156226233133f5da9dba15c63ca560b4794b831 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Thu, 15 Jul 2021 10:36:50 -0400 Subject: verilog: save and restore overwritten macro arguments --- frontends/verilog/preproc.cc | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'frontends/verilog/preproc.cc') diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index 4b9ebe0aa..17f567587 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -36,6 +36,7 @@ #include "verilog_frontend.h" #include "kernel/log.h" #include +#include #include #include #include @@ -334,6 +335,11 @@ define_map_t::add(const std::string &name, const std::string &txt, const arg_map defines[name] = std::unique_ptr(new define_body_t(txt, args)); } +void define_map_t::add(const std::string &name, const define_body_t &body) +{ + defines[name] = std::unique_ptr(new define_body_t(body)); +} + void define_map_t::merge(const define_map_t &map) { for (const auto &pr : map.defines) { @@ -440,7 +446,17 @@ static bool read_argument(std::string &dest) } } -static bool try_expand_macro(define_map_t &defines, std::string &tok) +using macro_arg_stack_t = std::stack>; + +static void restore_macro_arg(define_map_t &defines, macro_arg_stack_t ¯o_arg_stack) +{ + log_assert(!macro_arg_stack.empty()); + auto &overwritten_arg = macro_arg_stack.top(); + defines.add(overwritten_arg.first, overwritten_arg.second); + macro_arg_stack.pop(); +} + +static bool try_expand_macro(define_map_t &defines, macro_arg_stack_t ¯o_arg_stack, std::string &tok) { if (tok == "`\"") { std::string literal("\""); @@ -450,7 +466,7 @@ static bool try_expand_macro(define_map_t &defines, std::string &tok) if (ntok == "`\"") { insert_input(literal+"\""); return true; - } else if (!try_expand_macro(defines, ntok)) { + } else if (!try_expand_macro(defines, macro_arg_stack, ntok)) { literal += ntok; } } @@ -495,6 +511,10 @@ static bool try_expand_macro(define_map_t &defines, std::string &tok) args.push_back(arg); } for (const auto &pr : body->args.get_vals(name, args)) { + if (const define_body_t *existing = defines.find(pr.first)) { + macro_arg_stack.push({pr.first, *existing}); + insert_input("`__restore_macro_arg "); + } defines.add(pr.first, pr.second); } } else { @@ -725,6 +745,7 @@ frontend_verilog_preproc(std::istream &f, defines.merge(pre_defines); defines.merge(global_defines_cache); + macro_arg_stack_t macro_arg_stack; std::vector filename_stack; // We are inside pass_level levels of satisfied ifdefs, and then within // fail_level levels of unsatisfied ifdefs. The unsatisfied ones are @@ -828,7 +849,7 @@ frontend_verilog_preproc(std::istream &f, if (tok == "`include") { skip_spaces(); std::string fn = next_token(true); - while (try_expand_macro(defines, fn)) { + while (try_expand_macro(defines, macro_arg_stack, fn)) { fn = next_token(); } while (1) { @@ -935,7 +956,12 @@ frontend_verilog_preproc(std::istream &f, continue; } - if (try_expand_macro(defines, tok)) + if (tok == "`__restore_macro_arg") { + restore_macro_arg(defines, macro_arg_stack); + continue; + } + + if (try_expand_macro(defines, macro_arg_stack, tok)) continue; output_code.push_back(tok); -- cgit v1.2.3 From 4cd2f03e36d09f936d39f8499e26fb0a2bc897f9 Mon Sep 17 00:00:00 2001 From: Thomas Sailer Date: Wed, 25 Aug 2021 21:34:26 +0200 Subject: preprocessor: do not destroy double slash escaped identifiers The preprocessor currently destroys double slash containing escaped identifiers (for example \a//b ). This is due to next_token trying to convert single line comments (//) into /* */ comments. This then leads to an unintuitive error message like this: ERROR: syntax error, unexpected '*' This patch fixes the error by recognizing escaped identifiers and returning them as single token. It also adds a testcase. --- frontends/verilog/preproc.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'frontends/verilog/preproc.cc') diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index 17f567587..883531e78 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -142,6 +142,16 @@ static std::string next_token(bool pass_newline = false) return_char(ch); } } + else if (ch == '\\') + { + while ((ch = next_char()) != 0) { + if (ch < 33 || ch > 126) { + return_char(ch); + break; + } + token += ch; + } + } else if (ch == '/') { if ((ch = next_char()) != 0) { -- cgit v1.2.3