aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/verilog/preproc.cc
diff options
context:
space:
mode:
authorcombinatorylogic <combinatorylogic@users.noreply.github.com>2017-09-21 18:25:02 +0100
committercombinatorylogic <combinatorylogic@users.noreply.github.com>2017-09-21 18:25:02 +0100
commit64ca0be9716e956879f3fc863177f28eb3faa172 (patch)
treed55a76a766308fc3e8b4cfbb91cd143ea7cac9f5 /frontends/verilog/preproc.cc
parent143c0abd33ed76b2a7e38dbbac1767e6f7edd68f (diff)
downloadyosys-64ca0be9716e956879f3fc863177f28eb3faa172.tar.gz
yosys-64ca0be9716e956879f3fc863177f28eb3faa172.tar.bz2
yosys-64ca0be9716e956879f3fc863177f28eb3faa172.zip
Adding support for string macros and macros with arguments after include
Diffstat (limited to 'frontends/verilog/preproc.cc')
-rw-r--r--frontends/verilog/preproc.cc110
1 files changed, 69 insertions, 41 deletions
diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc
index cf220fef9..67a6d18ea 100644
--- a/frontends/verilog/preproc.cc
+++ b/frontends/verilog/preproc.cc
@@ -182,15 +182,19 @@ static std::string next_token(bool pass_newline = false)
{
const char *ok = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789";
if (ch == '`' || strchr(ok, ch) != NULL)
- while ((ch = next_char()) != 0) {
- if (strchr(ok, ch) == NULL) {
- return_char(ch);
- break;
- }
+ {
+ ch = next_char();
+ if (ch == '"') {
token += ch;
- }
+ } else do {
+ if (strchr(ok, ch) == NULL) {
+ return_char(ch);
+ break;
+ }
+ token += ch;
+ } while ((ch = next_char()) != 0);
+ }
}
-
return token;
}
@@ -210,6 +214,59 @@ static void input_file(std::istream &f, std::string filename)
input_buffer.insert(it, "\n`file_pop\n");
}
+
+static bool try_expand_macro(std::set<std::string> &defines_with_args,
+ std::map<std::string, std::string> &defines_map,
+ std::string &tok
+ )
+{
+ if (tok == "`\"") {
+ std::string literal("\"");
+ // Expand string literal
+ while (!input_buffer.empty()) {
+ std::string ntok = next_token();
+ if (ntok == "`\"") {
+ insert_input(literal+"\"");
+ return true;
+ } else if (!try_expand_macro(defines_with_args, defines_map, ntok)) {
+ literal += ntok;
+ }
+ }
+ return false; // error - unmatched `"
+ } else if (tok.size() > 1 && tok[0] == '`' && defines_map.count(tok.substr(1)) > 0) {
+ std::string name = tok.substr(1);
+ // printf("expand: >>%s<< -> >>%s<<\n", name.c_str(), defines_map[name].c_str());
+ std::string skipped_spaces = skip_spaces();
+ tok = next_token(false);
+ if (tok == "(" && defines_with_args.count(name) > 0) {
+ int level = 1;
+ std::vector<std::string> args;
+ args.push_back(std::string());
+ while (1)
+ {
+ tok = next_token(true);
+ if (tok == ")" || tok == "}" || tok == "]")
+ level--;
+ if (level == 0)
+ break;
+ if (level == 1 && tok == ",")
+ args.push_back(std::string());
+ else
+ args.back() += tok;
+ if (tok == "(" || tok == "{" || tok == "[")
+ level++;
+ }
+ for (int i = 0; i < GetSize(args); i++)
+ defines_map[stringf("macro_%s_arg%d", name.c_str(), i+1)] = args[i];
+ } else {
+ insert_input(tok);
+ insert_input(skipped_spaces);
+ }
+ insert_input(defines_map[name]);
+ return true;
+ } else return false;
+}
+
std::string frontend_verilog_preproc(std::istream &f, std::string filename, const std::map<std::string, std::string> &pre_defines_map,
dict<std::string, std::pair<std::string, bool>> &global_defines_cache, const std::list<std::string> &include_dirs)
{
@@ -293,8 +350,9 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
if (tok == "`include") {
skip_spaces();
std::string fn = next_token(true);
- while (fn.size() > 1 && fn[0] == '`' && defines_map.count(fn.substr(1)) > 0)
- fn = defines_map.at(fn.substr(1));
+ while(try_expand_macro(defines_with_args, defines_map, fn)) {
+ fn = next_token();
+ }
while (1) {
size_t pos = fn.find('"');
if (pos == std::string::npos)
@@ -445,39 +503,9 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
continue;
}
- if (tok.size() > 1 && tok[0] == '`' && defines_map.count(tok.substr(1)) > 0) {
- std::string name = tok.substr(1);
- // printf("expand: >>%s<< -> >>%s<<\n", name.c_str(), defines_map[name].c_str());
- std::string skipped_spaces = skip_spaces();
- tok = next_token(false);
- if (tok == "(" && defines_with_args.count(name) > 0) {
- int level = 1;
- std::vector<std::string> args;
- args.push_back(std::string());
- while (1)
- {
- tok = next_token(true);
- if (tok == ")" || tok == "}" || tok == "]")
- level--;
- if (level == 0)
- break;
- if (level == 1 && tok == ",")
- args.push_back(std::string());
- else
- args.back() += tok;
- if (tok == "(" || tok == "{" || tok == "[")
- level++;
- }
- for (int i = 0; i < GetSize(args); i++)
- defines_map[stringf("macro_%s_arg%d", name.c_str(), i+1)] = args[i];
- } else {
- insert_input(tok);
- insert_input(skipped_spaces);
- }
- insert_input(defines_map[name]);
+ if (try_expand_macro(defines_with_args, defines_map, tok))
continue;
- }
-
+
output_code.push_back(tok);
}