]> git.proxmox.com Git - ceph.git/blob - ceph/src/zstd/contrib/gen_html/gen_html.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / zstd / contrib / gen_html / gen_html.cpp
1 /*
2 * Copyright (c) 2016-present, Przemyslaw Skibinski, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
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);
22
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; }
51
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());
171 print_line(sout, lines[l]);
172 }
173 sout << "</b><p>";
174 for (l=0; l<comments.size(); l++) {
175 print_line(sout, comments[l]);
176 }
177 sout << "</p></pre><BR>" << endl << endl;
178 } else if (exclam == '=') { /* comments of type /*= and /**= mean: use a <H3> header and show also all functions until first empty line */
179 trim(comments[0], " ");
180 sout << "<h3>" << comments[0] << "</h3><pre>";
181 for (l=1; l<comments.size(); l++) {
182 print_line(sout, comments[l]);
183 }
184 sout << "</pre><b><pre>";
185 lines = get_lines(input, ++linenum, "");
186 for (l=0; l<lines.size(); l++) {
187 print_line(sout, lines[l]);
188 }
189 sout << "</pre></b><BR>" << endl;
190 } else { /* comments of type /** and /*- mean: this is a comment; use a <H2> header for the first line */
191 if (comments.empty()) continue;
192
193 trim(comments[0], " ");
194 sout << "<a name=\"Chapter" << chapter << "\"></a><h2>" << comments[0] << "</h2><pre>";
195 chapters.push_back(comments[0]);
196 chapter++;
197
198 for (l=1; l<comments.size(); l++) {
199 print_line(sout, comments[l]);
200 }
201 if (comments.size() > 1)
202 sout << "<BR></pre>" << endl << endl;
203 else
204 sout << "</pre>" << endl << endl;
205 }
206 }
207
208 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;
209 ostream << "<h1>" << version << "</h1>\n";
210
211 ostream << "<hr>\n<a name=\"Contents\"></a><h2>Contents</h2>\n<ol>\n";
212 for (size_t i=0; i<chapters.size(); i++)
213 ostream << "<li><a href=\"#Chapter" << i+1 << "\">" << chapters[i].c_str() << "</a></li>\n";
214 ostream << "</ol>\n<hr>\n";
215
216 ostream << sout.str();
217 ostream << "</html>" << endl << "</body>" << endl;
218
219 return 0;
220 }