Added support for here documents
authorClifford Wolf <clifford@clifford.at>
Sat, 26 Jul 2014 15:21:40 +0000 (17:21 +0200)
committerClifford Wolf <clifford@clifford.at>
Sat, 26 Jul 2014 15:21:40 +0000 (17:21 +0200)
kernel/driver.cc
kernel/register.cc
kernel/register.h

index 3c185e44bd04b50449995c9aed278079422ff58c..97910aa98156756f2210dd4c889e7a3fcc8133b5 100644 (file)
@@ -28,6 +28,7 @@
 #include <errno.h>
 
 #include <algorithm>
+#include <exception>
 
 #include "kernel/rtlil.h"
 #include "kernel/register.h"
@@ -116,26 +117,37 @@ static void run_frontend(std::string filename, std::string command, RTLIL::Desig
                if (f == NULL)
                        log_error("Can't open script file `%s' for reading: %s\n", filename.c_str(), strerror(errno));
 
-               std::string command;
-               while (fgetline(f, command)) {
-                       while (!command.empty() && command[command.size()-1] == '\\') {
-                               std::string next_line;
-                               if (!fgetline(f, next_line))
-                                       break;
-                               command.resize(command.size()-1);
-                               command += next_line;
+               FILE *backup_script_file = Frontend::current_script_file;
+               Frontend::current_script_file = f;
+
+               try {
+                       std::string command;
+                       while (fgetline(f, command)) {
+                               while (!command.empty() && command[command.size()-1] == '\\') {
+                                       std::string next_line;
+                                       if (!fgetline(f, next_line))
+                                               break;
+                                       command.resize(command.size()-1);
+                                       command += next_line;
+                               }
+                               handle_label(command, from_to_active, run_from, run_to);
+                               if (from_to_active)
+                                       Pass::call(design, command);
                        }
-                       handle_label(command, from_to_active, run_from, run_to);
-                       if (from_to_active)
-                               Pass::call(design, command);
-               }
 
-               if (!command.empty()) {
-                       handle_label(command, from_to_active, run_from, run_to);
-                       if (from_to_active)
-                               Pass::call(design, command);
+                       if (!command.empty()) {
+                               handle_label(command, from_to_active, run_from, run_to);
+                               if (from_to_active)
+                                       Pass::call(design, command);
+                       }
+               }
+               catch (...) {
+                       Frontend::current_script_file = backup_script_file;
+                       std::rethrow_exception(std::current_exception());
                }
 
+               Frontend::current_script_file = backup_script_file;
+
                if (filename != "-")
                        fclose(f);
 
index e7ad7ef0504c3a4c14b97d5a1ccf42cb1c4ab518..59667ac975ca806aa5b7158c28ac8728deb36119 100644 (file)
@@ -276,6 +276,9 @@ void Frontend::execute(std::vector<std::string> args, RTLIL::Design *design)
        } while (!args.empty());
 }
 
+FILE *Frontend::current_script_file = NULL;
+std::string Frontend::last_here_document;
+
 void Frontend::extra_args(FILE *&f, std::string &filename, std::vector<std::string> args, size_t argidx)
 {
        bool called_with_fp = f != NULL;
@@ -291,7 +294,33 @@ void Frontend::extra_args(FILE *&f, std::string &filename, std::vector<std::stri
                        cmd_error(args, argidx, "Extra filename argument in direct file mode.");
 
                filename = arg;
-               f = fopen(filename.c_str(), "r");
+               if (filename == "<<" && argidx+1 < args.size())
+                       filename += args[++argidx];
+               if (filename.substr(0, 2) == "<<") {
+                       if (Frontend::current_script_file == NULL)
+                               log_error("Unexpected here document '%s' outside of script!\n", filename.c_str());
+                       if (filename.size() <= 2)
+                               log_error("Missing EOT marker in here document!\n");
+                       std::string eot_marker = filename.substr(2);
+                       last_here_document.clear();
+                       while (1) {
+                               std::string buffer;
+                               char block[4096];
+                               while (1) {
+                                       if (fgets(block, 4096, Frontend::current_script_file) == NULL)
+                                               log_error("Unexpected end of file in here document '%s'!\n", filename.c_str());
+                                       buffer += block;
+                                       if (buffer.size() > 0 && (buffer[buffer.size() - 1] == '\n' || buffer[buffer.size() - 1] == '\r'))
+                                               break;
+                               }
+                               int indent = buffer.find_first_not_of(" \t\r\n");
+                               if (buffer.substr(indent, eot_marker.size()) == eot_marker)
+                                       break;
+                               last_here_document += buffer;
+                       }
+                       f = fmemopen((void*)last_here_document.c_str(), last_here_document.size(), "r");
+               } else
+                       f = fopen(filename.c_str(), "r");
                if (f == NULL)
                        log_cmd_error("Can't open input file `%s' for reading: %s\n", filename.c_str(), strerror(errno));
 
index fd073cbe7deb7473f28a19290e26f8c63d18fd69..73875e96810a2c3881253942704ea1130300f670 100644 (file)
@@ -38,7 +38,7 @@ extern const char *yosys_version_str;
 extern RTLIL::Design *yosys_get_design();
 extern std::string proc_self_dirname();
 extern std::string proc_share_dirname();
-const char *create_prompt(RTLIL::Design *design, int recursion_counter);
+extern const char *create_prompt(RTLIL::Design *design, int recursion_counter);
 
 // from passes/cmds/design.cc
 extern std::map<std::string, RTLIL::Design*> saved_designs;
@@ -76,6 +76,10 @@ struct Pass
 
 struct Frontend : Pass
 {
+       // for reading of here documents
+       static FILE *current_script_file;
+       static std::string last_here_document;
+
        std::string frontend_name;
        Frontend(std::string name, std::string short_help = "** document me **");
        virtual void run_register();