From: Clifford Wolf Date: Sun, 12 Oct 2014 08:57:15 +0000 (+0200) Subject: Added run_command() api to replace system() and popen() X-Git-Tag: yosys-0.4~61 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b1596bc0e7e5269fd610508f608f65f3aa696bd9;p=yosys.git Added run_command() api to replace system() and popen() --- diff --git a/frontends/vhdl2verilog/vhdl2verilog.cc b/frontends/vhdl2verilog/vhdl2verilog.cc index a8c411c7b..3895ecfd2 100644 --- a/frontends/vhdl2verilog/vhdl2verilog.cc +++ b/frontends/vhdl2verilog/vhdl2verilog.cc @@ -165,20 +165,9 @@ struct Vhdl2verilogPass : public Pass { log("Running '%s'..\n", command.c_str()); - errno = ENOMEM; // popen does not set errno if memory allocation fails, therefore set it by hand - f = popen(command.c_str(), "r"); - if (f == NULL) - log_error("Opening pipe to `%s' for reading failed: %s\n", command.c_str(), strerror(errno)); - - char logbuf[1024]; - while (fgets(logbuf, 1024, f) != NULL) - log("%s", logbuf); - - int ret = pclose(f); - if (ret < 0) - log_error("Closing pipe to `%s' failed: %s\n", command.c_str(), strerror(errno)); - if (WEXITSTATUS(ret) != 0) - log_error("Execution of command \"%s\" failed: the shell returned %d\n", command.c_str(), WEXITSTATUS(ret)); + int ret = run_command(command, [](const std::string &line) { log("%s", line.c_str()); }); + if (ret != 0) + log_error("Execution of command \"%s\" failed: return code %d.\n", command.c_str(), ret); if (out_file.empty()) { std::ifstream ff; @@ -189,7 +178,7 @@ struct Vhdl2verilogPass : public Pass { } log_header("Removing temp directory `%s':\n", tempdir_name); - if (system(stringf("rm -rf '%s'", tempdir_name).c_str()) != 0) + if (run_command(stringf("rm -rf '%s'", tempdir_name).c_str()) != 0) log_error("Execution of \"rm -rf '%s'\" failed!\n", tempdir_name); log_pop(); diff --git a/kernel/register.cc b/kernel/register.cc index 9452eb355..33c129d83 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -159,7 +159,7 @@ void Pass::call(RTLIL::Design *design, std::string command) cmd_buf.back() == '\r' || cmd_buf.back() == '\n')) cmd_buf.resize(cmd_buf.size()-1); log_header("Shell command: %s\n", cmd_buf.c_str()); - int retCode = system(cmd_buf.c_str()); + int retCode = run_command(cmd_buf); if (retCode != 0) log_cmd_error("Shell command returned error code %d.\n", retCode); return; diff --git a/kernel/yosys.cc b/kernel/yosys.cc index a40ad4372..50da13ae7 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -182,6 +182,31 @@ int readsome(std::istream &f, char *s, int n) return rc; } +int run_command(const std::string &command, std::function process_line) +{ + if (!process_line) + return system(command.c_str()); + + FILE *f = popen(command.c_str(), "r"); + if (f == nullptr) + return -1; + + std::string line; + char logbuf[128]; + while (fgets(logbuf, 128, f) != NULL) { + line += logbuf; + if (!line.empty() && line.back() == '\n') + process_line(line), line.clear(); + } + if (!line.empty()) + process_line(line); + + int ret = pclose(f); + if (ret < 0) + return -1; + return WEXITSTATUS(ret); +} + int GetSize(RTLIL::Wire *wire) { return wire->width; diff --git a/kernel/yosys.h b/kernel/yosys.h index d38e60ceb..fcf60f9f1 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -87,6 +87,7 @@ std::string vstringf(const char *fmt, va_list ap); std::string next_token(std::string &text, const char *sep); bool patmatch(const char *pattern, const char *string); int readsome(std::istream &f, char *s, int n); +int run_command(const std::string &command, std::function process_line = std::function()); template int GetSize(const T &obj) { return obj.size(); } int GetSize(RTLIL::Wire *wire); diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 487894941..bc7ccc065 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -86,16 +86,16 @@ struct gate_t RTLIL::SigBit bit; }; -static int map_autoidx; -static SigMap assign_map; -static RTLIL::Module *module; -static std::vector signal_list; -static std::map signal_map; +int map_autoidx; +SigMap assign_map; +RTLIL::Module *module; +std::vector signal_list; +std::map signal_map; -static bool clk_polarity; -static RTLIL::SigSpec clk_sig; +bool clk_polarity; +RTLIL::SigSpec clk_sig; -static int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, int in2 = -1, int in3 = -1, int in4 = -1) +int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, int in2 = -1, int in3 = -1, int in4 = -1) { assign_map.apply(bit); @@ -129,14 +129,14 @@ static int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in return gate.id; } -static void mark_port(RTLIL::SigSpec sig) +void mark_port(RTLIL::SigSpec sig) { for (auto &bit : assign_map(sig)) if (bit.wire != NULL && signal_map.count(bit) > 0) signal_list[signal_map[bit]].is_port = true; } -static void extract_cell(RTLIL::Cell *cell, bool keepff) +void extract_cell(RTLIL::Cell *cell, bool keepff) { if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_") { @@ -278,14 +278,14 @@ static void extract_cell(RTLIL::Cell *cell, bool keepff) } } -static std::string remap_name(RTLIL::IdString abc_name) +std::string remap_name(RTLIL::IdString abc_name) { std::stringstream sstr; sstr << "$abc$" << map_autoidx << "$" << abc_name.substr(1); return sstr.str(); } -static void dump_loop_graph(FILE *f, int &nr, std::map> &edges, std::set &workpool, std::vector &in_counts) +void dump_loop_graph(FILE *f, int &nr, std::map> &edges, std::set &workpool, std::vector &in_counts) { if (f == NULL) return; @@ -314,7 +314,7 @@ static void dump_loop_graph(FILE *f, int &nr, std::map> &edge fprintf(f, "}\n"); } -static void handle_loops() +void handle_loops() { // http://en.wikipedia.org/wiki/Topological_sorting // (Kahn, Arthur B. (1962), "Topological sorting of large networks") @@ -447,7 +447,7 @@ static void handle_loops() fclose(dot_f); } -static std::string add_echos_to_abc_cmd(std::string str) +std::string add_echos_to_abc_cmd(std::string str) { std::string new_str, token; for (size_t i = 0; i < str.size(); i++) { @@ -471,7 +471,7 @@ static std::string add_echos_to_abc_cmd(std::string str) return new_str; } -static std::string fold_abc_cmd(std::string str) +std::string fold_abc_cmd(std::string str) { std::string token, new_str = " "; int char_counter = 10; @@ -490,7 +490,56 @@ static std::string fold_abc_cmd(std::string str) return new_str; } -static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, +struct abc_output_filter +{ + bool got_cr; + int escape_seq_state; + std::string linebuf; + + abc_output_filter() + { + got_cr = false; + escape_seq_state = 0; + } + + void next_char(char ch) + { + if (escape_seq_state == 0 && ch == '\033') { + escape_seq_state = 1; + return; + } + if (escape_seq_state == 1) { + escape_seq_state = ch == '[' ? 2 : 0; + return; + } + if (escape_seq_state == 2) { + if ((ch < '0' || '9' < ch) && ch != ';') + escape_seq_state = 0; + return; + } + escape_seq_state = 0; + if (ch == '\r') { + got_cr = true; + return; + } + if (ch == '\n') { + log("ABC: %s\n", linebuf.c_str()); + got_cr = false, linebuf.clear(); + return; + } + if (got_cr) + got_cr = false, linebuf.clear(); + linebuf += ch; + } + + void next_line(const std::string &line) + { + for (char ch : line) + next_char(ch); + } +}; + +void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, std::string liberty_file, std::string constr_file, bool cleanup, int lut_mode, bool dff_mode, std::string clk_str, bool keepff, std::string delay_target, bool fast_mode) { @@ -767,62 +816,10 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std log("%s\n", buffer.c_str()); - errno = ENOMEM; // popen does not set errno if memory allocation fails, therefore set it by hand - f = popen(buffer.c_str(), "r"); - if (f == NULL) - log_error("Opening pipe to `%s' for reading failed: %s\n", buffer.c_str(), strerror(errno)); -#if 0 - char logbuf[1024]; - while (fgets(logbuf, 1024, f) != NULL) - log("ABC: %s", logbuf); -#else - bool got_cr = false; - int escape_seq_state = 0; - std::string linebuf; - char logbuf[1024]; - while (fgets(logbuf, 1024, f) != NULL) - for (char *p = logbuf; *p; p++) { - if (escape_seq_state == 0 && *p == '\033') { - escape_seq_state = 1; - continue; - } - if (escape_seq_state == 1) { - escape_seq_state = *p == '[' ? 2 : 0; - continue; - } - if (escape_seq_state == 2) { - if ((*p < '0' || '9' < *p) && *p != ';') - escape_seq_state = 0; - continue; - } - escape_seq_state = 0; - if (*p == '\r') { - got_cr = true; - continue; - } - if (*p == '\n') { - log("ABC: %s\n", linebuf.c_str()); - got_cr = false, linebuf.clear(); - continue; - } - if (got_cr) - got_cr = false, linebuf.clear(); - linebuf += *p; - } - if (!linebuf.empty()) - log("ABC: %s\n", linebuf.c_str()); -#endif - errno = 0; - int ret = pclose(f); - if (ret < 0) - log_error("Closing pipe to `%s' failed: %s\n", buffer.c_str(), strerror(errno)); - if (WEXITSTATUS(ret) != 0) { - switch (WEXITSTATUS(ret)) { - case 127: log_error("ABC: execution of command \"%s\" failed: Command not found\n", exe_file.c_str()); break; - case 126: log_error("ABC: execution of command \"%s\" failed: Command not executable\n", exe_file.c_str()); break; - default: log_error("ABC: execution of command \"%s\" failed: the shell returned %d\n", exe_file.c_str(), WEXITSTATUS(ret)); break; - } - } + abc_output_filter filt; + int ret = run_command(buffer, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1)); + if (ret != 0) + log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); if (asprintf(&p, "%s/%s", tempdir_name, "output.blif") < 0) log_abort(); f = fopen(p, "rt"); @@ -1215,4 +1212,4 @@ struct AbcPass : public Pass { } } AbcPass; - PRIVATE_NAMESPACE_END +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index 1599879a1..c6335cb30 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -760,20 +760,20 @@ struct ShowPass : public Pass { if (format != "dot" && !format.empty()) { std::string cmd = stringf("dot -T%s -o '%s' '%s'", format.c_str(), out_file.c_str(), dot_file.c_str()); log("Exec: %s\n", cmd.c_str()); - if (system(cmd.c_str()) != 0) + if (run_command(cmd) != 0) log_cmd_error("Shell command failed!\n"); } if (!viewer_exe.empty()) { std::string cmd = stringf("%s '%s' &", viewer_exe.c_str(), out_file.c_str()); log("Exec: %s\n", cmd.c_str()); - if (system(cmd.c_str()) != 0) + if (run_command(cmd) != 0) log_cmd_error("Shell command failed!\n"); } else if (format.empty()) { std::string cmd = stringf("fuser -s '%s' || xdot '%s' < '%s' &", dot_file.c_str(), dot_file.c_str(), dot_file.c_str()); log("Exec: %s\n", cmd.c_str()); - if (system(cmd.c_str()) != 0) + if (run_command(cmd) != 0) log_cmd_error("Shell command failed!\n"); }