xref: /aosp_15_r20/frameworks/rs/script_api/GenerateDocumentation.cpp (revision e1eccf28f96817838ad6867f7f39d2351ec11f56)
1*e1eccf28SAndroid Build Coastguard Worker /*
2*e1eccf28SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*e1eccf28SAndroid Build Coastguard Worker  *
4*e1eccf28SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*e1eccf28SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*e1eccf28SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*e1eccf28SAndroid Build Coastguard Worker  *
8*e1eccf28SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*e1eccf28SAndroid Build Coastguard Worker  *
10*e1eccf28SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*e1eccf28SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*e1eccf28SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e1eccf28SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*e1eccf28SAndroid Build Coastguard Worker  * limitations under the License.
15*e1eccf28SAndroid Build Coastguard Worker  */
16*e1eccf28SAndroid Build Coastguard Worker 
17*e1eccf28SAndroid Build Coastguard Worker #include <algorithm>
18*e1eccf28SAndroid Build Coastguard Worker #include <iostream>
19*e1eccf28SAndroid Build Coastguard Worker #include <sstream>
20*e1eccf28SAndroid Build Coastguard Worker 
21*e1eccf28SAndroid Build Coastguard Worker #include "Generator.h"
22*e1eccf28SAndroid Build Coastguard Worker #include "Specification.h"
23*e1eccf28SAndroid Build Coastguard Worker #include "Utilities.h"
24*e1eccf28SAndroid Build Coastguard Worker 
25*e1eccf28SAndroid Build Coastguard Worker using namespace std;
26*e1eccf28SAndroid Build Coastguard Worker 
27*e1eccf28SAndroid Build Coastguard Worker struct DetailedFunctionEntry {
28*e1eccf28SAndroid Build Coastguard Worker     VersionInfo info;
29*e1eccf28SAndroid Build Coastguard Worker     string htmlDeclaration;
30*e1eccf28SAndroid Build Coastguard Worker };
31*e1eccf28SAndroid Build Coastguard Worker 
32*e1eccf28SAndroid Build Coastguard Worker static const char OVERVIEW_HTML_FILE_NAME[] = "overview.html";
33*e1eccf28SAndroid Build Coastguard Worker static const char INDEX_HTML_FILE_NAME[] = "index.html";
34*e1eccf28SAndroid Build Coastguard Worker 
writeHeader(GeneratedFile * file,const string & title,const SpecFile & specFile)35*e1eccf28SAndroid Build Coastguard Worker static void writeHeader(GeneratedFile* file, const string& title,
36*e1eccf28SAndroid Build Coastguard Worker                         const SpecFile& specFile) {
37*e1eccf28SAndroid Build Coastguard Worker     // Generate DevSite markups
38*e1eccf28SAndroid Build Coastguard Worker     *file
39*e1eccf28SAndroid Build Coastguard Worker         << "<html devsite>\n"
40*e1eccf28SAndroid Build Coastguard Worker            "<!-- " << AUTO_GENERATED_WARNING << "-->\n"
41*e1eccf28SAndroid Build Coastguard Worker            "<head>\n"
42*e1eccf28SAndroid Build Coastguard Worker            "  <title>RenderScript " << title << "</title>\n"
43*e1eccf28SAndroid Build Coastguard Worker            "  <meta name=\"top_category\" value=\"develop\" />\n"
44*e1eccf28SAndroid Build Coastguard Worker            "  <meta name=\"subcategory\" value=\"guide\" />\n"
45*e1eccf28SAndroid Build Coastguard Worker            "  <meta name=\"book_path\" value=\"/guide/_book.yaml\" />\n"
46*e1eccf28SAndroid Build Coastguard Worker            "  <meta name=\"project_path\" value=\"/guide/_project.yaml\" />\n";
47*e1eccf28SAndroid Build Coastguard Worker     auto desc = specFile.getFullDescription();
48*e1eccf28SAndroid Build Coastguard Worker     if (desc.size()) {
49*e1eccf28SAndroid Build Coastguard Worker         *file << "  <meta name=\"description\" content=\"";
50*e1eccf28SAndroid Build Coastguard Worker         // Output only the first two lines. Assuming there's no other HTML
51*e1eccf28SAndroid Build Coastguard Worker         // markups there
52*e1eccf28SAndroid Build Coastguard Worker         // TODO: escape/remove markups
53*e1eccf28SAndroid Build Coastguard Worker         for (unsigned int i = 0; i < std::min(desc.size(), 2UL); ++i) {
54*e1eccf28SAndroid Build Coastguard Worker             if (i) *file << " ";
55*e1eccf28SAndroid Build Coastguard Worker             *file << desc[i];
56*e1eccf28SAndroid Build Coastguard Worker         }
57*e1eccf28SAndroid Build Coastguard Worker         *file << "…\">\n";
58*e1eccf28SAndroid Build Coastguard Worker     }
59*e1eccf28SAndroid Build Coastguard Worker     *file << "</head>\n\n"
60*e1eccf28SAndroid Build Coastguard Worker              "<body>\n\n";
61*e1eccf28SAndroid Build Coastguard Worker     *file << "<div class='renderscript'>\n";
62*e1eccf28SAndroid Build Coastguard Worker }
63*e1eccf28SAndroid Build Coastguard Worker 
writeFooter(GeneratedFile * file)64*e1eccf28SAndroid Build Coastguard Worker static void writeFooter(GeneratedFile* file) {
65*e1eccf28SAndroid Build Coastguard Worker     *file << "</div>\n";
66*e1eccf28SAndroid Build Coastguard Worker     *file << "\n\n</body>\n";
67*e1eccf28SAndroid Build Coastguard Worker     *file << "</html>\n";
68*e1eccf28SAndroid Build Coastguard Worker }
69*e1eccf28SAndroid Build Coastguard Worker 
70*e1eccf28SAndroid Build Coastguard Worker // If prefix starts input, copy it to stream and remove it from input.
skipPrefix(ostringstream * stream,string * input,const string & prefix)71*e1eccf28SAndroid Build Coastguard Worker static void skipPrefix(ostringstream* stream, string* input, const string& prefix) {
72*e1eccf28SAndroid Build Coastguard Worker     size_t size = prefix.size();
73*e1eccf28SAndroid Build Coastguard Worker     if (input->compare(0, size, prefix) != 0) {
74*e1eccf28SAndroid Build Coastguard Worker         return;
75*e1eccf28SAndroid Build Coastguard Worker     }
76*e1eccf28SAndroid Build Coastguard Worker     input->erase(0, size);
77*e1eccf28SAndroid Build Coastguard Worker     *stream << prefix;
78*e1eccf28SAndroid Build Coastguard Worker }
79*e1eccf28SAndroid Build Coastguard Worker 
80*e1eccf28SAndroid Build Coastguard Worker // Merge b into a.  Returns true if successful
mergeVersionInfo(VersionInfo * a,const VersionInfo & b)81*e1eccf28SAndroid Build Coastguard Worker static bool mergeVersionInfo(VersionInfo* a, const VersionInfo& b) {
82*e1eccf28SAndroid Build Coastguard Worker     if (a->intSize != b.intSize) {
83*e1eccf28SAndroid Build Coastguard Worker         cerr << "Error.  We don't currently support versions that differ based on int size\n";
84*e1eccf28SAndroid Build Coastguard Worker         return false;
85*e1eccf28SAndroid Build Coastguard Worker     }
86*e1eccf28SAndroid Build Coastguard Worker     if (b.minVersion != 0 && a->maxVersion == b.minVersion - 1) {
87*e1eccf28SAndroid Build Coastguard Worker         a->maxVersion = b.maxVersion;
88*e1eccf28SAndroid Build Coastguard Worker     } else if (b.maxVersion != 0 && a->minVersion == b.maxVersion + 1) {
89*e1eccf28SAndroid Build Coastguard Worker         a->minVersion = b.minVersion;
90*e1eccf28SAndroid Build Coastguard Worker     } else {
91*e1eccf28SAndroid Build Coastguard Worker         cerr << "Error.  This code currently assume that all versions are contiguous.  Don't know "
92*e1eccf28SAndroid Build Coastguard Worker                 "how to merge versions (" << a->minVersion << " - " << a->maxVersion << ") and ("
93*e1eccf28SAndroid Build Coastguard Worker              << b.minVersion << " - " << b.maxVersion << ")\n";
94*e1eccf28SAndroid Build Coastguard Worker         return false;
95*e1eccf28SAndroid Build Coastguard Worker     }
96*e1eccf28SAndroid Build Coastguard Worker     return true;
97*e1eccf28SAndroid Build Coastguard Worker }
98*e1eccf28SAndroid Build Coastguard Worker 
getHtmlStringForType(const ParameterDefinition & parameter)99*e1eccf28SAndroid Build Coastguard Worker static string getHtmlStringForType(const ParameterDefinition& parameter) {
100*e1eccf28SAndroid Build Coastguard Worker     string s = parameter.rsType;
101*e1eccf28SAndroid Build Coastguard Worker     ostringstream stream;
102*e1eccf28SAndroid Build Coastguard Worker     skipPrefix(&stream, &s, "const ");
103*e1eccf28SAndroid Build Coastguard Worker     skipPrefix(&stream, &s, "volatile ");
104*e1eccf28SAndroid Build Coastguard Worker     bool endsWithAsterisk = s.size() > 0 && s[s.size() - 1] == '*';
105*e1eccf28SAndroid Build Coastguard Worker     if (endsWithAsterisk) {
106*e1eccf28SAndroid Build Coastguard Worker         s.erase(s.size() - 1, 1);
107*e1eccf28SAndroid Build Coastguard Worker     }
108*e1eccf28SAndroid Build Coastguard Worker 
109*e1eccf28SAndroid Build Coastguard Worker     string anchor = systemSpecification.getHtmlAnchor(s);
110*e1eccf28SAndroid Build Coastguard Worker     if (anchor.empty()) {
111*e1eccf28SAndroid Build Coastguard Worker         // Not a RenderScript specific type.
112*e1eccf28SAndroid Build Coastguard Worker         return parameter.rsType;
113*e1eccf28SAndroid Build Coastguard Worker     } else {
114*e1eccf28SAndroid Build Coastguard Worker         stream << anchor;
115*e1eccf28SAndroid Build Coastguard Worker     }
116*e1eccf28SAndroid Build Coastguard Worker     if (endsWithAsterisk) {
117*e1eccf28SAndroid Build Coastguard Worker         stream << "*";
118*e1eccf28SAndroid Build Coastguard Worker     }
119*e1eccf28SAndroid Build Coastguard Worker     return stream.str();
120*e1eccf28SAndroid Build Coastguard Worker }
121*e1eccf28SAndroid Build Coastguard Worker 
getDetailedHtmlDeclaration(const FunctionPermutation & permutation)122*e1eccf28SAndroid Build Coastguard Worker static string getDetailedHtmlDeclaration(const FunctionPermutation& permutation) {
123*e1eccf28SAndroid Build Coastguard Worker     ostringstream stream;
124*e1eccf28SAndroid Build Coastguard Worker     auto ret = permutation.getReturn();
125*e1eccf28SAndroid Build Coastguard Worker     if (ret) {
126*e1eccf28SAndroid Build Coastguard Worker         stream << getHtmlStringForType(*ret);
127*e1eccf28SAndroid Build Coastguard Worker     } else {
128*e1eccf28SAndroid Build Coastguard Worker         stream << "void";
129*e1eccf28SAndroid Build Coastguard Worker     }
130*e1eccf28SAndroid Build Coastguard Worker     stream << " " << permutation.getName() << "(";
131*e1eccf28SAndroid Build Coastguard Worker     bool needComma = false;
132*e1eccf28SAndroid Build Coastguard Worker     for (auto p : permutation.getParams()) {
133*e1eccf28SAndroid Build Coastguard Worker         if (needComma) {
134*e1eccf28SAndroid Build Coastguard Worker             stream << ", ";
135*e1eccf28SAndroid Build Coastguard Worker         }
136*e1eccf28SAndroid Build Coastguard Worker         stream << getHtmlStringForType(*p);
137*e1eccf28SAndroid Build Coastguard Worker         if (p->isOutParameter) {
138*e1eccf28SAndroid Build Coastguard Worker             stream << "*";
139*e1eccf28SAndroid Build Coastguard Worker         }
140*e1eccf28SAndroid Build Coastguard Worker         if (!p->specName.empty()) {
141*e1eccf28SAndroid Build Coastguard Worker             stream << " " << p->specName;
142*e1eccf28SAndroid Build Coastguard Worker         }
143*e1eccf28SAndroid Build Coastguard Worker         needComma = true;
144*e1eccf28SAndroid Build Coastguard Worker     }
145*e1eccf28SAndroid Build Coastguard Worker     stream << ");\n";
146*e1eccf28SAndroid Build Coastguard Worker     return stream.str();
147*e1eccf28SAndroid Build Coastguard Worker }
148*e1eccf28SAndroid Build Coastguard Worker 
149*e1eccf28SAndroid Build Coastguard Worker /* Some functions (like max) have changed implementations but not their
150*e1eccf28SAndroid Build Coastguard Worker  * declaration.  We need to unify these so that we don't end up with entries
151*e1eccf28SAndroid Build Coastguard Worker  * like:
152*e1eccf28SAndroid Build Coastguard Worker  *   char max(char a, char b);  Removed from API level 20
153*e1eccf28SAndroid Build Coastguard Worker  *   char max(char a, char b);  Added to API level 20
154*e1eccf28SAndroid Build Coastguard Worker  */
getUnifiedFunctionPrototypes(Function * function,map<string,DetailedFunctionEntry> * entries)155*e1eccf28SAndroid Build Coastguard Worker static bool getUnifiedFunctionPrototypes(Function* function,
156*e1eccf28SAndroid Build Coastguard Worker                                          map<string, DetailedFunctionEntry>* entries) {
157*e1eccf28SAndroid Build Coastguard Worker     for (auto f : function->getSpecifications()) {
158*e1eccf28SAndroid Build Coastguard Worker         DetailedFunctionEntry entry;
159*e1eccf28SAndroid Build Coastguard Worker         entry.info = f->getVersionInfo();
160*e1eccf28SAndroid Build Coastguard Worker         for (auto p : f->getPermutations()) {
161*e1eccf28SAndroid Build Coastguard Worker             entry.htmlDeclaration = getDetailedHtmlDeclaration(*p);
162*e1eccf28SAndroid Build Coastguard Worker             const string s = stripHtml(entry.htmlDeclaration);
163*e1eccf28SAndroid Build Coastguard Worker             auto i = entries->find(s);
164*e1eccf28SAndroid Build Coastguard Worker             if (i == entries->end()) {
165*e1eccf28SAndroid Build Coastguard Worker                 entries->insert(pair<string, DetailedFunctionEntry>(s, entry));
166*e1eccf28SAndroid Build Coastguard Worker             } else {
167*e1eccf28SAndroid Build Coastguard Worker                 if (!mergeVersionInfo(&i->second.info, entry.info)) {
168*e1eccf28SAndroid Build Coastguard Worker                     return false;
169*e1eccf28SAndroid Build Coastguard Worker                 }
170*e1eccf28SAndroid Build Coastguard Worker             }
171*e1eccf28SAndroid Build Coastguard Worker         }
172*e1eccf28SAndroid Build Coastguard Worker     }
173*e1eccf28SAndroid Build Coastguard Worker     return true;
174*e1eccf28SAndroid Build Coastguard Worker }
175*e1eccf28SAndroid Build Coastguard Worker 
176*e1eccf28SAndroid Build Coastguard Worker // Convert words starting with @ into HTML references.  Returns false if error.
convertDocumentationRefences(string * s)177*e1eccf28SAndroid Build Coastguard Worker static bool convertDocumentationRefences(string* s) {
178*e1eccf28SAndroid Build Coastguard Worker     bool success = true;
179*e1eccf28SAndroid Build Coastguard Worker     size_t end = 0;
180*e1eccf28SAndroid Build Coastguard Worker     for (;;) {
181*e1eccf28SAndroid Build Coastguard Worker         size_t start = s->find('@', end);
182*e1eccf28SAndroid Build Coastguard Worker         if (start == string::npos) {
183*e1eccf28SAndroid Build Coastguard Worker             break;
184*e1eccf28SAndroid Build Coastguard Worker         }
185*e1eccf28SAndroid Build Coastguard Worker         // Find the end of the identifier
186*e1eccf28SAndroid Build Coastguard Worker         end = start;
187*e1eccf28SAndroid Build Coastguard Worker         char c;
188*e1eccf28SAndroid Build Coastguard Worker         do {
189*e1eccf28SAndroid Build Coastguard Worker             c = (*s)[++end];
190*e1eccf28SAndroid Build Coastguard Worker         } while (isalnum(c) || c == '_');
191*e1eccf28SAndroid Build Coastguard Worker 
192*e1eccf28SAndroid Build Coastguard Worker         const string id = s->substr(start + 1, end - start - 1);
193*e1eccf28SAndroid Build Coastguard Worker         string anchor = systemSpecification.getHtmlAnchor(id);
194*e1eccf28SAndroid Build Coastguard Worker         if (anchor.empty()) {
195*e1eccf28SAndroid Build Coastguard Worker             cerr << "Error:  Can't convert the documentation reference @" << id << "\n";
196*e1eccf28SAndroid Build Coastguard Worker             success = false;
197*e1eccf28SAndroid Build Coastguard Worker         }
198*e1eccf28SAndroid Build Coastguard Worker         s->replace(start, end - start, anchor);
199*e1eccf28SAndroid Build Coastguard Worker     }
200*e1eccf28SAndroid Build Coastguard Worker     return success;
201*e1eccf28SAndroid Build Coastguard Worker }
202*e1eccf28SAndroid Build Coastguard Worker 
generateHtmlParagraphs(GeneratedFile * file,const vector<string> & description)203*e1eccf28SAndroid Build Coastguard Worker static bool generateHtmlParagraphs(GeneratedFile* file, const vector<string>& description) {
204*e1eccf28SAndroid Build Coastguard Worker     bool inParagraph = false;
205*e1eccf28SAndroid Build Coastguard Worker     for (auto s : description) {
206*e1eccf28SAndroid Build Coastguard Worker         // Empty lines in the .spec marks paragraphs.
207*e1eccf28SAndroid Build Coastguard Worker         if (s.empty()) {
208*e1eccf28SAndroid Build Coastguard Worker             if (inParagraph) {
209*e1eccf28SAndroid Build Coastguard Worker                 *file << "</p>\n";
210*e1eccf28SAndroid Build Coastguard Worker                 inParagraph = false;
211*e1eccf28SAndroid Build Coastguard Worker             }
212*e1eccf28SAndroid Build Coastguard Worker         } else {
213*e1eccf28SAndroid Build Coastguard Worker             if (!inParagraph) {
214*e1eccf28SAndroid Build Coastguard Worker                 *file << "<p> ";
215*e1eccf28SAndroid Build Coastguard Worker                 inParagraph = true;
216*e1eccf28SAndroid Build Coastguard Worker             }
217*e1eccf28SAndroid Build Coastguard Worker         }
218*e1eccf28SAndroid Build Coastguard Worker         if (!convertDocumentationRefences(&s)) {
219*e1eccf28SAndroid Build Coastguard Worker             return false;
220*e1eccf28SAndroid Build Coastguard Worker         }
221*e1eccf28SAndroid Build Coastguard Worker         *file << s << "\n";
222*e1eccf28SAndroid Build Coastguard Worker     }
223*e1eccf28SAndroid Build Coastguard Worker     if (inParagraph) {
224*e1eccf28SAndroid Build Coastguard Worker         *file << "</p>\n";
225*e1eccf28SAndroid Build Coastguard Worker     }
226*e1eccf28SAndroid Build Coastguard Worker     return true;
227*e1eccf28SAndroid Build Coastguard Worker }
228*e1eccf28SAndroid Build Coastguard Worker 
writeSummaryTableStart(GeneratedFile * file,const string & label,bool labelIsHeading)229*e1eccf28SAndroid Build Coastguard Worker static void writeSummaryTableStart(GeneratedFile* file, const string& label, bool labelIsHeading) {
230*e1eccf28SAndroid Build Coastguard Worker     if (labelIsHeading) {
231*e1eccf28SAndroid Build Coastguard Worker         *file << "<h2 style='margin-bottom: 0px;'>" << label << "</h2>\n";
232*e1eccf28SAndroid Build Coastguard Worker     }
233*e1eccf28SAndroid Build Coastguard Worker     *file << "<table class='jd-sumtable'><tbody>\n";
234*e1eccf28SAndroid Build Coastguard Worker     if (!labelIsHeading) {
235*e1eccf28SAndroid Build Coastguard Worker         *file << "  <tr><th colspan='2'>" << label << "</th></tr>\n";
236*e1eccf28SAndroid Build Coastguard Worker     }
237*e1eccf28SAndroid Build Coastguard Worker }
238*e1eccf28SAndroid Build Coastguard Worker 
writeSummaryTableEnd(GeneratedFile * file)239*e1eccf28SAndroid Build Coastguard Worker static void writeSummaryTableEnd(GeneratedFile* file) {
240*e1eccf28SAndroid Build Coastguard Worker     *file << "</tbody></table>\n";
241*e1eccf28SAndroid Build Coastguard Worker }
242*e1eccf28SAndroid Build Coastguard Worker 
243*e1eccf28SAndroid Build Coastguard Worker enum DeprecatedSelector {
244*e1eccf28SAndroid Build Coastguard Worker     DEPRECATED_ONLY,
245*e1eccf28SAndroid Build Coastguard Worker     NON_DEPRECATED_ONLY,
246*e1eccf28SAndroid Build Coastguard Worker     ALL,
247*e1eccf28SAndroid Build Coastguard Worker };
248*e1eccf28SAndroid Build Coastguard Worker 
writeSummaryTableEntry(ostream * stream,Definition * definition,DeprecatedSelector deprecatedSelector)249*e1eccf28SAndroid Build Coastguard Worker static void writeSummaryTableEntry(ostream* stream, Definition* definition,
250*e1eccf28SAndroid Build Coastguard Worker                                    DeprecatedSelector deprecatedSelector) {
251*e1eccf28SAndroid Build Coastguard Worker     if (definition->hidden()) {
252*e1eccf28SAndroid Build Coastguard Worker         return;
253*e1eccf28SAndroid Build Coastguard Worker     }
254*e1eccf28SAndroid Build Coastguard Worker     const bool deprecated = definition->deprecated();
255*e1eccf28SAndroid Build Coastguard Worker     if ((deprecatedSelector == DEPRECATED_ONLY && !deprecated) ||
256*e1eccf28SAndroid Build Coastguard Worker         (deprecatedSelector == NON_DEPRECATED_ONLY && deprecated)) {
257*e1eccf28SAndroid Build Coastguard Worker         return;
258*e1eccf28SAndroid Build Coastguard Worker     }
259*e1eccf28SAndroid Build Coastguard Worker 
260*e1eccf28SAndroid Build Coastguard Worker     *stream << "  <tr class='alt-color api apilevel-1'>\n";
261*e1eccf28SAndroid Build Coastguard Worker     *stream << "    <td class='jd-linkcol'>\n";
262*e1eccf28SAndroid Build Coastguard Worker     *stream << "      <a href='" << definition->getUrl() << "'>" << definition->getName()
263*e1eccf28SAndroid Build Coastguard Worker             << "</a>\n";
264*e1eccf28SAndroid Build Coastguard Worker     *stream << "    </td>\n";
265*e1eccf28SAndroid Build Coastguard Worker     *stream << "    <td class='jd-descrcol' width='100%'>\n";
266*e1eccf28SAndroid Build Coastguard Worker     *stream << "      ";
267*e1eccf28SAndroid Build Coastguard Worker     if (deprecated) {
268*e1eccf28SAndroid Build Coastguard Worker         *stream << "<b>Deprecated</b>.  ";
269*e1eccf28SAndroid Build Coastguard Worker     }
270*e1eccf28SAndroid Build Coastguard Worker     *stream << definition->getSummary() << "\n";
271*e1eccf28SAndroid Build Coastguard Worker     *stream << "    </td>\n";
272*e1eccf28SAndroid Build Coastguard Worker     *stream << "  </tr>\n";
273*e1eccf28SAndroid Build Coastguard Worker }
274*e1eccf28SAndroid Build Coastguard Worker 
writeSummaryTable(GeneratedFile * file,const ostringstream * entries,const char * name,DeprecatedSelector deprecatedSelector,bool labelAsHeader)275*e1eccf28SAndroid Build Coastguard Worker static void writeSummaryTable(GeneratedFile* file, const ostringstream* entries, const char* name,
276*e1eccf28SAndroid Build Coastguard Worker                               DeprecatedSelector deprecatedSelector, bool labelAsHeader) {
277*e1eccf28SAndroid Build Coastguard Worker     string s = entries->str();
278*e1eccf28SAndroid Build Coastguard Worker     if (!s.empty()) {
279*e1eccf28SAndroid Build Coastguard Worker         string prefix;
280*e1eccf28SAndroid Build Coastguard Worker         if (deprecatedSelector == DEPRECATED_ONLY) {
281*e1eccf28SAndroid Build Coastguard Worker             prefix = "Deprecated ";
282*e1eccf28SAndroid Build Coastguard Worker         }
283*e1eccf28SAndroid Build Coastguard Worker         writeSummaryTableStart(file, prefix + name, labelAsHeader);
284*e1eccf28SAndroid Build Coastguard Worker         *file << s;
285*e1eccf28SAndroid Build Coastguard Worker         writeSummaryTableEnd(file);
286*e1eccf28SAndroid Build Coastguard Worker     }
287*e1eccf28SAndroid Build Coastguard Worker }
288*e1eccf28SAndroid Build Coastguard Worker 
writeSummaryTables(GeneratedFile * file,const map<string,Constant * > & constants,const map<string,Type * > & types,const map<string,Function * > & functions,DeprecatedSelector deprecatedSelector,bool labelAsHeader)289*e1eccf28SAndroid Build Coastguard Worker static void writeSummaryTables(GeneratedFile* file, const map<string, Constant*>& constants,
290*e1eccf28SAndroid Build Coastguard Worker                                const map<string, Type*>& types,
291*e1eccf28SAndroid Build Coastguard Worker                                const map<string, Function*>& functions,
292*e1eccf28SAndroid Build Coastguard Worker                                DeprecatedSelector deprecatedSelector, bool labelAsHeader) {
293*e1eccf28SAndroid Build Coastguard Worker     ostringstream constantStream;
294*e1eccf28SAndroid Build Coastguard Worker     for (auto e : constants) {
295*e1eccf28SAndroid Build Coastguard Worker         writeSummaryTableEntry(&constantStream, e.second, deprecatedSelector);
296*e1eccf28SAndroid Build Coastguard Worker     }
297*e1eccf28SAndroid Build Coastguard Worker     writeSummaryTable(file, &constantStream, "Constants", deprecatedSelector, labelAsHeader);
298*e1eccf28SAndroid Build Coastguard Worker 
299*e1eccf28SAndroid Build Coastguard Worker     ostringstream typeStream;
300*e1eccf28SAndroid Build Coastguard Worker     for (auto e : types) {
301*e1eccf28SAndroid Build Coastguard Worker         writeSummaryTableEntry(&typeStream, e.second, deprecatedSelector);
302*e1eccf28SAndroid Build Coastguard Worker     }
303*e1eccf28SAndroid Build Coastguard Worker     writeSummaryTable(file, &typeStream, "Types", deprecatedSelector, labelAsHeader);
304*e1eccf28SAndroid Build Coastguard Worker 
305*e1eccf28SAndroid Build Coastguard Worker     ostringstream functionStream;
306*e1eccf28SAndroid Build Coastguard Worker     for (auto e : functions) {
307*e1eccf28SAndroid Build Coastguard Worker         writeSummaryTableEntry(&functionStream, e.second, deprecatedSelector);
308*e1eccf28SAndroid Build Coastguard Worker     }
309*e1eccf28SAndroid Build Coastguard Worker     writeSummaryTable(file, &functionStream, "Functions", deprecatedSelector, labelAsHeader);
310*e1eccf28SAndroid Build Coastguard Worker }
311*e1eccf28SAndroid Build Coastguard Worker 
writeHtmlVersionTag(GeneratedFile * file,VersionInfo info,bool addSpacing)312*e1eccf28SAndroid Build Coastguard Worker static void writeHtmlVersionTag(GeneratedFile* file, VersionInfo info,
313*e1eccf28SAndroid Build Coastguard Worker                                 bool addSpacing) {
314*e1eccf28SAndroid Build Coastguard Worker     ostringstream stream;
315*e1eccf28SAndroid Build Coastguard Worker     if (info.intSize == 32) {
316*e1eccf28SAndroid Build Coastguard Worker         stream << "When compiling for 32 bits. ";
317*e1eccf28SAndroid Build Coastguard Worker     } else if (info.intSize == 64) {
318*e1eccf28SAndroid Build Coastguard Worker         stream << "When compiling for 64 bits. ";
319*e1eccf28SAndroid Build Coastguard Worker     }
320*e1eccf28SAndroid Build Coastguard Worker 
321*e1eccf28SAndroid Build Coastguard Worker     if (info.minVersion > 1 || info.maxVersion) {
322*e1eccf28SAndroid Build Coastguard Worker         const char* mid =
323*e1eccf28SAndroid Build Coastguard Worker                     "<a "
324*e1eccf28SAndroid Build Coastguard Worker                     "href='http://developer.android.com/guide/topics/manifest/"
325*e1eccf28SAndroid Build Coastguard Worker                     "uses-sdk-element.html#ApiLevels'>API level ";
326*e1eccf28SAndroid Build Coastguard Worker         if (info.minVersion <= 1) {
327*e1eccf28SAndroid Build Coastguard Worker             // No minimum
328*e1eccf28SAndroid Build Coastguard Worker             if (info.maxVersion > 0) {
329*e1eccf28SAndroid Build Coastguard Worker                 stream << "Removed from " << mid << info.maxVersion + 1 << " and higher";
330*e1eccf28SAndroid Build Coastguard Worker             }
331*e1eccf28SAndroid Build Coastguard Worker         } else {
332*e1eccf28SAndroid Build Coastguard Worker             if (info.maxVersion == 0) {
333*e1eccf28SAndroid Build Coastguard Worker                 // No maximum
334*e1eccf28SAndroid Build Coastguard Worker                 stream << "Added in " << mid << info.minVersion;
335*e1eccf28SAndroid Build Coastguard Worker             } else {
336*e1eccf28SAndroid Build Coastguard Worker                 stream << mid << info.minVersion << " - " << info.maxVersion;
337*e1eccf28SAndroid Build Coastguard Worker             }
338*e1eccf28SAndroid Build Coastguard Worker         }
339*e1eccf28SAndroid Build Coastguard Worker         stream << "</a>";
340*e1eccf28SAndroid Build Coastguard Worker     }
341*e1eccf28SAndroid Build Coastguard Worker     string s = stream.str();
342*e1eccf28SAndroid Build Coastguard Worker     // Remove any trailing whitespace
343*e1eccf28SAndroid Build Coastguard Worker     while (s.back() == ' ') {
344*e1eccf28SAndroid Build Coastguard Worker         s.pop_back();
345*e1eccf28SAndroid Build Coastguard Worker     }
346*e1eccf28SAndroid Build Coastguard Worker     if (!s.empty()) {
347*e1eccf28SAndroid Build Coastguard Worker         *file << (addSpacing ? "    " : "") << s << "\n";
348*e1eccf28SAndroid Build Coastguard Worker     }
349*e1eccf28SAndroid Build Coastguard Worker }
350*e1eccf28SAndroid Build Coastguard Worker 
writeDetailedTypeSpecification(GeneratedFile * file,const TypeSpecification * spec)351*e1eccf28SAndroid Build Coastguard Worker static void writeDetailedTypeSpecification(GeneratedFile* file, const TypeSpecification* spec) {
352*e1eccf28SAndroid Build Coastguard Worker     switch (spec->getKind()) {
353*e1eccf28SAndroid Build Coastguard Worker         case SIMPLE: {
354*e1eccf28SAndroid Build Coastguard Worker             Type* type = spec->getType();
355*e1eccf28SAndroid Build Coastguard Worker             *file << "<p>A typedef of: " << spec->getSimpleType()
356*e1eccf28SAndroid Build Coastguard Worker                   << makeAttributeTag(spec->getAttribute(), "", type->getDeprecatedApiLevel(),
357*e1eccf28SAndroid Build Coastguard Worker                                       type->getDeprecatedMessage())
358*e1eccf28SAndroid Build Coastguard Worker                   << "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
359*e1eccf28SAndroid Build Coastguard Worker             writeHtmlVersionTag(file, spec->getVersionInfo(), false);
360*e1eccf28SAndroid Build Coastguard Worker             *file << "</p>\n";
361*e1eccf28SAndroid Build Coastguard Worker             break;
362*e1eccf28SAndroid Build Coastguard Worker         }
363*e1eccf28SAndroid Build Coastguard Worker         case RS_OBJECT: {
364*e1eccf28SAndroid Build Coastguard Worker             *file << "<p>";
365*e1eccf28SAndroid Build Coastguard Worker             writeHtmlVersionTag(file, spec->getVersionInfo(), false);
366*e1eccf28SAndroid Build Coastguard Worker             *file << "</p>\n";
367*e1eccf28SAndroid Build Coastguard Worker             break;
368*e1eccf28SAndroid Build Coastguard Worker         }
369*e1eccf28SAndroid Build Coastguard Worker         case ENUM: {
370*e1eccf28SAndroid Build Coastguard Worker             *file << "<p>An enum with the following values:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n";
371*e1eccf28SAndroid Build Coastguard Worker             writeHtmlVersionTag(file, spec->getVersionInfo(), false);
372*e1eccf28SAndroid Build Coastguard Worker             *file << "</p>\n";
373*e1eccf28SAndroid Build Coastguard Worker 
374*e1eccf28SAndroid Build Coastguard Worker             *file << "  <table class='jd-tagtable'><tbody>\n";
375*e1eccf28SAndroid Build Coastguard Worker             const vector<string>& values = spec->getValues();
376*e1eccf28SAndroid Build Coastguard Worker             const vector<string>& valueComments = spec->getValueComments();
377*e1eccf28SAndroid Build Coastguard Worker             for (size_t i = 0; i < values.size(); i++) {
378*e1eccf28SAndroid Build Coastguard Worker                 *file << "    <tr><th>" << values[i] << "</th><td>";
379*e1eccf28SAndroid Build Coastguard Worker                 if (valueComments.size() > i) {
380*e1eccf28SAndroid Build Coastguard Worker                     *file << valueComments[i];
381*e1eccf28SAndroid Build Coastguard Worker                 }
382*e1eccf28SAndroid Build Coastguard Worker                 *file << "</td></tr>\n";
383*e1eccf28SAndroid Build Coastguard Worker             }
384*e1eccf28SAndroid Build Coastguard Worker             *file << "  </tbody></table><br/>\n";
385*e1eccf28SAndroid Build Coastguard Worker             break;
386*e1eccf28SAndroid Build Coastguard Worker         }
387*e1eccf28SAndroid Build Coastguard Worker         case STRUCT: {
388*e1eccf28SAndroid Build Coastguard Worker             *file << "<p>A structure with the following fields:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
389*e1eccf28SAndroid Build Coastguard Worker             writeHtmlVersionTag(file, spec->getVersionInfo(), false);
390*e1eccf28SAndroid Build Coastguard Worker             *file << "</p>\n";
391*e1eccf28SAndroid Build Coastguard Worker 
392*e1eccf28SAndroid Build Coastguard Worker             *file << "  <table class='jd-tagtable'><tbody>\n";
393*e1eccf28SAndroid Build Coastguard Worker             const vector<string>& fields = spec->getFields();
394*e1eccf28SAndroid Build Coastguard Worker             const vector<string>& fieldComments = spec->getFieldComments();
395*e1eccf28SAndroid Build Coastguard Worker             for (size_t i = 0; i < fields.size(); i++) {
396*e1eccf28SAndroid Build Coastguard Worker                 *file << "    <tr><th>" << fields[i] << "</th><td>";
397*e1eccf28SAndroid Build Coastguard Worker                 if (fieldComments.size() > i && !fieldComments[i].empty()) {
398*e1eccf28SAndroid Build Coastguard Worker                     *file << fieldComments[i];
399*e1eccf28SAndroid Build Coastguard Worker                 }
400*e1eccf28SAndroid Build Coastguard Worker                 *file << "</td></tr>\n";
401*e1eccf28SAndroid Build Coastguard Worker             }
402*e1eccf28SAndroid Build Coastguard Worker             *file << "  </tbody></table><br/>\n";
403*e1eccf28SAndroid Build Coastguard Worker             break;
404*e1eccf28SAndroid Build Coastguard Worker         }
405*e1eccf28SAndroid Build Coastguard Worker     }
406*e1eccf28SAndroid Build Coastguard Worker }
407*e1eccf28SAndroid Build Coastguard Worker 
writeDetailedConstantSpecification(GeneratedFile * file,ConstantSpecification * c)408*e1eccf28SAndroid Build Coastguard Worker static void writeDetailedConstantSpecification(GeneratedFile* file, ConstantSpecification* c) {
409*e1eccf28SAndroid Build Coastguard Worker     *file << "      <tr><td>";
410*e1eccf28SAndroid Build Coastguard Worker     *file << "Value: " << c->getValue() << "\n";
411*e1eccf28SAndroid Build Coastguard Worker     writeHtmlVersionTag(file, c->getVersionInfo(), true);
412*e1eccf28SAndroid Build Coastguard Worker     *file << "      </td></tr>\n";
413*e1eccf28SAndroid Build Coastguard Worker     *file << "<br/>\n";
414*e1eccf28SAndroid Build Coastguard Worker }
415*e1eccf28SAndroid Build Coastguard Worker 
writeOverviewForFile(GeneratedFile * file,const SpecFile & specFile)416*e1eccf28SAndroid Build Coastguard Worker static bool writeOverviewForFile(GeneratedFile* file, const SpecFile& specFile) {
417*e1eccf28SAndroid Build Coastguard Worker     bool success = true;
418*e1eccf28SAndroid Build Coastguard Worker     *file << "<h2>" << specFile.getBriefDescription() << "</h2>\n";
419*e1eccf28SAndroid Build Coastguard Worker     if (!generateHtmlParagraphs(file, specFile.getFullDescription())) {
420*e1eccf28SAndroid Build Coastguard Worker         success = false;
421*e1eccf28SAndroid Build Coastguard Worker     }
422*e1eccf28SAndroid Build Coastguard Worker 
423*e1eccf28SAndroid Build Coastguard Worker     // Write the summary tables.
424*e1eccf28SAndroid Build Coastguard Worker     // file << "<h2>Summary</h2>\n";
425*e1eccf28SAndroid Build Coastguard Worker     writeSummaryTables(file, specFile.getDocumentedConstants(), specFile.getDocumentedTypes(),
426*e1eccf28SAndroid Build Coastguard Worker                        specFile.getDocumentedFunctions(), NON_DEPRECATED_ONLY, false);
427*e1eccf28SAndroid Build Coastguard Worker 
428*e1eccf28SAndroid Build Coastguard Worker     return success;
429*e1eccf28SAndroid Build Coastguard Worker }
430*e1eccf28SAndroid Build Coastguard Worker 
generateOverview(const string & directory)431*e1eccf28SAndroid Build Coastguard Worker static bool generateOverview(const string& directory) {
432*e1eccf28SAndroid Build Coastguard Worker     GeneratedFile file;
433*e1eccf28SAndroid Build Coastguard Worker     if (!file.start(directory, OVERVIEW_HTML_FILE_NAME)) {
434*e1eccf28SAndroid Build Coastguard Worker         return false;
435*e1eccf28SAndroid Build Coastguard Worker     }
436*e1eccf28SAndroid Build Coastguard Worker     bool success = true;
437*e1eccf28SAndroid Build Coastguard Worker 
438*e1eccf28SAndroid Build Coastguard Worker     // Take the description from the first spec file (rs_core.spec, based on how
439*e1eccf28SAndroid Build Coastguard Worker     // currently this generator is called)
440*e1eccf28SAndroid Build Coastguard Worker     writeHeader(&file, "Runtime API Reference",
441*e1eccf28SAndroid Build Coastguard Worker                 *(systemSpecification.getSpecFiles()[0]));
442*e1eccf28SAndroid Build Coastguard Worker 
443*e1eccf28SAndroid Build Coastguard Worker     for (auto specFile : systemSpecification.getSpecFiles()) {
444*e1eccf28SAndroid Build Coastguard Worker         if (!writeOverviewForFile(&file, *specFile)) {
445*e1eccf28SAndroid Build Coastguard Worker             success = false;
446*e1eccf28SAndroid Build Coastguard Worker         }
447*e1eccf28SAndroid Build Coastguard Worker     }
448*e1eccf28SAndroid Build Coastguard Worker 
449*e1eccf28SAndroid Build Coastguard Worker     writeFooter(&file);
450*e1eccf28SAndroid Build Coastguard Worker     file.close();
451*e1eccf28SAndroid Build Coastguard Worker     return success;
452*e1eccf28SAndroid Build Coastguard Worker }
453*e1eccf28SAndroid Build Coastguard Worker 
generateAlphabeticalIndex(const string & directory)454*e1eccf28SAndroid Build Coastguard Worker static bool generateAlphabeticalIndex(const string& directory) {
455*e1eccf28SAndroid Build Coastguard Worker     GeneratedFile file;
456*e1eccf28SAndroid Build Coastguard Worker     if (!file.start(directory, INDEX_HTML_FILE_NAME)) {
457*e1eccf28SAndroid Build Coastguard Worker         return false;
458*e1eccf28SAndroid Build Coastguard Worker     }
459*e1eccf28SAndroid Build Coastguard Worker     writeHeader(&file, "Index", SpecFile(""));
460*e1eccf28SAndroid Build Coastguard Worker 
461*e1eccf28SAndroid Build Coastguard Worker     writeSummaryTables(&file, systemSpecification.getConstants(), systemSpecification.getTypes(),
462*e1eccf28SAndroid Build Coastguard Worker                        systemSpecification.getFunctions(), NON_DEPRECATED_ONLY, true);
463*e1eccf28SAndroid Build Coastguard Worker 
464*e1eccf28SAndroid Build Coastguard Worker     writeSummaryTables(&file, systemSpecification.getConstants(), systemSpecification.getTypes(),
465*e1eccf28SAndroid Build Coastguard Worker                        systemSpecification.getFunctions(), DEPRECATED_ONLY, true);
466*e1eccf28SAndroid Build Coastguard Worker 
467*e1eccf28SAndroid Build Coastguard Worker     writeFooter(&file);
468*e1eccf28SAndroid Build Coastguard Worker     file.close();
469*e1eccf28SAndroid Build Coastguard Worker     return true;
470*e1eccf28SAndroid Build Coastguard Worker }
471*e1eccf28SAndroid Build Coastguard Worker 
writeDeprecatedWarning(GeneratedFile * file,Definition * definition)472*e1eccf28SAndroid Build Coastguard Worker static void writeDeprecatedWarning(GeneratedFile* file, Definition* definition) {
473*e1eccf28SAndroid Build Coastguard Worker     if (definition->deprecated()) {
474*e1eccf28SAndroid Build Coastguard Worker         *file << "    <p><b>Deprecated.</b>  ";
475*e1eccf28SAndroid Build Coastguard Worker         string s = definition->getDeprecatedMessage();
476*e1eccf28SAndroid Build Coastguard Worker         convertDocumentationRefences(&s);
477*e1eccf28SAndroid Build Coastguard Worker         if (!s.empty()) {
478*e1eccf28SAndroid Build Coastguard Worker             *file << s;
479*e1eccf28SAndroid Build Coastguard Worker         } else {
480*e1eccf28SAndroid Build Coastguard Worker             *file << "Do not use.";
481*e1eccf28SAndroid Build Coastguard Worker         }
482*e1eccf28SAndroid Build Coastguard Worker         *file << "</p>\n";
483*e1eccf28SAndroid Build Coastguard Worker     }
484*e1eccf28SAndroid Build Coastguard Worker }
485*e1eccf28SAndroid Build Coastguard Worker 
writeDetailedConstant(GeneratedFile * file,Constant * constant)486*e1eccf28SAndroid Build Coastguard Worker static bool writeDetailedConstant(GeneratedFile* file, Constant* constant) {
487*e1eccf28SAndroid Build Coastguard Worker     if (constant->hidden()) {
488*e1eccf28SAndroid Build Coastguard Worker         return true;
489*e1eccf28SAndroid Build Coastguard Worker     }
490*e1eccf28SAndroid Build Coastguard Worker     const string& name = constant->getName();
491*e1eccf28SAndroid Build Coastguard Worker 
492*e1eccf28SAndroid Build Coastguard Worker     *file << "<a name='android_rs:" << name << "'></a>\n";
493*e1eccf28SAndroid Build Coastguard Worker     *file << "<div class='jd-details'>\n";
494*e1eccf28SAndroid Build Coastguard Worker     *file << "  <h4 class='jd-details-title'>\n";
495*e1eccf28SAndroid Build Coastguard Worker     *file << "    <span class='sympad'>" << name << "</span>\n";
496*e1eccf28SAndroid Build Coastguard Worker     *file << "    <span class='normal'>: " << constant->getSummary() << "</span>\n";
497*e1eccf28SAndroid Build Coastguard Worker     *file << "  </h4>\n";
498*e1eccf28SAndroid Build Coastguard Worker 
499*e1eccf28SAndroid Build Coastguard Worker     *file << "  <div class='jd-details-descr'>\n";
500*e1eccf28SAndroid Build Coastguard Worker     *file << "    <table class='jd-tagtable'><tbody>\n";
501*e1eccf28SAndroid Build Coastguard Worker     auto specifications = constant->getSpecifications();
502*e1eccf28SAndroid Build Coastguard Worker     bool addSeparator = specifications.size() > 1;
503*e1eccf28SAndroid Build Coastguard Worker     for (auto spec : specifications) {
504*e1eccf28SAndroid Build Coastguard Worker         if (addSeparator) {
505*e1eccf28SAndroid Build Coastguard Worker             *file << "    <h5 class='jd-tagtitle'>Variant:</h5>\n";
506*e1eccf28SAndroid Build Coastguard Worker         }
507*e1eccf28SAndroid Build Coastguard Worker         writeDetailedConstantSpecification(file, spec);
508*e1eccf28SAndroid Build Coastguard Worker     }
509*e1eccf28SAndroid Build Coastguard Worker     *file << "    </tbody></table>\n";
510*e1eccf28SAndroid Build Coastguard Worker     *file << "  </div>\n";
511*e1eccf28SAndroid Build Coastguard Worker 
512*e1eccf28SAndroid Build Coastguard Worker     *file << "    <div class='jd-tagdata jd-tagdescr'>\n";
513*e1eccf28SAndroid Build Coastguard Worker 
514*e1eccf28SAndroid Build Coastguard Worker     writeDeprecatedWarning(file, constant);
515*e1eccf28SAndroid Build Coastguard Worker     if (!generateHtmlParagraphs(file, constant->getDescription())) {
516*e1eccf28SAndroid Build Coastguard Worker         return false;
517*e1eccf28SAndroid Build Coastguard Worker     }
518*e1eccf28SAndroid Build Coastguard Worker     *file << "    </div>\n";
519*e1eccf28SAndroid Build Coastguard Worker 
520*e1eccf28SAndroid Build Coastguard Worker     *file << "</div>\n";
521*e1eccf28SAndroid Build Coastguard Worker     *file << "\n";
522*e1eccf28SAndroid Build Coastguard Worker     return true;
523*e1eccf28SAndroid Build Coastguard Worker }
524*e1eccf28SAndroid Build Coastguard Worker 
writeDetailedType(GeneratedFile * file,Type * type)525*e1eccf28SAndroid Build Coastguard Worker static bool writeDetailedType(GeneratedFile* file, Type* type) {
526*e1eccf28SAndroid Build Coastguard Worker     if (type->hidden()) {
527*e1eccf28SAndroid Build Coastguard Worker         return true;
528*e1eccf28SAndroid Build Coastguard Worker     }
529*e1eccf28SAndroid Build Coastguard Worker     const string& name = type->getName();
530*e1eccf28SAndroid Build Coastguard Worker 
531*e1eccf28SAndroid Build Coastguard Worker     *file << "<a name='android_rs:" << name << "'></a>\n";
532*e1eccf28SAndroid Build Coastguard Worker     *file << "<div class='jd-details'>\n";
533*e1eccf28SAndroid Build Coastguard Worker     *file << "  <h4 class='jd-details-title'>\n";
534*e1eccf28SAndroid Build Coastguard Worker     *file << "    <span class='sympad'>" << name << "</span>\n";
535*e1eccf28SAndroid Build Coastguard Worker     *file << "    <span class='normal'>: " << type->getSummary() << "</span>\n";
536*e1eccf28SAndroid Build Coastguard Worker     *file << "  </h4>\n";
537*e1eccf28SAndroid Build Coastguard Worker 
538*e1eccf28SAndroid Build Coastguard Worker     *file << "  <div class='jd-details-descr'>\n";
539*e1eccf28SAndroid Build Coastguard Worker     for (auto spec : type->getSpecifications()) {
540*e1eccf28SAndroid Build Coastguard Worker         writeDetailedTypeSpecification(file, spec);
541*e1eccf28SAndroid Build Coastguard Worker     }
542*e1eccf28SAndroid Build Coastguard Worker 
543*e1eccf28SAndroid Build Coastguard Worker     writeDeprecatedWarning(file, type);
544*e1eccf28SAndroid Build Coastguard Worker     if (!generateHtmlParagraphs(file, type->getDescription())) {
545*e1eccf28SAndroid Build Coastguard Worker         return false;
546*e1eccf28SAndroid Build Coastguard Worker     }
547*e1eccf28SAndroid Build Coastguard Worker 
548*e1eccf28SAndroid Build Coastguard Worker     *file << "  </div>\n";
549*e1eccf28SAndroid Build Coastguard Worker     *file << "</div>\n";
550*e1eccf28SAndroid Build Coastguard Worker     *file << "\n";
551*e1eccf28SAndroid Build Coastguard Worker     return true;
552*e1eccf28SAndroid Build Coastguard Worker }
553*e1eccf28SAndroid Build Coastguard Worker 
writeDetailedFunction(GeneratedFile * file,Function * function)554*e1eccf28SAndroid Build Coastguard Worker static bool writeDetailedFunction(GeneratedFile* file, Function* function) {
555*e1eccf28SAndroid Build Coastguard Worker     if (function->hidden()) {
556*e1eccf28SAndroid Build Coastguard Worker         return true;
557*e1eccf28SAndroid Build Coastguard Worker     }
558*e1eccf28SAndroid Build Coastguard Worker     const string& name = function->getName();
559*e1eccf28SAndroid Build Coastguard Worker 
560*e1eccf28SAndroid Build Coastguard Worker     *file << "<a name='android_rs:" << name << "'></a>\n";
561*e1eccf28SAndroid Build Coastguard Worker     *file << "<div class='jd-details'>\n";
562*e1eccf28SAndroid Build Coastguard Worker     *file << "  <h4 class='jd-details-title'>\n";
563*e1eccf28SAndroid Build Coastguard Worker     *file << "    <span class='sympad'>" << name << "</span>\n";
564*e1eccf28SAndroid Build Coastguard Worker     *file << "    <span class='normal'>: " << function->getSummary() << "</span>\n";
565*e1eccf28SAndroid Build Coastguard Worker     *file << "  </h4>\n";
566*e1eccf28SAndroid Build Coastguard Worker 
567*e1eccf28SAndroid Build Coastguard Worker     *file << "  <div class='jd-details-descr'>\n";
568*e1eccf28SAndroid Build Coastguard Worker     map<string, DetailedFunctionEntry> entries;
569*e1eccf28SAndroid Build Coastguard Worker     if (!getUnifiedFunctionPrototypes(function, &entries)) {
570*e1eccf28SAndroid Build Coastguard Worker         return false;
571*e1eccf28SAndroid Build Coastguard Worker     }
572*e1eccf28SAndroid Build Coastguard Worker     *file << "    <table class='jd-tagtable'><tbody>\n";
573*e1eccf28SAndroid Build Coastguard Worker     for (auto i : entries) {
574*e1eccf28SAndroid Build Coastguard Worker         *file << "      <tr>\n";
575*e1eccf28SAndroid Build Coastguard Worker         *file << "        <td>" << i.second.htmlDeclaration << "</td>\n";
576*e1eccf28SAndroid Build Coastguard Worker         *file << "        <td>";
577*e1eccf28SAndroid Build Coastguard Worker         writeHtmlVersionTag(file, i.second.info, true);
578*e1eccf28SAndroid Build Coastguard Worker         *file << "        </td>\n";
579*e1eccf28SAndroid Build Coastguard Worker         *file << "      </tr>\n";
580*e1eccf28SAndroid Build Coastguard Worker     }
581*e1eccf28SAndroid Build Coastguard Worker     *file << "    </tbody></table>\n";
582*e1eccf28SAndroid Build Coastguard Worker     *file << "  </div>\n";
583*e1eccf28SAndroid Build Coastguard Worker 
584*e1eccf28SAndroid Build Coastguard Worker     if (function->someParametersAreDocumented()) {
585*e1eccf28SAndroid Build Coastguard Worker         *file << "  <div class='jd-tagdata'>";
586*e1eccf28SAndroid Build Coastguard Worker         *file << "    <h5 class='jd-tagtitle'>Parameters</h5>\n";
587*e1eccf28SAndroid Build Coastguard Worker         *file << "    <table class='jd-tagtable'><tbody>\n";
588*e1eccf28SAndroid Build Coastguard Worker         for (ParameterEntry* p : function->getParameters()) {
589*e1eccf28SAndroid Build Coastguard Worker             *file << "    <tr><th>" << p->name << "</th><td>" << p->documentation << "</td></tr>\n";
590*e1eccf28SAndroid Build Coastguard Worker         }
591*e1eccf28SAndroid Build Coastguard Worker         *file << "    </tbody></table>\n";
592*e1eccf28SAndroid Build Coastguard Worker         *file << "  </div>\n";
593*e1eccf28SAndroid Build Coastguard Worker     }
594*e1eccf28SAndroid Build Coastguard Worker 
595*e1eccf28SAndroid Build Coastguard Worker     string ret = function->getReturnDocumentation();
596*e1eccf28SAndroid Build Coastguard Worker     if (!ret.empty()) {
597*e1eccf28SAndroid Build Coastguard Worker         *file << "  <div class='jd-tagdata'>";
598*e1eccf28SAndroid Build Coastguard Worker         *file << "    <h5 class='jd-tagtitle'>Returns</h5>\n";
599*e1eccf28SAndroid Build Coastguard Worker         *file << "    <table class='jd-tagtable'><tbody>\n";
600*e1eccf28SAndroid Build Coastguard Worker         *file << "    <tr><td>" << ret << "</td></tr>\n";
601*e1eccf28SAndroid Build Coastguard Worker         *file << "    </tbody></table>\n";
602*e1eccf28SAndroid Build Coastguard Worker         *file << "  </div>\n";
603*e1eccf28SAndroid Build Coastguard Worker     }
604*e1eccf28SAndroid Build Coastguard Worker 
605*e1eccf28SAndroid Build Coastguard Worker     *file << "  <div class='jd-tagdata jd-tagdescr'>\n";
606*e1eccf28SAndroid Build Coastguard Worker     writeDeprecatedWarning(file, function);
607*e1eccf28SAndroid Build Coastguard Worker     if (!generateHtmlParagraphs(file, function->getDescription())) {
608*e1eccf28SAndroid Build Coastguard Worker         return false;
609*e1eccf28SAndroid Build Coastguard Worker     }
610*e1eccf28SAndroid Build Coastguard Worker     *file << "  </div>\n";
611*e1eccf28SAndroid Build Coastguard Worker 
612*e1eccf28SAndroid Build Coastguard Worker     *file << "</div>\n";
613*e1eccf28SAndroid Build Coastguard Worker     *file << "\n";
614*e1eccf28SAndroid Build Coastguard Worker     return true;
615*e1eccf28SAndroid Build Coastguard Worker }
616*e1eccf28SAndroid Build Coastguard Worker 
writeDetailedDocumentationFile(const string & directory,const SpecFile & specFile)617*e1eccf28SAndroid Build Coastguard Worker static bool writeDetailedDocumentationFile(const string& directory,
618*e1eccf28SAndroid Build Coastguard Worker                                            const SpecFile& specFile) {
619*e1eccf28SAndroid Build Coastguard Worker     if (!specFile.hasSpecifications()) {
620*e1eccf28SAndroid Build Coastguard Worker         // This is true for rs_core.spec
621*e1eccf28SAndroid Build Coastguard Worker         return true;
622*e1eccf28SAndroid Build Coastguard Worker     }
623*e1eccf28SAndroid Build Coastguard Worker 
624*e1eccf28SAndroid Build Coastguard Worker     GeneratedFile file;
625*e1eccf28SAndroid Build Coastguard Worker     const string fileName = stringReplace(specFile.getSpecFileName(), ".spec",
626*e1eccf28SAndroid Build Coastguard Worker                                           ".html");
627*e1eccf28SAndroid Build Coastguard Worker     if (!file.start(directory, fileName)) {
628*e1eccf28SAndroid Build Coastguard Worker         return false;
629*e1eccf28SAndroid Build Coastguard Worker     }
630*e1eccf28SAndroid Build Coastguard Worker     bool success = true;
631*e1eccf28SAndroid Build Coastguard Worker 
632*e1eccf28SAndroid Build Coastguard Worker     string title = specFile.getBriefDescription();
633*e1eccf28SAndroid Build Coastguard Worker     writeHeader(&file, title, specFile);
634*e1eccf28SAndroid Build Coastguard Worker 
635*e1eccf28SAndroid Build Coastguard Worker     file << "<h2>Overview</h2>\n";
636*e1eccf28SAndroid Build Coastguard Worker     if (!generateHtmlParagraphs(&file, specFile.getFullDescription())) {
637*e1eccf28SAndroid Build Coastguard Worker         success = false;
638*e1eccf28SAndroid Build Coastguard Worker     }
639*e1eccf28SAndroid Build Coastguard Worker 
640*e1eccf28SAndroid Build Coastguard Worker     // Write the summary tables.
641*e1eccf28SAndroid Build Coastguard Worker     file << "<h2>Summary</h2>\n";
642*e1eccf28SAndroid Build Coastguard Worker     const auto& constants = specFile.getDocumentedConstants();
643*e1eccf28SAndroid Build Coastguard Worker     const auto& types = specFile.getDocumentedTypes();
644*e1eccf28SAndroid Build Coastguard Worker     const auto& functions = specFile.getDocumentedFunctions();
645*e1eccf28SAndroid Build Coastguard Worker 
646*e1eccf28SAndroid Build Coastguard Worker     writeSummaryTables(&file, constants, types, functions, NON_DEPRECATED_ONLY, false);
647*e1eccf28SAndroid Build Coastguard Worker     writeSummaryTables(&file, constants, types, functions, DEPRECATED_ONLY, false);
648*e1eccf28SAndroid Build Coastguard Worker 
649*e1eccf28SAndroid Build Coastguard Worker     // Write the full details of each constant, type, and function.
650*e1eccf28SAndroid Build Coastguard Worker     if (!constants.empty()) {
651*e1eccf28SAndroid Build Coastguard Worker         file << "<h2>Constants</h2>\n";
652*e1eccf28SAndroid Build Coastguard Worker         for (auto i : constants) {
653*e1eccf28SAndroid Build Coastguard Worker             if (!writeDetailedConstant(&file, i.second)) {
654*e1eccf28SAndroid Build Coastguard Worker                 success = false;
655*e1eccf28SAndroid Build Coastguard Worker             }
656*e1eccf28SAndroid Build Coastguard Worker         }
657*e1eccf28SAndroid Build Coastguard Worker     }
658*e1eccf28SAndroid Build Coastguard Worker     if (!types.empty()) {
659*e1eccf28SAndroid Build Coastguard Worker         file << "<h2>Types</h2>\n";
660*e1eccf28SAndroid Build Coastguard Worker         for (auto i : types) {
661*e1eccf28SAndroid Build Coastguard Worker             if (!writeDetailedType(&file, i.second)) {
662*e1eccf28SAndroid Build Coastguard Worker                 success = false;
663*e1eccf28SAndroid Build Coastguard Worker             }
664*e1eccf28SAndroid Build Coastguard Worker         }
665*e1eccf28SAndroid Build Coastguard Worker     }
666*e1eccf28SAndroid Build Coastguard Worker     if (!functions.empty()) {
667*e1eccf28SAndroid Build Coastguard Worker         file << "<h2>Functions</h2>\n";
668*e1eccf28SAndroid Build Coastguard Worker         for (auto i : functions) {
669*e1eccf28SAndroid Build Coastguard Worker             if (!writeDetailedFunction(&file, i.second)) {
670*e1eccf28SAndroid Build Coastguard Worker                 success = false;
671*e1eccf28SAndroid Build Coastguard Worker             }
672*e1eccf28SAndroid Build Coastguard Worker         }
673*e1eccf28SAndroid Build Coastguard Worker     }
674*e1eccf28SAndroid Build Coastguard Worker 
675*e1eccf28SAndroid Build Coastguard Worker     writeFooter(&file);
676*e1eccf28SAndroid Build Coastguard Worker     file.close();
677*e1eccf28SAndroid Build Coastguard Worker 
678*e1eccf28SAndroid Build Coastguard Worker     if (!success) {
679*e1eccf28SAndroid Build Coastguard Worker         // If in error, write a final message to make it easier to figure out which file failed.
680*e1eccf28SAndroid Build Coastguard Worker         cerr << fileName << ": Failed due to errors.\n";
681*e1eccf28SAndroid Build Coastguard Worker     }
682*e1eccf28SAndroid Build Coastguard Worker     return success;
683*e1eccf28SAndroid Build Coastguard Worker }
684*e1eccf28SAndroid Build Coastguard Worker 
generateSnippet(GeneratedFile * file,const string & fileName,const string & title)685*e1eccf28SAndroid Build Coastguard Worker static void generateSnippet(GeneratedFile* file, const string& fileName, const string& title) {
686*e1eccf28SAndroid Build Coastguard Worker     const char offset[] = "                  ";
687*e1eccf28SAndroid Build Coastguard Worker     *file << offset << "<li><a href=\"<?cs var:toroot ?>guide/topics/renderscript/reference/"
688*e1eccf28SAndroid Build Coastguard Worker           << fileName << "\">\n";
689*e1eccf28SAndroid Build Coastguard Worker     *file << offset << "  <span class=\"en\">" << title << "</span>\n";
690*e1eccf28SAndroid Build Coastguard Worker     *file << offset << "</a></li>\n";
691*e1eccf28SAndroid Build Coastguard Worker }
692*e1eccf28SAndroid Build Coastguard Worker 
693*e1eccf28SAndroid Build Coastguard Worker /* Generate a partial file of links that should be cut & pasted into the proper section of the
694*e1eccf28SAndroid Build Coastguard Worker  * guide_toc.cs file.
695*e1eccf28SAndroid Build Coastguard Worker  */
generateAndroidTableOfContentSnippet(const string & directory)696*e1eccf28SAndroid Build Coastguard Worker static bool generateAndroidTableOfContentSnippet(const string& directory) {
697*e1eccf28SAndroid Build Coastguard Worker     GeneratedFile file;
698*e1eccf28SAndroid Build Coastguard Worker     if (!file.start(directory, "guide_toc.cs")) {
699*e1eccf28SAndroid Build Coastguard Worker         return false;
700*e1eccf28SAndroid Build Coastguard Worker     }
701*e1eccf28SAndroid Build Coastguard Worker     file << "<!-- Copy and paste the following lines into the RenderScript section of\n";
702*e1eccf28SAndroid Build Coastguard Worker     file << "     platform/frameworks/base/docs/html/guide/guide_toc.cs\n\n";
703*e1eccf28SAndroid Build Coastguard Worker 
704*e1eccf28SAndroid Build Coastguard Worker     const char offset[] = "              ";
705*e1eccf28SAndroid Build Coastguard Worker     file << offset << "<li class=\"nav-section\">\n";
706*e1eccf28SAndroid Build Coastguard Worker     file << offset << "  <div class=\"nav-section-header\">\n";
707*e1eccf28SAndroid Build Coastguard Worker     file << offset << "    <a href=\"<?cs var:toroot ?>guide/topics/renderscript/reference/" <<
708*e1eccf28SAndroid Build Coastguard Worker             OVERVIEW_HTML_FILE_NAME << "\">\n";
709*e1eccf28SAndroid Build Coastguard Worker     file << offset << "      <span class=\"en\">Runtime API Reference</span>\n";
710*e1eccf28SAndroid Build Coastguard Worker     file << offset << "    </a></div>\n";
711*e1eccf28SAndroid Build Coastguard Worker     file << offset << "  <ul>\n";
712*e1eccf28SAndroid Build Coastguard Worker 
713*e1eccf28SAndroid Build Coastguard Worker     for (auto specFile : systemSpecification.getSpecFiles()) {
714*e1eccf28SAndroid Build Coastguard Worker         if (specFile->hasSpecifications()) {
715*e1eccf28SAndroid Build Coastguard Worker             const string fileName = stringReplace(specFile->getSpecFileName(), ".spec", ".html");
716*e1eccf28SAndroid Build Coastguard Worker             generateSnippet(&file, fileName, specFile->getBriefDescription());
717*e1eccf28SAndroid Build Coastguard Worker         }
718*e1eccf28SAndroid Build Coastguard Worker     }
719*e1eccf28SAndroid Build Coastguard Worker     generateSnippet(&file, INDEX_HTML_FILE_NAME, "Index");
720*e1eccf28SAndroid Build Coastguard Worker 
721*e1eccf28SAndroid Build Coastguard Worker     file << offset << "  </ul>\n";
722*e1eccf28SAndroid Build Coastguard Worker     file << offset << "</li>\n";
723*e1eccf28SAndroid Build Coastguard Worker 
724*e1eccf28SAndroid Build Coastguard Worker     return true;
725*e1eccf28SAndroid Build Coastguard Worker }
726*e1eccf28SAndroid Build Coastguard Worker 
generateDocumentation(const string & directory)727*e1eccf28SAndroid Build Coastguard Worker bool generateDocumentation(const string& directory) {
728*e1eccf28SAndroid Build Coastguard Worker     bool success = generateOverview(directory) &&
729*e1eccf28SAndroid Build Coastguard Worker                    generateAlphabeticalIndex(directory) &&
730*e1eccf28SAndroid Build Coastguard Worker                    generateAndroidTableOfContentSnippet(directory);
731*e1eccf28SAndroid Build Coastguard Worker     for (auto specFile : systemSpecification.getSpecFiles()) {
732*e1eccf28SAndroid Build Coastguard Worker         if (!writeDetailedDocumentationFile(directory, *specFile)) {
733*e1eccf28SAndroid Build Coastguard Worker             success = false;
734*e1eccf28SAndroid Build Coastguard Worker         }
735*e1eccf28SAndroid Build Coastguard Worker     }
736*e1eccf28SAndroid Build Coastguard Worker     return success;
737*e1eccf28SAndroid Build Coastguard Worker }
738