Added run_command() api to replace system() and popen()
authorClifford Wolf <clifford@clifford.at>
Sun, 12 Oct 2014 08:57:15 +0000 (10:57 +0200)
committerClifford Wolf <clifford@clifford.at>
Sun, 12 Oct 2014 08:57:15 +0000 (10:57 +0200)
frontends/vhdl2verilog/vhdl2verilog.cc
kernel/register.cc
kernel/yosys.cc
kernel/yosys.h
passes/abc/abc.cc
passes/cmds/show.cc

index a8c411c7b000ec1ac35574b0efe9ae2eaf89b53d..3895ecfd2d3171341eb079c1b85c90caba347810 100644 (file)
@@ -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();
index 9452eb3554ed0f1a0185724ea6bea54255cd0ee5..33c129d837a26a08b08c5d29d135d04b33e7a37b 100644 (file)
@@ -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;
index a40ad4372fb4ad5b300c64bb3839b551f2ede86b..50da13ae74bb7e8ac7a4953d423e7821340f5f8e 100644 (file)
@@ -182,6 +182,31 @@ int readsome(std::istream &f, char *s, int n)
        return rc;
 }
 
+int run_command(const std::string &command, std::function<void(const std::string&)> 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;
index d38e60ceba53170b8a8d01638710ef3ab7e76c61..fcf60f9f15355d8ece2a2f2fb1c5db7bc3517a41 100644 (file)
@@ -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<void(const std::string&)> process_line = std::function<void(const std::string&)>());
 
 template<typename T> int GetSize(const T &obj) { return obj.size(); }
 int GetSize(RTLIL::Wire *wire);
index 487894941dea18a2d6d3e779c257c828c3ba2a0f..bc7ccc06524fdb616c12c93414e69bfcd55201c7 100644 (file)
@@ -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<gate_t> signal_list;
-static std::map<RTLIL::SigBit, int> signal_map;
+int map_autoidx;
+SigMap assign_map;
+RTLIL::Module *module;
+std::vector<gate_t> signal_list;
+std::map<RTLIL::SigBit, int> 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<int, std::set<int>> &edges, std::set<int> &workpool, std::vector<int> &in_counts)
+void dump_loop_graph(FILE *f, int &nr, std::map<int, std::set<int>> &edges, std::set<int> &workpool, std::vector<int> &in_counts)
 {
        if (f == NULL)
                return;
@@ -314,7 +314,7 @@ static void dump_loop_graph(FILE *f, int &nr, std::map<int, std::set<int>> &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
index 1599879a12fc8444c43af21cee0c020ac4144122..c6335cb301d114c587b120e14268ce011fe72b22 100644 (file)
@@ -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");
                }