From 974b6a947c822e9f1a5e67c4847c98b923d30398 Mon Sep 17 00:00:00 2001
From: Clifford Wolf <clifford@clifford.at>
Date: Fri, 26 Jul 2013 00:01:31 +0200
Subject: [PATCH] Added "help -write-web-command-reference-manual"

---
 kernel/register.cc | 52 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/kernel/register.cc b/kernel/register.cc
index dae47f976..f6f5804b5 100644
--- a/kernel/register.cc
+++ b/kernel/register.cc
@@ -391,7 +391,43 @@ struct HelpPass : public Pass {
 		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, "&lt;");
+				pos += 4;
+				break;
+			case '>':
+				html.replace(pos, 1, "&gt;");
+				pos += 4;
+				break;
+			case '&':
+				html.replace(pos, 1, "&amp;");
+				pos += 5;
+				break;
+			}
+	}
+	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");
+
+		fclose(f);
 	}
 	virtual void execute(std::vector<std::string> args, RTLIL::Design*)
 	{
@@ -433,6 +469,22 @@ struct HelpPass : public Pass {
 				}
 				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");
+				for (auto &it : REGISTER_INTERN::pass_register) {
+					size_t memsize;
+					char *memptr;
+					FILE *memf = open_memstream(&memptr, &memsize);
+					log_files.push_back(memf);
+					it.second->help();
+					log_files.pop_back();
+					fclose(memf);
+					write_html(f, it.first, it.second->short_help, memptr);
+					free(memptr);
+				}
+				fclose(f);
+			}
 			else if (REGISTER_INTERN::pass_register.count(args[1]) == 0)
 				log("No such command: %s\n", args[1].c_str());
 			else