std.pair <string, bool> process_line(string line_in) { bool line_cont = plib.pg.right(line_in, 1) == "\\"; string line = line_cont ? plib.pg.left(line_in, line_in.length() - 1) : line_in; if (m_state == state_e.LINE_CONTINUATION) { m_line += line; } else { m_line = line; } if (line_cont) { m_state = state_e.LINE_CONTINUATION; return(new std.pair <string, bool>("", false)); } m_state = state_e.PROCESS; line = process_comments(m_line); string lt = plib.pg.trim(plib.pg.replace_all(line, "\t", " ")); if (plib.pg.startsWith(lt, "#")) { ppreprocessor_string_list lti = plib.pg.psplit(lt, ' ', true); if (lti[0] == "#if") { m_if_level++; m_if_seen |= (1U << m_if_level); if (m_if_flag == 0) { lt = replace_macros(lt); simple_iter t = new simple_iter(this, tokenize(lt.substr(3), m_expr_sep, true, true)); //simple_iter<ppreprocessor> t(this, tokenize(lt.substr(3), m_expr_sep, true, true)); var val = (int)prepro_expr(t, 255); t.skip_ws(); if (!t.eod()) { error("found unprocessed content at end of line"); } if (val == 0) { m_if_flag |= (1U << m_if_level); } else { m_elif |= (1U << m_if_level); } } } else if (lti[0] == "#ifdef") { m_if_level++; m_if_seen |= (1U << m_if_level); if (get_define(lti[1]) == null) { m_if_flag |= (1U << m_if_level); } else { m_elif |= (1U << m_if_level); } } else if (lti[0] == "#ifndef") { m_if_level++; m_if_seen |= (1U << m_if_level); if (get_define(lti[1]) != null) { m_if_flag |= (1U << m_if_level); } else { m_elif |= (1U << m_if_level); } } else if (lti[0] == "#else") // basically #elif (1) { if ((m_if_seen & (1U << m_if_level)) == 0) { error("#else without #if"); } if ((m_elif & (1U << m_if_level)) != 0) // elif disabled { m_if_flag |= (1U << m_if_level); } else { m_if_flag &= ~(1U << m_if_level); } m_elif |= (1U << m_if_level); } else if (lti[0] == "#elif") { if ((m_if_seen & (1U << m_if_level)) == 0) { error("#elif without #if"); } //if ((m_if_flag & (1 << m_if_level)) == 0) // m_if_flag ^= (1 << m_if_level); if ((m_elif & (1U << m_if_level)) != 0) // elif disabled { m_if_flag |= (1U << m_if_level); } else { m_if_flag &= ~(1U << m_if_level); } if (m_if_flag == 0) { //m_if_flag ^= (1 << m_if_level); lt = replace_macros(lt); simple_iter t = new simple_iter(this, tokenize(lt.substr(5), m_expr_sep, true, true)); //simple_iter<ppreprocessor> t(this, tokenize(lt.substr(5), m_expr_sep, true, true)); var val = (int)prepro_expr(t, 255); t.skip_ws(); if (!t.eod()) { error("found unprocessed content at end of line"); } if (val == 0) { m_if_flag |= (1U << m_if_level); } else { m_elif |= (1U << m_if_level); } } } else if (lti[0] == "#endif") { if ((m_if_seen & (1U << m_if_level)) == 0) { error("#else without #if"); } m_if_seen &= ~(1U << m_if_level); m_elif &= ~(1U << m_if_level); m_if_flag &= ~(1U << m_if_level); m_if_level--; } else if (lti[0] == "#include") { if (m_if_flag == 0) { string arg = ""; for (size_t i = 1; i < lti.size(); i++) { arg += (lti[i] + " "); } arg = plib.pg.trim(arg); if (plib.pg.startsWith(arg, "\"") && plib.pg.endsWith(arg, "\"")) { arg = arg.substr(1, arg.length() - 2); // first try local context var l = plib.util.buildpath(m_stack.back().m_local_path, arg); var lstrm = m_sources.get_stream(l); if (!lstrm.empty()) { m_stack.emplace_back(new input_context(lstrm, plib.util.path(l), l)); //m_stack.emplace_back(input_context(lstrm.release_stream(), plib::util::path(l), l)); } else { var strm = m_sources.get_stream(arg); if (!strm.empty()) { m_stack.emplace_back(new input_context(strm, plib.util.path(arg), arg)); //m_stack.emplace_back(input_context(strm.release_stream(), plib::util::path(arg), arg)); } else { error("include not found:" + arg); } } } else { error("include misspelled:" + arg); } string linemarker = new pfmt("# {0} \"{1}\" 1\n").op(m_stack.back().m_lineno, m_stack.back().m_name); push_out(linemarker); } } else if (lti[0] == "#pragma") { if (m_if_flag == 0 && lti.size() > 3 && lti[1] == "NETLIST") { if (lti[2] == "warning") { error("NETLIST: " + catremainder(lti, 3, " ")); } } } else if (lti[0] == "#define") { if (m_if_flag == 0) { if (lti.size() < 2) { error("define needs at least one argument"); } simple_iter args = new simple_iter(this, tokenize(lt.substr(8), m_expr_sep, false, false)); //simple_iter<ppreprocessor> args(this, tokenize(lt.substr(8), m_expr_sep, false, false)); string n = args.next(); if (!is_valid_token(n)) { error("define expected identifier"); } var prevdef = get_define(n); if (lti.size() == 2) { if (prevdef != null && !prevdef.m_replace.empty()) { error("redefinition of " + n); } m_defines.insert(n, new define_t(n, "")); } else if (args.next_ws() == "(") { define_t def = new define_t(n); def.m_has_params = true; var token = args.next(); while (true) { if (token == ")") { break; } def.m_params.push_back(token); token = args.next(); if (token != "," && token != ")") { error(new pfmt("expected , or ), found <{0}>").op(token)); } if (token == ",") { token = args.next(); } } string r = ""; while (!args.eod()) { r += args.next_ws(); } def.m_replace = r; if (prevdef != null && prevdef.m_replace != r) { error("redefinition of " + n); } m_defines.insert(n, def); } else { string r = ""; while (!args.eod()) { r += args.next_ws(); } if (prevdef != null && prevdef.m_replace != r) { error("redefinition of " + n); } m_defines.insert(n, new define_t(n, r)); } } } else if (lti[0] == "#undef") { if (m_if_flag == 0) { if (lti.size() < 2) { error("undef needs at least one argument"); } simple_iter args = new simple_iter(this, tokenize(lt.substr(7), m_expr_sep, false, false)); //simple_iter<ppreprocessor> args(this, tokenize(lt.substr(7), m_expr_sep, false, false)); string n = args.next(); if (!is_valid_token(n)) { error("undef expected identifier"); } m_defines.erase(n); } } else { if (m_if_flag == 0) { error("unknown directive"); } } return(new std.pair <string, bool>("", false)); } if (m_if_flag == 0) { return(new std.pair <string, bool>(replace_macros(lt), true)); } return(new std.pair <string, bool>("", false)); }
string replace_macros(string line) { //std::vector<pstring> elems(psplit(line, m_expr_sep)); bool repeat = false; string tmpret = line; do { repeat = false; simple_iter elems = new simple_iter(this, tokenize(tmpret, m_expr_sep, false, true)); //simple_iter<ppreprocessor> elems(this, tokenize(tmpret, m_expr_sep, false, true)); tmpret = ""; while (!elems.eod()) { var token = elems.next_ws(); define_t def = get_define(token); if (def == null) { tmpret += token; } else if (!def.m_has_params) { tmpret += def.m_replace; repeat = true; } else { token = elems.next(); if (token != "(") { error("expected '(' in macro expansion of " + def.m_name); } ppreprocessor_string_list rep = new ppreprocessor_string_list(); token = elems.next(); while (token != ")") { string par = ""; int pcnt = 1; while (true) { if (pcnt == 1 && token == ",") { token = elems.next(); break; } if (token == "(") { pcnt++; } if (token == ")") { if (--pcnt == 0) { break; } } par += token; token = elems.next(); } rep.push_back(par); } repeat = true; if (def.m_params.size() != rep.size()) { error(new pfmt("Expected {0} parameters, got {1}").op(def.m_params.size(), rep.size())); } simple_iter r = new simple_iter(this, tokenize(def.m_replace, m_expr_sep, false, false)); //simple_iter<ppreprocessor> r(this, tokenize(def->m_replace, m_expr_sep, false, false)); bool stringify_next = false; while (!r.eod()) { token = r.next(); if (token == "#") { stringify_next = true; } else if (token != " " && token != "\t") { for (size_t i = 0; i < def.m_params.size(); i++) { if (def.m_params[i] == token) { if (stringify_next) { stringify_next = false; token = "\"" + rep[i] + "\""; } else { token = rep[i]; } break; } } if (stringify_next) { error("'#' is not followed by a macro parameter"); } tmpret += token; tmpret += " "; // make sure this is not concatenated with next token } else { tmpret += token; } } } } } while (repeat); return(tmpret); }