MXVM 1.8.1
Virtual Machine, Compiler, and Pascal Frontend
Loading...
Searching...
No Matches
html.cpp
Go to the documentation of this file.
1
21#include "mxvm/html_gen.hpp"
22#include "argz.hpp"
23#include <cctype>
24#include <fstream>
25#include <iostream>
26#include <sstream>
27#include <string>
28#include <vector>
29
30static std::string readFile(const std::string &path) {
31 std::fstream f(path, std::ios::in);
32 if (!f.is_open()) {
33 std::cerr << "mxvm-html: could not open file: " << path << "\n";
34 exit(EXIT_FAILURE);
35 }
36 std::ostringstream ss;
37 ss << f.rdbuf();
38 return ss.str();
39}
40
41static bool endsWith(const std::string &s, const std::string &suffix) {
42 return s.size() >= suffix.size() &&
43 s.compare(s.size() - suffix.size(), suffix.size(), suffix) == 0;
44}
45
47static std::string dirOf(const std::string &path) {
48 auto pos = path.find_last_of("/\\");
49 return pos == std::string::npos ? "./" : path.substr(0, pos + 1);
50}
51
52static bool fileExists(const std::string &path) {
53 std::ifstream f(path);
54 return f.good();
55}
56
58static void ensureCss(const std::string &outPath) {
59 std::string cssPath = dirOf(outPath) + "mxvm-highlight.css";
60 if (!fileExists(cssPath)) {
61 std::ofstream f(cssPath);
62 if (f.is_open()) {
64 std::cout << "mxvm-html: wrote " << cssPath << "\n";
65 }
66 }
67}
68
74static void writeHtml(const std::string &src, const std::string &inPath,
75 const std::string &outPath, const std::string &cssHref = "") {
76 std::fstream ofile(outPath, std::ios::out);
77 if (!ofile.is_open()) {
78 std::cerr << "mxvm-html: could not open output file: " << outPath << "\n";
79 exit(EXIT_FAILURE);
80 }
81
82 if (endsWith(inPath, ".pas")) {
83 std::string href = cssHref.empty() ? "mxvm-highlight.css" : cssHref;
84 if (cssHref.empty()) ensureCss(outPath);
85 mxvm::PasHTMLGen gen(src);
86 gen.output(ofile, inPath, href);
87 } else {
88 mxvm::HTMLGen gen(src);
89 gen.output(ofile, inPath);
90 }
91
92 ofile.close();
93 std::cout << "mxvm-html: wrote " << outPath << "\n";
94}
95
98static std::string extractDeclName(const std::string &src) {
99 const std::string decls[] = {"program", "unit", "object"};
100 std::size_t pos = 0, n = src.size();
101 while (pos < n) {
102 char c = src[pos];
103 // whitespace
104 if (std::isspace(static_cast<unsigned char>(c))) { ++pos; continue; }
105 // // line comment
106 if (c == '/' && pos + 1 < n && src[pos + 1] == '/') {
107 while (pos < n && src[pos] != '\n') ++pos;
108 continue;
109 }
110 // MXVM # comment
111 if (c == '#') {
112 while (pos < n && src[pos] != '\n') ++pos;
113 continue;
114 }
115 // Pascal { } comment
116 if (c == '{') {
117 while (pos < n && src[pos] != '}') ++pos;
118 if (pos < n) ++pos;
119 continue;
120 }
121 // Pascal (* *) comment
122 if (c == '(' && pos + 1 < n && src[pos + 1] == '*') {
123 pos += 2;
124 while (pos + 1 < n && !(src[pos] == '*' && src[pos + 1] == ')')) ++pos;
125 if (pos + 1 < n) pos += 2;
126 continue;
127 }
128 // MXVM /* */ comment
129 if (c == '/' && pos + 1 < n && src[pos + 1] == '*') {
130 pos += 2;
131 while (pos + 1 < n && !(src[pos] == '*' && src[pos + 1] == '/')) ++pos;
132 if (pos + 1 < n) pos += 2;
133 continue;
134 }
135 if (std::isalpha(static_cast<unsigned char>(c)) || c == '_') {
136 std::size_t start = pos;
137 while (pos < n && (std::isalnum(static_cast<unsigned char>(src[pos])) || src[pos] == '_'))
138 ++pos;
139 std::string tok = src.substr(start, pos - start);
140 // case-insensitive match for Pascal (unit/program)
141 std::string ltok = tok;
142 for (auto &ch : ltok) ch = static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
143 for (const auto &kw : decls) {
144 if (ltok == kw) {
145 while (pos < n && std::isspace(static_cast<unsigned char>(src[pos]))) ++pos;
146 if (pos < n && (std::isalpha(static_cast<unsigned char>(src[pos])) || src[pos] == '_')) {
147 std::size_t ns = pos;
148 while (pos < n && (std::isalnum(static_cast<unsigned char>(src[pos])) || src[pos] == '_'))
149 ++pos;
150 return src.substr(ns, pos - ns);
151 }
152 }
153 }
154 continue;
155 }
156 ++pos;
157 }
158 return {};
159}
160
161int main(int argc, char **argv) {
163 args.addOptionSingleValue('i', "input source file (.mxvm or .pas)")
164 .addOptionSingleValue('o', "output .html file (single-file mode only)")
165 .addOptionSingleValue('s', "link to this CSS file instead of writing mxvm-highlight.css")
166 .addOptionSingle('c', "batch: convert each listed file, auto-name output from program/unit/object")
167 .addOptionSingle('h', "show this help");
168
169 std::string inputFile, outputFile, cssHref;
170 bool batchMode = false;
171 std::vector<std::string> positional;
172
174 int opt;
175 try {
176 while ((opt = args.proc(arg)) != -1) {
177 switch (opt) {
178 case 'i': inputFile = arg.arg_value; break;
179 case 'o': outputFile = arg.arg_value; break;
180 case 's': cssHref = arg.arg_value; break;
181 case 'c': batchMode = true; break;
182 case 'h':
183 std::cout << "mxvm-html: MXVM / Pascal source to HTML converter\n\n";
184 args.help(std::cout);
185 return EXIT_SUCCESS;
186 case '-':
187 positional.push_back(arg.arg_value);
188 break;
189 default: break;
190 }
191 }
192 } catch (const mx::ArgException<std::string> &e) {
193 std::cerr << "mxvm-html: " << e.text() << "\n";
194 return EXIT_FAILURE;
195 }
196
197 if (batchMode) {
198 if (positional.empty()) {
199 std::cerr << "mxvm-html: -c requires at least one input file\n";
200 return EXIT_FAILURE;
201 }
202 for (const auto &path : positional) {
203 std::string src = readFile(path);
204 std::string name = extractDeclName(src);
205 if (name.empty()) {
206 std::cerr << "mxvm-html: no program/unit/object declaration found in: " << path << "\n";
207 continue;
208 }
209 writeHtml(src, path, name + ".html", cssHref);
210 }
211 return EXIT_SUCCESS;
212 }
213
214 if (!inputFile.empty()) {
215 std::string src = readFile(inputFile);
216 if (outputFile.empty()) {
217 std::string name = extractDeclName(src);
218 if (name.empty()) {
219 std::cerr << "mxvm-html: no program/unit/object declaration found in: " << inputFile
220 << " — use -o to specify output filename\n";
221 return EXIT_FAILURE;
222 }
223 outputFile = name + ".html";
224 }
225 writeHtml(src, inputFile, outputFile, cssHref);
226 return EXIT_SUCCESS;
227 }
228
229 std::cerr << "mxvm-html: no input specified. Use -i <file> [-o <output>] [-s <css>] or -c <file1> [file2...]\n";
230 std::cerr << "Run with -h for help.\n";
231 return EXIT_FAILURE;
232}
Generic command-line argument parser with concept-constrained string types.
Exception type thrown for argument parsing errors.
Definition argz.hpp:102
String text() const
Get the error message.
Definition argz.hpp:110
Generic command-line argument parser supporting single/double-dash options.
Definition argz.hpp:126
Argz< String > & addOptionSingleValue(const int &c, const String &description)
Register a single-dash option that takes a value.
Definition argz.hpp:217
void help(T &cout)
Print a formatted help message listing all registered options.
Definition argz.hpp:427
int proc(Argument< String > &a)
Process the next argument from the command line.
Definition argz.hpp:276
Generates syntax-highlighted HTML output from MXVM source code.
Definition html_gen.hpp:15
void output(std::ostream &out, std::string filename)
Write the generated HTML to an output stream.
Definition html_gen.cpp:86
Generates syntax-highlighted HTML output from Pascal (.pas) source code.
Definition html_gen.hpp:46
void output(std::ostream &out, const std::string &filename, const std::string &cssHref="mxvm-highlight.css")
Write generated HTML to an output stream.
Definition html_gen.cpp:378
static std::string defaultCss()
Return the default stylesheet text.
Definition html_gen.cpp:326
int64_t pos(const char *substr, const char *s)
Definition cstring.c:51
static bool fileExists(const std::string &path)
Definition html.cpp:52
static bool endsWith(const std::string &s, const std::string &suffix)
Definition html.cpp:41
int main(int argc, char **argv)
Definition html.cpp:161
static void writeHtml(const std::string &src, const std::string &inPath, const std::string &outPath, const std::string &cssHref="")
Definition html.cpp:74
static std::string readFile(const std::string &path)
Definition html.cpp:30
static std::string dirOf(const std::string &path)
Definition html.cpp:47
static void ensureCss(const std::string &outPath)
Definition html.cpp:58
static std::string extractDeclName(const std::string &src)
Definition html.cpp:98
HTML documentation generator from MXVM source code.
int argc(void)
Return the number of stored command-line arguments.
Definition std.c:72
const char * argv(int idx)
Return the command-line argument at the given index.
Definition std.c:76
A parsed or registered command-line argument definition.
Definition argz.hpp:52
String arg_value
parsed value (for value-taking options)
Definition argz.hpp:55