Added make_temp_{file,dir}() and remove_directory() APIs
authorClifford Wolf <clifford@clifford.at>
Sun, 12 Oct 2014 10:11:57 +0000 (12:11 +0200)
committerClifford Wolf <clifford@clifford.at>
Sun, 12 Oct 2014 10:11:57 +0000 (12:11 +0200)
frontends/vhdl2verilog/vhdl2verilog.cc
kernel/yosys.cc
kernel/yosys.h
passes/abc/abc.cc

index 3895ecfd2d3171341eb079c1b85c90caba347810..39b4f14960411c0bccef9418eb25a481ac39c34a 100644 (file)
@@ -120,15 +120,8 @@ struct Vhdl2verilogPass : public Pass {
                if (top_entity.empty())
                        log_cmd_error("Missing -top option.\n");
 
-#ifdef _WIN32
-               #warning Fixme: The vhdl2veriog command has not been ported to win32.
-               log_cmd_error("The vhdl2veriog command has not been ported to win32.\n");
-#else
-               char tempdir_name[] = "/tmp/yosys-vhdl2verilog-XXXXXX";
-               char *p = mkdtemp(tempdir_name);
-               log("Using temp directory %s.\n", tempdir_name);
-               if (p == NULL)
-                       log_error("For some reason mkdtemp() failed!\n");
+               std::string tempdir_name = make_temp_dir("/tmp/yosys-vhdl2verilog-XXXXXX");
+               log("Using temp directory %s.\n", tempdir_name.c_str());
 
                if (!out_file.empty() && out_file[0] != '/') {
                        char pwd[PATH_MAX];
@@ -139,7 +132,7 @@ struct Vhdl2verilogPass : public Pass {
                        out_file = pwd + ("/" + out_file);
                }
 
-               FILE *f = fopen(stringf("%s/files.list", tempdir_name).c_str(), "wt");
+               FILE *f = fopen(stringf("%s/files.list", tempdir_name.c_str()).c_str(), "wt");
                while (argidx < args.size()) {
                        std::string file = args[argidx++];
                        if (file.empty())
@@ -160,7 +153,7 @@ struct Vhdl2verilogPass : public Pass {
                std::string command = "exec 2>&1; ";
                if (!vhdl2verilog_dir.empty())
                        command += stringf("cd '%s'; . ./setup_env.sh; ", vhdl2verilog_dir.c_str());
-               command += stringf("cd '%s'; vhdl2verilog -out '%s' -filelist files.list -top '%s'%s", tempdir_name,
+               command += stringf("cd '%s'; vhdl2verilog -out '%s' -filelist files.list -top '%s'%s", tempdir_name.c_str(),
                                out_file.empty() ? "vhdl2verilog_output.v" : out_file.c_str(), top_entity.c_str(), extra_opts.c_str());
 
                log("Running '%s'..\n", command.c_str());
@@ -171,18 +164,15 @@ struct Vhdl2verilogPass : public Pass {
 
                if (out_file.empty()) {
                        std::ifstream ff;
-                       ff.open(stringf("%s/vhdl2verilog_output.v", tempdir_name).c_str());
+                       ff.open(stringf("%s/vhdl2verilog_output.v", tempdir_name.c_str()).c_str());
                        if (ff.fail())
                                log_error("Can't open vhdl2verilog output file `vhdl2verilog_output.v'.\n");
-                       Frontend::frontend_call(design, &ff, stringf("%s/vhdl2verilog_output.v", tempdir_name), "verilog");
+                       Frontend::frontend_call(design, &ff, stringf("%s/vhdl2verilog_output.v", tempdir_name.c_str()), "verilog");
                }
 
-               log_header("Removing temp directory `%s':\n", tempdir_name);
-               if (run_command(stringf("rm -rf '%s'", tempdir_name).c_str()) != 0)
-                       log_error("Execution of \"rm -rf '%s'\" failed!\n", tempdir_name);
-
+               log_header("Removing temp directory `%s':\n", tempdir_name.c_str());
+               remove_directory(tempdir_name);
                log_pop();
-#endif
        }
 } Vhdl2verilogPass;
  
index 50da13ae74bb7e8ac7a4953d423e7821340f5f8e..4af3ff9c0dcf9c84bbcdd6770dc81ff3af8757b8 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <unistd.h>
 #include <limits.h>
+#include <dirent.h>
 #include <errno.h>
 
 YOSYS_NAMESPACE_BEGIN
@@ -204,7 +205,96 @@ int run_command(const std::string &command, std::function<void(const std::string
        int ret = pclose(f);
        if (ret < 0)
                return -1;
+#ifdef _WIN32
+       return ret;
+#else
        return WEXITSTATUS(ret);
+#endif
+}
+
+std::string make_temp_file(std::string template_str)
+{
+#ifdef _WIN32
+       if (template_str.rfind("/tmp/", 0) == 0) {
+               char path[MAX_PATH+1];
+               GetTempPath(MAX_PATH+1, path);
+               template_str = stringf("%s\\%s", path, template_str.c_str() + 5);
+       }
+
+       size_t pos = template_str.rfind("XXXXXX");
+       log_assert(pos != std::string::npos);
+
+       while (1) {
+               for (int i = 0; i < 6; i++) {
+                       static std::string y = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+                       static uint32_t x = 314159265 ^ time(NULL);
+                       x ^= x << 13, x ^= x >> 17, x ^= x << 5;
+                       template_str[pos+i] = y[x % y.size()];
+               }
+               if (access(template_str.c_str(), F_OK) != 0)
+                       break;
+       }
+#else
+       size_t pos = template_str.rfind("XXXXXX");
+       log_assert(pos != std::string::npos);
+
+       int suffixlen = GetSize(template_str) - pos - 6;
+
+       char *p = strdup(template_str.c_str());
+       close(mkstemps(p, suffixlen));
+       template_str = p;
+       free(p);
+#endif
+
+       return template_str;
+}
+
+std::string make_temp_dir(std::string template_str)
+{
+#ifdef _WIN32
+       template_str = make_temp_file(template_str);
+       mkdir(template_str.c_str());
+       return template_str;
+#else
+       size_t pos = template_str.rfind("XXXXXX");
+       log_assert(pos != std::string::npos);
+
+       int suffixlen = GetSize(template_str) - pos - 6;
+       log_assert(suffixlen == 0);
+
+       char *p = strdup(template_str.c_str());
+       mkdtemp(p, suffixlen);
+       template_str = p;
+       free(p);
+
+       return template_str;
+#endif
+}
+
+void remove_directory(std::string dirname)
+{
+#ifdef _WIN32
+       run_command(stringf("rmdir /s /q \"%s\"", dirname.c_str()));
+#else
+       struct stat stbuf;
+       struct dirent **namelist;
+       int n = scandir(dirname.c_str(), &namelist, nullptr, alphasort);
+       log_assert(n >= 0);
+       for (int i = 0; i < n; i++) {
+               if (strcmp(namelist[i]->d_name, ".") && strcmp(namelist[i]->d_name, "..")) {
+                       buffer = stringf("%s/%s", dirname.c_str(), namelist[i]->d_name);
+                       if (!stat(buffer.c_str(), &stbuf) && S_ISREG(stbuf.st_mode)) {
+                               log("Removing `%s'.\n", buffer.c_str());
+                               remove(buffer.c_str());
+                       } else
+                               remove_directory(buffer);
+               }
+               free(namelist[i]);
+       }
+       free(namelist);
+       log("Removing `%s'.\n", dirname.c_str());
+       rmdir(dirname.c_str());
+#endif
 }
 
 int GetSize(RTLIL::Wire *wire)
index fcf60f9f15355d8ece2a2f2fb1c5db7bc3517a41..e579e90d93c6bfaf920133ad6fbadae15937a3c3 100644 (file)
@@ -88,6 +88,9 @@ 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&)>());
+std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX");
+std::string make_temp_dir(std::string template_str = "/tmp/yosys_XXXXXX");
+void remove_directory(std::string dirname);
 
 template<typename T> int GetSize(const T &obj) { return obj.size(); }
 int GetSize(RTLIL::Wire *wire);
index 82ebead7135c87d44d60942bc6ebfa0570bc0a8a..c63867068f4732b8d70540b9ab18b031c8628bb7 100644 (file)
@@ -553,13 +553,11 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
        clk_polarity = true;
        clk_sig = RTLIL::SigSpec();
 
-       char tempdir_name[] = "/tmp/yosys-abc-XXXXXX";
+       std::string tempdir_name = "/tmp/yosys-abc-XXXXXX";
        if (!cleanup)
                tempdir_name[0] = tempdir_name[4] = '_';
-       char *p = mkdtemp(tempdir_name);
-       log_header("Extracting gate netlist of module `%s' to `%s/input.blif'..\n", module->name.c_str(), tempdir_name);
-       if (p == NULL)
-               log_error("For some reason mkdtemp() failed!\n");
+       tempdir_name = make_temp_dir(tempdir_name);
+       log_header("Extracting gate netlist of module `%s' to `%s/input.blif'..\n", module->name.c_str(), tempdir_name.c_str());
 
        std::string abc_command;
        if (!script_file.empty()) {
@@ -589,10 +587,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                for (size_t i = 0; i+1 < abc_command.size(); i++)
                        if (abc_command[i] == ';' && abc_command[i+1] == ' ')
                                abc_command[i+1] = '\n';
-               FILE *f = fopen(stringf("%s/abc.script", tempdir_name).c_str(), "wt");
+               FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt");
                fprintf(f, "%s\n", abc_command.c_str());
                fclose(f);
-               abc_command = stringf("source %s/abc.script", tempdir_name);
+               abc_command = stringf("source %s/abc.script", tempdir_name.c_str());
        }
 
        if (clk_str.empty()) {
@@ -653,7 +651,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
        
        handle_loops();
 
-       std::string buffer = stringf("%s/input.blif", tempdir_name);
+       std::string buffer = stringf("%s/input.blif", tempdir_name.c_str());
        FILE *f = fopen(buffer.c_str(), "wt");
        if (f == NULL)
                log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
@@ -764,7 +762,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
        {
                log_header("Executing ABC.\n");
 
-               buffer = stringf("%s/stdcells.genlib", tempdir_name);
+               buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str());
                f = fopen(buffer.c_str(), "wt");
                if (f == NULL)
                        log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
@@ -786,7 +784,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                fclose(f);
 
                if (lut_mode) {
-                       buffer = stringf("%s/lutdefs.txt", tempdir_name);
+                       buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str());
                        f = fopen(buffer.c_str(), "wt");
                        if (f == NULL)
                                log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
@@ -798,18 +796,18 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                buffer = stringf("%s -s -c '", exe_file.c_str());
                if (!liberty_file.empty()) {
                        buffer += stringf("read_blif %s/input.blif; read_lib -w %s; ",
-                                       tempdir_name, liberty_file.c_str());
+                                       tempdir_name.c_str(), liberty_file.c_str());
                        if (!constr_file.empty())
                                buffer += stringf("read_constr -v %s; ", constr_file.c_str());
                        buffer += abc_command + "; ";
                } else
                if (lut_mode)
                        buffer += stringf("read_blif %s/input.blif; read_lut %s/lutdefs.txt; %s; ",
-                                       tempdir_name, tempdir_name, abc_command.c_str());
+                                       tempdir_name.c_str(), tempdir_name.c_str(), abc_command.c_str());
                else
                        buffer += stringf("read_blif %s/input.blif; read_library %s/stdcells.genlib; %s; ",
-                                       tempdir_name, tempdir_name, abc_command.c_str());
-               buffer += stringf("write_blif %s/output.blif' 2>&1", tempdir_name);
+                                       tempdir_name.c_str(), tempdir_name.c_str(), abc_command.c_str());
+               buffer += stringf("write_blif %s/output.blif' 2>&1", tempdir_name.c_str());
 
                log("%s\n", buffer.c_str());
 
@@ -818,7 +816,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                if (ret != 0)
                        log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
 
-               buffer = stringf("%s/%s", tempdir_name, "output.blif");
+               buffer = stringf("%s/%s", tempdir_name.c_str(), "output.blif");
                f = fopen(buffer.c_str(), "rt");
                if (f == NULL)
                        log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
@@ -991,22 +989,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
 
        if (cleanup)
        {
-               log_header("Removing temp directory `%s':\n", tempdir_name);
-
-               struct dirent **namelist;
-               int n = scandir(tempdir_name, &namelist, 0, alphasort);
-               log_assert(n >= 0);
-               for (int i = 0; i < n; i++) {
-                       if (strcmp(namelist[i]->d_name, ".") && strcmp(namelist[i]->d_name, "..")) {
-                               buffer = stringf("%s/%s", tempdir_name, namelist[i]->d_name);
-                               log("Removing `%s'.\n", buffer.c_str());
-                               remove(buffer.c_str());
-                       }
-                       free(namelist[i]);
-               }
-               free(namelist);
-               log("Removing `%s'.\n", tempdir_name);
-               rmdir(tempdir_name);
+               log_header("Removing temp directory `%s':\n", tempdir_name.c_str());
+               remove_directory(tempdir_name);
        }
 
        log_pop();