diff options
Diffstat (limited to 'kernel/register.cc')
| -rw-r--r-- | kernel/register.cc | 187 |
1 files changed, 106 insertions, 81 deletions
diff --git a/kernel/register.cc b/kernel/register.cc index 226963fda..9ffb17c1a 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -108,7 +108,9 @@ Pass::Pass(std::string name, std::string short_help) : pass_name(name), short_he void Pass::run_register() { - log_assert(pass_register.count(pass_name) == 0); + if (pass_register.count(pass_name)) + log_error("Unable to register pass '%s', pass already exists!\n", pass_name.c_str()); + pass_register[pass_name] = this; } @@ -445,10 +447,13 @@ Frontend::Frontend(std::string name, std::string short_help) : void Frontend::run_register() { - log_assert(pass_register.count(pass_name) == 0); + if (pass_register.count(pass_name)) + log_error("Unable to register pass '%s', pass already exists!\n", pass_name.c_str()); pass_register[pass_name] = this; - log_assert(frontend_register.count(frontend_name) == 0); + if (frontend_register.count(frontend_name)) + log_error("Unable to register frontend '%s', frontend already exists!\n", frontend_name.c_str()); + frontend_register[frontend_name] = this; } @@ -526,10 +531,11 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s std::ifstream *ff = new std::ifstream; ff->open(filename.c_str(), bin_input ? std::ifstream::binary : std::ifstream::in); yosys_input_files.insert(filename); - if (ff->fail()) + if (ff->fail()) { delete ff; - else - f = ff; + ff = nullptr; + } + f = ff; if (f != NULL) { // Check for gzip magic unsigned char magic[3]; @@ -626,10 +632,12 @@ Backend::Backend(std::string name, std::string short_help) : void Backend::run_register() { - log_assert(pass_register.count(pass_name) == 0); + if (pass_register.count(pass_name)) + log_error("Unable to register pass '%s', pass already exists!\n", pass_name.c_str()); pass_register[pass_name] = this; - log_assert(backend_register.count(backend_name) == 0); + if (backend_register.count(backend_name)) + log_error("Unable to register backend '%s', backend already exists!\n", backend_name.c_str()); backend_register[backend_name] = this; } @@ -765,61 +773,98 @@ struct HelpPass : public Pass { log(" help <celltype>+ .... print verilog code for given cell type\n"); log("\n"); } - void escape_tex(std::string &tex) - { - for (size_t pos = 0; (pos = tex.find('_', pos)) != std::string::npos; pos += 2) - tex.replace(pos, 1, "\\_"); - for (size_t pos = 0; (pos = tex.find('$', pos)) != std::string::npos; pos += 2) - tex.replace(pos, 1, "\\$"); - } - void write_tex(FILE *f, std::string cmd, std::string title, std::string text) + void write_rst(std::string cmd, std::string title, std::string text) { - size_t begin = text.find_first_not_of("\n"), end = text.find_last_not_of("\n"); - if (begin != std::string::npos && end != std::string::npos && begin < end) - text = text.substr(begin, end-begin+1); - std::string cmd_unescaped = cmd; - escape_tex(cmd); - escape_tex(title); - fprintf(f, "\\section{%s -- %s}\n", cmd.c_str(), title.c_str()); - fprintf(f, "\\label{cmd:%s}\n", cmd_unescaped.c_str()); - fprintf(f, "\\begin{lstlisting}[numbers=left,frame=single]\n"); - fprintf(f, "%s\n\\end{lstlisting}\n\n", text.c_str()); - } - void escape_html(std::string &html) - { - size_t pos = 0; - while ((pos = html.find_first_of("<>&", pos)) != std::string::npos) - switch (html[pos]) { - case '<': - html.replace(pos, 1, "<"); - pos += 4; - break; - case '>': - html.replace(pos, 1, ">"); - pos += 4; - break; - case '&': - html.replace(pos, 1, "&"); - pos += 5; - break; + FILE *f = fopen(stringf("docs/source/cmd/%s.rst", cmd.c_str()).c_str(), "wt"); + // make header + size_t char_len = cmd.length() + 3 + title.length(); + std::string title_line = "\n"; + title_line.insert(0, char_len, '='); + fprintf(f, "%s", title_line.c_str()); + fprintf(f, "%s - %s\n", cmd.c_str(), title.c_str()); + fprintf(f, "%s\n", title_line.c_str()); + fprintf(f, ".. raw:: latex\n\n \\begin{comment}\n\n"); + + // render html + fprintf(f, ":code:`yosys> help %s`\n", cmd.c_str()); + fprintf(f, "--------------------------------------------------------------------------------\n\n"); + fprintf(f, ".. container:: cmdref\n"); + std::stringstream ss; + std::string textcp = text; + ss << text; + bool IsUsage = true; + int blank_count = 0; + size_t def_strip_count = 0; + bool WasDefinition = false; + for (std::string line; std::getline(ss, line, '\n');) { + // find position of first non space character + std::size_t first_pos = line.find_first_not_of(" \t"); + std::size_t last_pos = line.find_last_not_of(" \t"); + if (first_pos == std::string::npos) { + // skip formatting empty lines + if (!WasDefinition) + fputc('\n', f); + blank_count += 1; + continue; } - } - void write_html(FILE *idxf, std::string cmd, std::string title, std::string text) - { - FILE *f = fopen(stringf("cmd_%s.in", cmd.c_str()).c_str(), "wt"); - fprintf(idxf, "<li><a href=\"cmd_%s.html\"> ", cmd.c_str()); - escape_html(cmd); - escape_html(title); - escape_html(text); - - fprintf(idxf, "%s</a> <span>%s</span></a>\n", cmd.c_str(), title.c_str()); - - fprintf(f, "@cmd_header %s@\n", cmd.c_str()); - fprintf(f, "<h1>%s - %s</h1>\n", cmd.c_str(), title.c_str()); - fprintf(f, "<pre>%s</pre>\n", text.c_str()); - fprintf(f, "@footer@\n"); + // strip leading and trailing whitespace + std::string stripped_line = line.substr(first_pos, last_pos - first_pos +1); + bool IsDefinition = stripped_line[0] == '-'; + IsDefinition &= stripped_line[1] != ' ' && stripped_line[1] != '>'; + bool IsDedent = def_strip_count && first_pos <= def_strip_count; + bool IsIndent = first_pos == 2 || first_pos == 4; + if (cmd.compare(0, 7, "verific") == 0) + // verific.cc has strange and different formatting from the rest + IsIndent = false; + + // another usage block + bool NewUsage = stripped_line.find(cmd) == 0; + + if (IsUsage) { + if (stripped_line.compare(0, 4, "See ") == 0) { + // description refers to another function + fprintf(f, "\n %s\n", stripped_line.c_str()); + } else { + // usage should be the first line of help output + fprintf(f, "\n .. code:: yoscrypt\n\n %s\n\n ", stripped_line.c_str()); + WasDefinition = true; + } + IsUsage = false; + } else if (IsIndent && NewUsage && (blank_count >= 2 || WasDefinition)) { + // another usage block + fprintf(f, "\n .. code:: yoscrypt\n\n %s\n\n ", stripped_line.c_str()); + WasDefinition = true; + def_strip_count = 0; + } else if (IsIndent && IsDefinition && (blank_count || WasDefinition)) { + // format definition term + fprintf(f, "\n\n .. code:: yoscrypt\n\n %s\n\n ", stripped_line.c_str()); + WasDefinition = true; + def_strip_count = first_pos; + } else { + if (IsDedent) { + fprintf(f, "\n\n ::\n"); + def_strip_count = first_pos; + } else if (WasDefinition) { + fprintf(f, " ::\n"); + WasDefinition = false; + } + fprintf(f, "\n %s", line.substr(def_strip_count, std::string::npos).c_str()); + } + blank_count = 0; + } + fputc('\n', f); + + // render latex + fprintf(f, ".. raw:: latex\n\n \\end{comment}\n\n"); + fprintf(f, ".. only:: latex\n\n"); + fprintf(f, " ::\n\n"); + std::stringstream ss2; + ss2 << textcp; + for (std::string line; std::getline(ss2, line, '\n');) { + fprintf(f, " %s\n", line.c_str()); + } fclose(f); } void execute(std::vector<std::string> args, RTLIL::Design*) override @@ -864,26 +909,7 @@ struct HelpPass : public Pass { return; } // this option is undocumented as it is for internal use only - else if (args[1] == "-write-tex-command-reference-manual") { - FILE *f = fopen("command-reference-manual.tex", "wt"); - fprintf(f, "%% Generated using the yosys 'help -write-tex-command-reference-manual' command.\n\n"); - for (auto &it : pass_register) { - std::ostringstream buf; - log_streams.push_back(&buf); - it.second->help(); - if (it.second->experimental_flag) { - log("\n"); - log("WARNING: THE '%s' COMMAND IS EXPERIMENTAL.\n", it.first.c_str()); - log("\n"); - } - log_streams.pop_back(); - write_tex(f, it.first, it.second->short_help, buf.str()); - } - fclose(f); - } - // this option is undocumented as it is for internal use only - else if (args[1] == "-write-web-command-reference-manual") { - FILE *f = fopen("templates/cmd_index.in", "wt"); + else if (args[1] == "-write-rst-command-reference-manual") { for (auto &it : pass_register) { std::ostringstream buf; log_streams.push_back(&buf); @@ -894,9 +920,8 @@ struct HelpPass : public Pass { log("\n"); } log_streams.pop_back(); - write_html(f, it.first, it.second->short_help, buf.str()); + write_rst(it.first, it.second->short_help, buf.str()); } - fclose(f); } else if (pass_register.count(args[1])) { pass_register.at(args[1])->help(); |
