]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Copyright (c) 2016-present, Przemyslaw Skibinski, Facebook, Inc. | |
3 | * All rights reserved. | |
4 | * | |
11fdf7f2 TL |
5 | * This source code is licensed under both the BSD-style license (found in the |
6 | * LICENSE file in the root directory of this source tree) and the GPLv2 (found | |
7 | * in the COPYING file in the root directory of this source tree). | |
7c673cae FG |
8 | */ |
9 | ||
10 | #include <iostream> | |
11 | #include <fstream> | |
12 | #include <sstream> | |
13 | #include <vector> | |
14 | using namespace std; | |
15 | ||
16 | ||
17 | /* trim string at the beginning and at the end */ | |
18 | void trim(string& s, string characters) | |
19 | { | |
20 | size_t p = s.find_first_not_of(characters); | |
21 | s.erase(0, p); | |
11fdf7f2 | 22 | |
7c673cae FG |
23 | p = s.find_last_not_of(characters); |
24 | if (string::npos != p) | |
25 | s.erase(p+1); | |
26 | } | |
27 | ||
28 | ||
29 | /* trim C++ style comments */ | |
30 | void trim_comments(string &s) | |
31 | { | |
32 | size_t spos, epos; | |
33 | ||
34 | spos = s.find("/*"); | |
35 | epos = s.find("*/"); | |
36 | s = s.substr(spos+3, epos-(spos+3)); | |
37 | } | |
38 | ||
39 | ||
40 | /* get lines until a given terminator */ | |
41 | vector<string> get_lines(vector<string>& input, int& linenum, string terminator) | |
42 | { | |
43 | vector<string> out; | |
44 | string line; | |
45 | size_t epos; | |
46 | ||
47 | while ((size_t)linenum < input.size()) { | |
48 | line = input[linenum]; | |
49 | ||
50 | if (terminator.empty() && line.empty()) { linenum--; break; } | |
11fdf7f2 | 51 | |
7c673cae FG |
52 | epos = line.find(terminator); |
53 | if (!terminator.empty() && epos!=string::npos) { | |
54 | out.push_back(line); | |
55 | break; | |
56 | } | |
57 | out.push_back(line); | |
58 | linenum++; | |
59 | } | |
60 | return out; | |
61 | } | |
62 | ||
63 | ||
64 | /* print line with ZSTDLIB_API removed and C++ comments not bold */ | |
65 | void print_line(stringstream &sout, string line) | |
66 | { | |
67 | size_t spos; | |
68 | ||
69 | if (line.substr(0,12) == "ZSTDLIB_API ") line = line.substr(12); | |
70 | spos = line.find("/*"); | |
71 | if (spos!=string::npos) { | |
72 | sout << line.substr(0, spos); | |
73 | sout << "</b>" << line.substr(spos) << "<b>" << endl; | |
74 | } else { | |
75 | // fprintf(stderr, "lines=%s\n", line.c_str()); | |
76 | sout << line << endl; | |
77 | } | |
78 | } | |
79 | ||
80 | ||
81 | int main(int argc, char *argv[]) { | |
82 | char exclam; | |
83 | int linenum, chapter = 1; | |
84 | vector<string> input, lines, comments, chapters; | |
85 | string line, version; | |
86 | size_t spos, l; | |
87 | stringstream sout; | |
88 | ifstream istream; | |
89 | ofstream ostream; | |
90 | ||
91 | if (argc < 4) { | |
92 | cout << "usage: " << argv[0] << " [zstd_version] [input_file] [output_html]" << endl; | |
93 | return 1; | |
94 | } | |
95 | ||
96 | version = "zstd " + string(argv[1]) + " Manual"; | |
97 | ||
98 | istream.open(argv[2], ifstream::in); | |
99 | if (!istream.is_open()) { | |
100 | cout << "Error opening file " << argv[2] << endl; | |
101 | return 1; | |
102 | } | |
103 | ||
104 | ostream.open(argv[3], ifstream::out); | |
105 | if (!ostream.is_open()) { | |
106 | cout << "Error opening file " << argv[3] << endl; | |
107 | return 1; | |
108 | } | |
109 | ||
110 | while (getline(istream, line)) { | |
111 | input.push_back(line); | |
112 | } | |
113 | ||
114 | for (linenum=0; (size_t)linenum < input.size(); linenum++) { | |
115 | line = input[linenum]; | |
116 | ||
117 | /* typedefs are detected and included even if uncommented */ | |
118 | if (line.substr(0,7) == "typedef" && line.find("{")!=string::npos) { | |
119 | lines = get_lines(input, linenum, "}"); | |
120 | sout << "<pre><b>"; | |
121 | for (l=0; l<lines.size(); l++) { | |
122 | print_line(sout, lines[l]); | |
123 | } | |
124 | sout << "</b></pre><BR>" << endl; | |
125 | continue; | |
126 | } | |
127 | ||
128 | /* comments of type /**< and /*!< are detected and only function declaration is highlighted (bold) */ | |
129 | if ((line.find("/**<")!=string::npos || line.find("/*!<")!=string::npos) && line.find("*/")!=string::npos) { | |
130 | sout << "<pre><b>"; | |
131 | print_line(sout, line); | |
132 | sout << "</b></pre><BR>" << endl; | |
133 | continue; | |
134 | } | |
135 | ||
136 | spos = line.find("/**="); | |
137 | if (spos==string::npos) { | |
138 | spos = line.find("/*!"); | |
139 | if (spos==string::npos) | |
140 | spos = line.find("/**"); | |
141 | if (spos==string::npos) | |
142 | spos = line.find("/*-"); | |
143 | if (spos==string::npos) | |
144 | spos = line.find("/*="); | |
145 | if (spos==string::npos) | |
146 | continue; | |
147 | exclam = line[spos+2]; | |
148 | } | |
149 | else exclam = '='; | |
150 | ||
151 | comments = get_lines(input, linenum, "*/"); | |
152 | if (!comments.empty()) comments[0] = line.substr(spos+3); | |
153 | if (!comments.empty()) comments[comments.size()-1] = comments[comments.size()-1].substr(0, comments[comments.size()-1].find("*/")); | |
154 | for (l=0; l<comments.size(); l++) { | |
155 | if (comments[l].find(" *")==0) comments[l] = comments[l].substr(2); | |
156 | else if (comments[l].find(" *")==0) comments[l] = comments[l].substr(3); | |
157 | trim(comments[l], "*-="); | |
158 | } | |
159 | while (!comments.empty() && comments[comments.size()-1].empty()) comments.pop_back(); // remove empty line at the end | |
160 | while (!comments.empty() && comments[0].empty()) comments.erase(comments.begin()); // remove empty line at the start | |
161 | ||
162 | /* comments of type /*! mean: this is a function declaration; switch comments with declarations */ | |
163 | if (exclam == '!') { | |
164 | if (!comments.empty()) comments.erase(comments.begin()); /* remove first line like "ZSTD_XXX() :" */ | |
165 | linenum++; | |
166 | lines = get_lines(input, linenum, ""); | |
167 | ||
168 | sout << "<pre><b>"; | |
169 | for (l=0; l<lines.size(); l++) { | |
170 | // fprintf(stderr, "line[%d]=%s\n", l, lines[l].c_str()); | |
11fdf7f2 TL |
171 | string fline = lines[l]; |
172 | if (fline.substr(0, 12) == "ZSTDLIB_API " || | |
173 | fline.substr(0, 12) == string(12, ' ')) | |
174 | fline = fline.substr(12); | |
175 | print_line(sout, fline); | |
7c673cae FG |
176 | } |
177 | sout << "</b><p>"; | |
178 | for (l=0; l<comments.size(); l++) { | |
179 | print_line(sout, comments[l]); | |
180 | } | |
181 | sout << "</p></pre><BR>" << endl << endl; | |
182 | } else if (exclam == '=') { /* comments of type /*= and /**= mean: use a <H3> header and show also all functions until first empty line */ | |
183 | trim(comments[0], " "); | |
184 | sout << "<h3>" << comments[0] << "</h3><pre>"; | |
185 | for (l=1; l<comments.size(); l++) { | |
186 | print_line(sout, comments[l]); | |
187 | } | |
188 | sout << "</pre><b><pre>"; | |
189 | lines = get_lines(input, ++linenum, ""); | |
190 | for (l=0; l<lines.size(); l++) { | |
191 | print_line(sout, lines[l]); | |
192 | } | |
193 | sout << "</pre></b><BR>" << endl; | |
194 | } else { /* comments of type /** and /*- mean: this is a comment; use a <H2> header for the first line */ | |
195 | if (comments.empty()) continue; | |
196 | ||
197 | trim(comments[0], " "); | |
198 | sout << "<a name=\"Chapter" << chapter << "\"></a><h2>" << comments[0] << "</h2><pre>"; | |
199 | chapters.push_back(comments[0]); | |
200 | chapter++; | |
201 | ||
202 | for (l=1; l<comments.size(); l++) { | |
203 | print_line(sout, comments[l]); | |
204 | } | |
205 | if (comments.size() > 1) | |
206 | sout << "<BR></pre>" << endl << endl; | |
207 | else | |
208 | sout << "</pre>" << endl << endl; | |
209 | } | |
210 | } | |
211 | ||
212 | ostream << "<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\n<title>" << version << "</title>\n</head>\n<body>" << endl; | |
213 | ostream << "<h1>" << version << "</h1>\n"; | |
214 | ||
215 | ostream << "<hr>\n<a name=\"Contents\"></a><h2>Contents</h2>\n<ol>\n"; | |
216 | for (size_t i=0; i<chapters.size(); i++) | |
217 | ostream << "<li><a href=\"#Chapter" << i+1 << "\">" << chapters[i].c_str() << "</a></li>\n"; | |
218 | ostream << "</ol>\n<hr>\n"; | |
219 | ||
220 | ostream << sout.str(); | |
221 | ostream << "</html>" << endl << "</body>" << endl; | |
222 | ||
223 | return 0; | |
11fdf7f2 | 224 | } |