summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2014-07-26 17:21:40 +0200
committerClifford Wolf <clifford@clifford.at>2014-07-26 17:21:40 +0200
commit267c61564047f8768c29040f898633d9444a5404 (patch)
tree91fd6e4cbda4bf89f446c927bff27afac4ce7447
parent3f4e3ca8ad480c2e73e2072ada77078ffd95e08f (diff)
Added support for here documents
-rw-r--r--kernel/driver.cc44
-rw-r--r--kernel/register.cc31
-rw-r--r--kernel/register.h6
3 files changed, 63 insertions, 18 deletions
diff --git a/kernel/driver.cc b/kernel/driver.cc
index 3c185e44..97910aa9 100644
--- a/kernel/driver.cc
+++ b/kernel/driver.cc
@@ -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);
diff --git a/kernel/register.cc b/kernel/register.cc
index e7ad7ef0..59667ac9 100644
--- a/kernel/register.cc
+++ b/kernel/register.cc
@@ -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));
diff --git a/kernel/register.h b/kernel/register.h
index fd073cbe..73875e96 100644
--- a/kernel/register.h
+++ b/kernel/register.h
@@ -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();