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