diff options
author | Clifford Wolf <clifford@clifford.at> | 2014-07-26 17:21:40 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2014-07-26 17:21:40 +0200 |
commit | 267c61564047f8768c29040f898633d9444a5404 (patch) | |
tree | 91fd6e4cbda4bf89f446c927bff27afac4ce7447 | |
parent | 3f4e3ca8ad480c2e73e2072ada77078ffd95e08f (diff) | |
download | yosys-267c61564047f8768c29040f898633d9444a5404.tar.gz yosys-267c61564047f8768c29040f898633d9444a5404.tar.bz2 yosys-267c61564047f8768c29040f898633d9444a5404.zip |
Added support for here documents
-rw-r--r-- | kernel/driver.cc | 44 | ||||
-rw-r--r-- | kernel/register.cc | 31 | ||||
-rw-r--r-- | kernel/register.h | 6 |
3 files changed, 63 insertions, 18 deletions
diff --git a/kernel/driver.cc b/kernel/driver.cc index 3c185e44b..97910aa98 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 e7ad7ef05..59667ac97 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 fd073cbe7..73875e968 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(); |