1*e1eccf28SAndroid Build Coastguard Worker /*
2*e1eccf28SAndroid Build Coastguard Worker * Copyright (C) 2013 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 <stdio.h>
18*e1eccf28SAndroid Build Coastguard Worker #include <cctype>
19*e1eccf28SAndroid Build Coastguard Worker #include <cstdlib>
20*e1eccf28SAndroid Build Coastguard Worker #include <fstream>
21*e1eccf28SAndroid Build Coastguard Worker #include <functional>
22*e1eccf28SAndroid Build Coastguard Worker #include <iostream>
23*e1eccf28SAndroid Build Coastguard Worker #include <memory>
24*e1eccf28SAndroid Build Coastguard Worker #include <sstream>
25*e1eccf28SAndroid Build Coastguard Worker #include <strings.h>
26*e1eccf28SAndroid Build Coastguard Worker
27*e1eccf28SAndroid Build Coastguard Worker #include "Generator.h"
28*e1eccf28SAndroid Build Coastguard Worker #include "Scanner.h"
29*e1eccf28SAndroid Build Coastguard Worker #include "Specification.h"
30*e1eccf28SAndroid Build Coastguard Worker #include "Utilities.h"
31*e1eccf28SAndroid Build Coastguard Worker
32*e1eccf28SAndroid Build Coastguard Worker using namespace std;
33*e1eccf28SAndroid Build Coastguard Worker
34*e1eccf28SAndroid Build Coastguard Worker // API level when RenderScript was added.
35*e1eccf28SAndroid Build Coastguard Worker const unsigned int MIN_API_LEVEL = 9;
36*e1eccf28SAndroid Build Coastguard Worker
37*e1eccf28SAndroid Build Coastguard Worker const NumericalType TYPES[] = {
38*e1eccf28SAndroid Build Coastguard Worker {"f16", "FLOAT_16", "half", "short", FLOATING_POINT, 11, 5},
39*e1eccf28SAndroid Build Coastguard Worker {"f32", "FLOAT_32", "float", "float", FLOATING_POINT, 24, 8},
40*e1eccf28SAndroid Build Coastguard Worker {"f64", "FLOAT_64", "double", "double", FLOATING_POINT, 53, 11},
41*e1eccf28SAndroid Build Coastguard Worker {"i8", "SIGNED_8", "char", "byte", SIGNED_INTEGER, 7, 0},
42*e1eccf28SAndroid Build Coastguard Worker {"u8", "UNSIGNED_8", "uchar", "byte", UNSIGNED_INTEGER, 8, 0},
43*e1eccf28SAndroid Build Coastguard Worker {"i16", "SIGNED_16", "short", "short", SIGNED_INTEGER, 15, 0},
44*e1eccf28SAndroid Build Coastguard Worker {"u16", "UNSIGNED_16", "ushort", "short", UNSIGNED_INTEGER, 16, 0},
45*e1eccf28SAndroid Build Coastguard Worker {"i32", "SIGNED_32", "int", "int", SIGNED_INTEGER, 31, 0},
46*e1eccf28SAndroid Build Coastguard Worker {"u32", "UNSIGNED_32", "uint", "int", UNSIGNED_INTEGER, 32, 0},
47*e1eccf28SAndroid Build Coastguard Worker {"i64", "SIGNED_64", "long", "long", SIGNED_INTEGER, 63, 0},
48*e1eccf28SAndroid Build Coastguard Worker {"u64", "UNSIGNED_64", "ulong", "long", UNSIGNED_INTEGER, 64, 0},
49*e1eccf28SAndroid Build Coastguard Worker };
50*e1eccf28SAndroid Build Coastguard Worker
51*e1eccf28SAndroid Build Coastguard Worker const int NUM_TYPES = sizeof(TYPES) / sizeof(TYPES[0]);
52*e1eccf28SAndroid Build Coastguard Worker
53*e1eccf28SAndroid Build Coastguard Worker static const char kTagUnreleased[] = "UNRELEASED";
54*e1eccf28SAndroid Build Coastguard Worker
55*e1eccf28SAndroid Build Coastguard Worker // Patterns that get substituted with C type or RS Data type names in function
56*e1eccf28SAndroid Build Coastguard Worker // names, arguments, return types, and inlines.
57*e1eccf28SAndroid Build Coastguard Worker static const string kCTypePatterns[] = {"#1", "#2", "#3", "#4"};
58*e1eccf28SAndroid Build Coastguard Worker static const string kRSTypePatterns[] = {"#RST_1", "#RST_2", "#RST_3", "#RST_4"};
59*e1eccf28SAndroid Build Coastguard Worker
60*e1eccf28SAndroid Build Coastguard Worker // The singleton of the collected information of all the spec files.
61*e1eccf28SAndroid Build Coastguard Worker SystemSpecification systemSpecification;
62*e1eccf28SAndroid Build Coastguard Worker
63*e1eccf28SAndroid Build Coastguard Worker // Returns the index in TYPES for the provided cType
findCType(const string & cType)64*e1eccf28SAndroid Build Coastguard Worker static int findCType(const string& cType) {
65*e1eccf28SAndroid Build Coastguard Worker for (int i = 0; i < NUM_TYPES; i++) {
66*e1eccf28SAndroid Build Coastguard Worker if (cType == TYPES[i].cType) {
67*e1eccf28SAndroid Build Coastguard Worker return i;
68*e1eccf28SAndroid Build Coastguard Worker }
69*e1eccf28SAndroid Build Coastguard Worker }
70*e1eccf28SAndroid Build Coastguard Worker return -1;
71*e1eccf28SAndroid Build Coastguard Worker }
72*e1eccf28SAndroid Build Coastguard Worker
73*e1eccf28SAndroid Build Coastguard Worker /* Converts a string like "u8, u16" to a vector of "ushort", "uint".
74*e1eccf28SAndroid Build Coastguard Worker * For non-numerical types, we don't need to convert the abbreviation.
75*e1eccf28SAndroid Build Coastguard Worker */
convertToTypeVector(const string & input)76*e1eccf28SAndroid Build Coastguard Worker static vector<string> convertToTypeVector(const string& input) {
77*e1eccf28SAndroid Build Coastguard Worker // First convert the string to an array of strings.
78*e1eccf28SAndroid Build Coastguard Worker vector<string> entries;
79*e1eccf28SAndroid Build Coastguard Worker stringstream stream(input);
80*e1eccf28SAndroid Build Coastguard Worker string entry;
81*e1eccf28SAndroid Build Coastguard Worker while (getline(stream, entry, ',')) {
82*e1eccf28SAndroid Build Coastguard Worker trimSpaces(&entry);
83*e1eccf28SAndroid Build Coastguard Worker entries.push_back(entry);
84*e1eccf28SAndroid Build Coastguard Worker }
85*e1eccf28SAndroid Build Coastguard Worker
86*e1eccf28SAndroid Build Coastguard Worker /* Second, we look for present numerical types. We do it this way
87*e1eccf28SAndroid Build Coastguard Worker * so the order of numerical types is always the same, no matter
88*e1eccf28SAndroid Build Coastguard Worker * how specified in the spec file.
89*e1eccf28SAndroid Build Coastguard Worker */
90*e1eccf28SAndroid Build Coastguard Worker vector<string> result;
91*e1eccf28SAndroid Build Coastguard Worker for (auto t : TYPES) {
92*e1eccf28SAndroid Build Coastguard Worker for (auto i = entries.begin(); i != entries.end(); ++i) {
93*e1eccf28SAndroid Build Coastguard Worker if (*i == t.specType) {
94*e1eccf28SAndroid Build Coastguard Worker result.push_back(t.cType);
95*e1eccf28SAndroid Build Coastguard Worker entries.erase(i);
96*e1eccf28SAndroid Build Coastguard Worker break;
97*e1eccf28SAndroid Build Coastguard Worker }
98*e1eccf28SAndroid Build Coastguard Worker }
99*e1eccf28SAndroid Build Coastguard Worker }
100*e1eccf28SAndroid Build Coastguard Worker
101*e1eccf28SAndroid Build Coastguard Worker // Add the remaining; they are not numerical types.
102*e1eccf28SAndroid Build Coastguard Worker for (auto s : entries) {
103*e1eccf28SAndroid Build Coastguard Worker result.push_back(s);
104*e1eccf28SAndroid Build Coastguard Worker }
105*e1eccf28SAndroid Build Coastguard Worker
106*e1eccf28SAndroid Build Coastguard Worker return result;
107*e1eccf28SAndroid Build Coastguard Worker }
108*e1eccf28SAndroid Build Coastguard Worker
109*e1eccf28SAndroid Build Coastguard Worker // Returns true if each entry in typeVector is an RS numerical type
isRSTValid(const vector<string> & typeVector)110*e1eccf28SAndroid Build Coastguard Worker static bool isRSTValid(const vector<string> &typeVector) {
111*e1eccf28SAndroid Build Coastguard Worker for (auto type: typeVector) {
112*e1eccf28SAndroid Build Coastguard Worker if (findCType(type) == -1)
113*e1eccf28SAndroid Build Coastguard Worker return false;
114*e1eccf28SAndroid Build Coastguard Worker }
115*e1eccf28SAndroid Build Coastguard Worker return true;
116*e1eccf28SAndroid Build Coastguard Worker }
117*e1eccf28SAndroid Build Coastguard Worker
getVectorSizeAndBaseType(const string & type,string & vectorSize,string & baseType)118*e1eccf28SAndroid Build Coastguard Worker void getVectorSizeAndBaseType(const string& type, string& vectorSize, string& baseType) {
119*e1eccf28SAndroid Build Coastguard Worker vectorSize = "1";
120*e1eccf28SAndroid Build Coastguard Worker baseType = type;
121*e1eccf28SAndroid Build Coastguard Worker
122*e1eccf28SAndroid Build Coastguard Worker /* If it's a vector type, we need to split the base type from the size.
123*e1eccf28SAndroid Build Coastguard Worker * We know that's it's a vector type if the last character is a digit and
124*e1eccf28SAndroid Build Coastguard Worker * the rest is an actual base type. We used to only verify the first part,
125*e1eccf28SAndroid Build Coastguard Worker * which created a problem with rs_matrix2x2.
126*e1eccf28SAndroid Build Coastguard Worker */
127*e1eccf28SAndroid Build Coastguard Worker const int last = type.size() - 1;
128*e1eccf28SAndroid Build Coastguard Worker const char lastChar = type[last];
129*e1eccf28SAndroid Build Coastguard Worker if (lastChar >= '0' && lastChar <= '9') {
130*e1eccf28SAndroid Build Coastguard Worker const string trimmed = type.substr(0, last);
131*e1eccf28SAndroid Build Coastguard Worker int i = findCType(trimmed);
132*e1eccf28SAndroid Build Coastguard Worker if (i >= 0) {
133*e1eccf28SAndroid Build Coastguard Worker baseType = trimmed;
134*e1eccf28SAndroid Build Coastguard Worker vectorSize = lastChar;
135*e1eccf28SAndroid Build Coastguard Worker }
136*e1eccf28SAndroid Build Coastguard Worker }
137*e1eccf28SAndroid Build Coastguard Worker }
138*e1eccf28SAndroid Build Coastguard Worker
parseParameterDefinition(const string & type,const string & name,const string & testOption,int lineNumber,bool isReturn,Scanner * scanner)139*e1eccf28SAndroid Build Coastguard Worker void ParameterDefinition::parseParameterDefinition(const string& type, const string& name,
140*e1eccf28SAndroid Build Coastguard Worker const string& testOption, int lineNumber,
141*e1eccf28SAndroid Build Coastguard Worker bool isReturn, Scanner* scanner) {
142*e1eccf28SAndroid Build Coastguard Worker rsType = type;
143*e1eccf28SAndroid Build Coastguard Worker specName = name;
144*e1eccf28SAndroid Build Coastguard Worker
145*e1eccf28SAndroid Build Coastguard Worker // Determine if this is an output.
146*e1eccf28SAndroid Build Coastguard Worker isOutParameter = isReturn || charRemoved('*', &rsType);
147*e1eccf28SAndroid Build Coastguard Worker
148*e1eccf28SAndroid Build Coastguard Worker getVectorSizeAndBaseType(rsType, mVectorSize, rsBaseType);
149*e1eccf28SAndroid Build Coastguard Worker typeIndex = findCType(rsBaseType);
150*e1eccf28SAndroid Build Coastguard Worker
151*e1eccf28SAndroid Build Coastguard Worker if (mVectorSize == "3") {
152*e1eccf28SAndroid Build Coastguard Worker vectorWidth = "4";
153*e1eccf28SAndroid Build Coastguard Worker } else {
154*e1eccf28SAndroid Build Coastguard Worker vectorWidth = mVectorSize;
155*e1eccf28SAndroid Build Coastguard Worker }
156*e1eccf28SAndroid Build Coastguard Worker
157*e1eccf28SAndroid Build Coastguard Worker /* Create variable names to be used in the java and .rs files. Because x and
158*e1eccf28SAndroid Build Coastguard Worker * y are reserved in .rs files, we prefix variable names with "in" or "out".
159*e1eccf28SAndroid Build Coastguard Worker */
160*e1eccf28SAndroid Build Coastguard Worker if (isOutParameter) {
161*e1eccf28SAndroid Build Coastguard Worker variableName = "out";
162*e1eccf28SAndroid Build Coastguard Worker if (!specName.empty()) {
163*e1eccf28SAndroid Build Coastguard Worker variableName += capitalize(specName);
164*e1eccf28SAndroid Build Coastguard Worker } else if (!isReturn) {
165*e1eccf28SAndroid Build Coastguard Worker scanner->error(lineNumber) << "Should have a name.\n";
166*e1eccf28SAndroid Build Coastguard Worker }
167*e1eccf28SAndroid Build Coastguard Worker doubleVariableName = variableName + "Double";
168*e1eccf28SAndroid Build Coastguard Worker } else {
169*e1eccf28SAndroid Build Coastguard Worker variableName = "in";
170*e1eccf28SAndroid Build Coastguard Worker if (specName.empty()) {
171*e1eccf28SAndroid Build Coastguard Worker scanner->error(lineNumber) << "Should have a name.\n";
172*e1eccf28SAndroid Build Coastguard Worker }
173*e1eccf28SAndroid Build Coastguard Worker variableName += capitalize(specName);
174*e1eccf28SAndroid Build Coastguard Worker doubleVariableName = variableName + "Double";
175*e1eccf28SAndroid Build Coastguard Worker }
176*e1eccf28SAndroid Build Coastguard Worker rsAllocName = "gAlloc" + capitalize(variableName);
177*e1eccf28SAndroid Build Coastguard Worker javaAllocName = variableName;
178*e1eccf28SAndroid Build Coastguard Worker javaArrayName = "array" + capitalize(javaAllocName);
179*e1eccf28SAndroid Build Coastguard Worker
180*e1eccf28SAndroid Build Coastguard Worker // Process the option.
181*e1eccf28SAndroid Build Coastguard Worker undefinedIfOutIsNan = false;
182*e1eccf28SAndroid Build Coastguard Worker compatibleTypeIndex = -1;
183*e1eccf28SAndroid Build Coastguard Worker if (!testOption.empty()) {
184*e1eccf28SAndroid Build Coastguard Worker if (testOption.compare(0, 6, "range(") == 0) {
185*e1eccf28SAndroid Build Coastguard Worker size_t pComma = testOption.find(',');
186*e1eccf28SAndroid Build Coastguard Worker size_t pParen = testOption.find(')');
187*e1eccf28SAndroid Build Coastguard Worker if (pComma == string::npos || pParen == string::npos) {
188*e1eccf28SAndroid Build Coastguard Worker scanner->error(lineNumber) << "Incorrect range " << testOption << "\n";
189*e1eccf28SAndroid Build Coastguard Worker } else {
190*e1eccf28SAndroid Build Coastguard Worker minValue = testOption.substr(6, pComma - 6);
191*e1eccf28SAndroid Build Coastguard Worker maxValue = testOption.substr(pComma + 1, pParen - pComma - 1);
192*e1eccf28SAndroid Build Coastguard Worker }
193*e1eccf28SAndroid Build Coastguard Worker } else if (testOption.compare(0, 6, "above(") == 0) {
194*e1eccf28SAndroid Build Coastguard Worker size_t pParen = testOption.find(')');
195*e1eccf28SAndroid Build Coastguard Worker if (pParen == string::npos) {
196*e1eccf28SAndroid Build Coastguard Worker scanner->error(lineNumber) << "Incorrect testOption " << testOption << "\n";
197*e1eccf28SAndroid Build Coastguard Worker } else {
198*e1eccf28SAndroid Build Coastguard Worker smallerParameter = testOption.substr(6, pParen - 6);
199*e1eccf28SAndroid Build Coastguard Worker }
200*e1eccf28SAndroid Build Coastguard Worker } else if (testOption.compare(0, 11, "compatible(") == 0) {
201*e1eccf28SAndroid Build Coastguard Worker size_t pParen = testOption.find(')');
202*e1eccf28SAndroid Build Coastguard Worker if (pParen == string::npos) {
203*e1eccf28SAndroid Build Coastguard Worker scanner->error(lineNumber) << "Incorrect testOption " << testOption << "\n";
204*e1eccf28SAndroid Build Coastguard Worker } else {
205*e1eccf28SAndroid Build Coastguard Worker compatibleTypeIndex = findCType(testOption.substr(11, pParen - 11));
206*e1eccf28SAndroid Build Coastguard Worker }
207*e1eccf28SAndroid Build Coastguard Worker } else if (testOption.compare(0, 11, "conditional") == 0) {
208*e1eccf28SAndroid Build Coastguard Worker undefinedIfOutIsNan = true;
209*e1eccf28SAndroid Build Coastguard Worker } else {
210*e1eccf28SAndroid Build Coastguard Worker scanner->error(lineNumber) << "Unrecognized testOption " << testOption << "\n";
211*e1eccf28SAndroid Build Coastguard Worker }
212*e1eccf28SAndroid Build Coastguard Worker }
213*e1eccf28SAndroid Build Coastguard Worker
214*e1eccf28SAndroid Build Coastguard Worker isFloatType = false;
215*e1eccf28SAndroid Build Coastguard Worker if (typeIndex >= 0) {
216*e1eccf28SAndroid Build Coastguard Worker javaBaseType = TYPES[typeIndex].javaType;
217*e1eccf28SAndroid Build Coastguard Worker specType = TYPES[typeIndex].specType;
218*e1eccf28SAndroid Build Coastguard Worker isFloatType = TYPES[typeIndex].exponentBits > 0;
219*e1eccf28SAndroid Build Coastguard Worker }
220*e1eccf28SAndroid Build Coastguard Worker if (!minValue.empty()) {
221*e1eccf28SAndroid Build Coastguard Worker if (typeIndex < 0 || TYPES[typeIndex].kind != FLOATING_POINT) {
222*e1eccf28SAndroid Build Coastguard Worker scanner->error(lineNumber) << "range(,) is only supported for floating point\n";
223*e1eccf28SAndroid Build Coastguard Worker }
224*e1eccf28SAndroid Build Coastguard Worker }
225*e1eccf28SAndroid Build Coastguard Worker }
226*e1eccf28SAndroid Build Coastguard Worker
scan(Scanner * scanner,unsigned int maxApiLevel)227*e1eccf28SAndroid Build Coastguard Worker bool VersionInfo::scan(Scanner* scanner, unsigned int maxApiLevel) {
228*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("version:")) {
229*e1eccf28SAndroid Build Coastguard Worker const string s = scanner->getValue();
230*e1eccf28SAndroid Build Coastguard Worker if (s.compare(0, sizeof(kTagUnreleased), kTagUnreleased) == 0) {
231*e1eccf28SAndroid Build Coastguard Worker // The API is still under development and does not have
232*e1eccf28SAndroid Build Coastguard Worker // an official version number.
233*e1eccf28SAndroid Build Coastguard Worker minVersion = maxVersion = kUnreleasedVersion;
234*e1eccf28SAndroid Build Coastguard Worker } else {
235*e1eccf28SAndroid Build Coastguard Worker sscanf(s.c_str(), "%u %u", &minVersion, &maxVersion);
236*e1eccf28SAndroid Build Coastguard Worker if (minVersion && minVersion < MIN_API_LEVEL) {
237*e1eccf28SAndroid Build Coastguard Worker scanner->error() << "Minimum version must >= 9\n";
238*e1eccf28SAndroid Build Coastguard Worker }
239*e1eccf28SAndroid Build Coastguard Worker if (minVersion == MIN_API_LEVEL) {
240*e1eccf28SAndroid Build Coastguard Worker minVersion = 0;
241*e1eccf28SAndroid Build Coastguard Worker }
242*e1eccf28SAndroid Build Coastguard Worker if (maxVersion && maxVersion < MIN_API_LEVEL) {
243*e1eccf28SAndroid Build Coastguard Worker scanner->error() << "Maximum version must >= 9\n";
244*e1eccf28SAndroid Build Coastguard Worker }
245*e1eccf28SAndroid Build Coastguard Worker }
246*e1eccf28SAndroid Build Coastguard Worker }
247*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("size:")) {
248*e1eccf28SAndroid Build Coastguard Worker sscanf(scanner->getValue().c_str(), "%i", &intSize);
249*e1eccf28SAndroid Build Coastguard Worker }
250*e1eccf28SAndroid Build Coastguard Worker
251*e1eccf28SAndroid Build Coastguard Worker if (maxVersion > maxApiLevel) {
252*e1eccf28SAndroid Build Coastguard Worker maxVersion = maxApiLevel;
253*e1eccf28SAndroid Build Coastguard Worker }
254*e1eccf28SAndroid Build Coastguard Worker
255*e1eccf28SAndroid Build Coastguard Worker return minVersion == 0 || minVersion <= maxApiLevel;
256*e1eccf28SAndroid Build Coastguard Worker }
257*e1eccf28SAndroid Build Coastguard Worker
Definition(const std::string & name)258*e1eccf28SAndroid Build Coastguard Worker Definition::Definition(const std::string& name)
259*e1eccf28SAndroid Build Coastguard Worker : mName(name), mDeprecatedApiLevel(0), mHidden(false), mFinalVersion(-1) {
260*e1eccf28SAndroid Build Coastguard Worker }
261*e1eccf28SAndroid Build Coastguard Worker
updateFinalVersion(const VersionInfo & info)262*e1eccf28SAndroid Build Coastguard Worker void Definition::updateFinalVersion(const VersionInfo& info) {
263*e1eccf28SAndroid Build Coastguard Worker /* We set it if:
264*e1eccf28SAndroid Build Coastguard Worker * - We have never set mFinalVersion before, or
265*e1eccf28SAndroid Build Coastguard Worker * - The max version is 0, which means we have not expired this API, or
266*e1eccf28SAndroid Build Coastguard Worker * - We have a max that's later than what we currently have.
267*e1eccf28SAndroid Build Coastguard Worker */
268*e1eccf28SAndroid Build Coastguard Worker if (mFinalVersion < 0 || info.maxVersion == 0 ||
269*e1eccf28SAndroid Build Coastguard Worker (mFinalVersion > 0 &&
270*e1eccf28SAndroid Build Coastguard Worker static_cast<int>(info.maxVersion) > mFinalVersion)) {
271*e1eccf28SAndroid Build Coastguard Worker mFinalVersion = info.maxVersion;
272*e1eccf28SAndroid Build Coastguard Worker }
273*e1eccf28SAndroid Build Coastguard Worker }
274*e1eccf28SAndroid Build Coastguard Worker
scanDocumentationTags(Scanner * scanner,bool firstOccurence,const SpecFile * specFile)275*e1eccf28SAndroid Build Coastguard Worker void Definition::scanDocumentationTags(Scanner* scanner, bool firstOccurence,
276*e1eccf28SAndroid Build Coastguard Worker const SpecFile* specFile) {
277*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("hidden:")) {
278*e1eccf28SAndroid Build Coastguard Worker scanner->checkNoValue();
279*e1eccf28SAndroid Build Coastguard Worker mHidden = true;
280*e1eccf28SAndroid Build Coastguard Worker }
281*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("deprecated:")) {
282*e1eccf28SAndroid Build Coastguard Worker string value = scanner->getValue();
283*e1eccf28SAndroid Build Coastguard Worker size_t pComma = value.find(", ");
284*e1eccf28SAndroid Build Coastguard Worker if (pComma != string::npos) {
285*e1eccf28SAndroid Build Coastguard Worker mDeprecatedMessage = value.substr(pComma + 2);
286*e1eccf28SAndroid Build Coastguard Worker value.erase(pComma);
287*e1eccf28SAndroid Build Coastguard Worker }
288*e1eccf28SAndroid Build Coastguard Worker sscanf(value.c_str(), "%i", &mDeprecatedApiLevel);
289*e1eccf28SAndroid Build Coastguard Worker if (mDeprecatedApiLevel <= 0) {
290*e1eccf28SAndroid Build Coastguard Worker scanner->error() << "deprecated entries should have a level > 0\n";
291*e1eccf28SAndroid Build Coastguard Worker }
292*e1eccf28SAndroid Build Coastguard Worker }
293*e1eccf28SAndroid Build Coastguard Worker if (firstOccurence) {
294*e1eccf28SAndroid Build Coastguard Worker if (scanner->findTag("summary:")) {
295*e1eccf28SAndroid Build Coastguard Worker mSummary = scanner->getValue();
296*e1eccf28SAndroid Build Coastguard Worker }
297*e1eccf28SAndroid Build Coastguard Worker if (scanner->findTag("description:")) {
298*e1eccf28SAndroid Build Coastguard Worker scanner->checkNoValue();
299*e1eccf28SAndroid Build Coastguard Worker while (scanner->findOptionalTag("")) {
300*e1eccf28SAndroid Build Coastguard Worker mDescription.push_back(scanner->getValue());
301*e1eccf28SAndroid Build Coastguard Worker }
302*e1eccf28SAndroid Build Coastguard Worker }
303*e1eccf28SAndroid Build Coastguard Worker mUrl = specFile->getDetailedDocumentationUrl() + "#android_rs:" + mName;
304*e1eccf28SAndroid Build Coastguard Worker } else if (scanner->findOptionalTag("summary:")) {
305*e1eccf28SAndroid Build Coastguard Worker scanner->error() << "Only the first specification should have a summary.\n";
306*e1eccf28SAndroid Build Coastguard Worker }
307*e1eccf28SAndroid Build Coastguard Worker }
308*e1eccf28SAndroid Build Coastguard Worker
~Constant()309*e1eccf28SAndroid Build Coastguard Worker Constant::~Constant() {
310*e1eccf28SAndroid Build Coastguard Worker for (auto i : mSpecifications) {
311*e1eccf28SAndroid Build Coastguard Worker delete i;
312*e1eccf28SAndroid Build Coastguard Worker }
313*e1eccf28SAndroid Build Coastguard Worker }
314*e1eccf28SAndroid Build Coastguard Worker
~Type()315*e1eccf28SAndroid Build Coastguard Worker Type::~Type() {
316*e1eccf28SAndroid Build Coastguard Worker for (auto i : mSpecifications) {
317*e1eccf28SAndroid Build Coastguard Worker delete i;
318*e1eccf28SAndroid Build Coastguard Worker }
319*e1eccf28SAndroid Build Coastguard Worker }
320*e1eccf28SAndroid Build Coastguard Worker
Function(const string & name)321*e1eccf28SAndroid Build Coastguard Worker Function::Function(const string& name) : Definition(name) {
322*e1eccf28SAndroid Build Coastguard Worker mCapitalizedName = capitalize(mName);
323*e1eccf28SAndroid Build Coastguard Worker }
324*e1eccf28SAndroid Build Coastguard Worker
~Function()325*e1eccf28SAndroid Build Coastguard Worker Function::~Function() {
326*e1eccf28SAndroid Build Coastguard Worker for (auto i : mSpecifications) {
327*e1eccf28SAndroid Build Coastguard Worker delete i;
328*e1eccf28SAndroid Build Coastguard Worker }
329*e1eccf28SAndroid Build Coastguard Worker }
330*e1eccf28SAndroid Build Coastguard Worker
someParametersAreDocumented() const331*e1eccf28SAndroid Build Coastguard Worker bool Function::someParametersAreDocumented() const {
332*e1eccf28SAndroid Build Coastguard Worker for (auto p : mParameters) {
333*e1eccf28SAndroid Build Coastguard Worker if (!p->documentation.empty()) {
334*e1eccf28SAndroid Build Coastguard Worker return true;
335*e1eccf28SAndroid Build Coastguard Worker }
336*e1eccf28SAndroid Build Coastguard Worker }
337*e1eccf28SAndroid Build Coastguard Worker return false;
338*e1eccf28SAndroid Build Coastguard Worker }
339*e1eccf28SAndroid Build Coastguard Worker
addParameter(ParameterEntry * entry,Scanner * scanner)340*e1eccf28SAndroid Build Coastguard Worker void Function::addParameter(ParameterEntry* entry, Scanner* scanner) {
341*e1eccf28SAndroid Build Coastguard Worker for (auto i : mParameters) {
342*e1eccf28SAndroid Build Coastguard Worker if (i->name == entry->name) {
343*e1eccf28SAndroid Build Coastguard Worker // It's a duplicate.
344*e1eccf28SAndroid Build Coastguard Worker if (!entry->documentation.empty()) {
345*e1eccf28SAndroid Build Coastguard Worker scanner->error(entry->lineNumber)
346*e1eccf28SAndroid Build Coastguard Worker << "Only the first occurence of an arg should have the "
347*e1eccf28SAndroid Build Coastguard Worker "documentation.\n";
348*e1eccf28SAndroid Build Coastguard Worker }
349*e1eccf28SAndroid Build Coastguard Worker return;
350*e1eccf28SAndroid Build Coastguard Worker }
351*e1eccf28SAndroid Build Coastguard Worker }
352*e1eccf28SAndroid Build Coastguard Worker mParameters.push_back(entry);
353*e1eccf28SAndroid Build Coastguard Worker }
354*e1eccf28SAndroid Build Coastguard Worker
addReturn(ParameterEntry * entry,Scanner * scanner)355*e1eccf28SAndroid Build Coastguard Worker void Function::addReturn(ParameterEntry* entry, Scanner* scanner) {
356*e1eccf28SAndroid Build Coastguard Worker if (entry->documentation.empty()) {
357*e1eccf28SAndroid Build Coastguard Worker return;
358*e1eccf28SAndroid Build Coastguard Worker }
359*e1eccf28SAndroid Build Coastguard Worker if (!mReturnDocumentation.empty()) {
360*e1eccf28SAndroid Build Coastguard Worker scanner->error() << "ret: should be documented only for the first variant\n";
361*e1eccf28SAndroid Build Coastguard Worker }
362*e1eccf28SAndroid Build Coastguard Worker mReturnDocumentation = entry->documentation;
363*e1eccf28SAndroid Build Coastguard Worker }
364*e1eccf28SAndroid Build Coastguard Worker
scanConstantSpecification(Scanner * scanner,SpecFile * specFile,unsigned int maxApiLevel)365*e1eccf28SAndroid Build Coastguard Worker void ConstantSpecification::scanConstantSpecification(Scanner* scanner, SpecFile* specFile,
366*e1eccf28SAndroid Build Coastguard Worker unsigned int maxApiLevel) {
367*e1eccf28SAndroid Build Coastguard Worker string name = scanner->getValue();
368*e1eccf28SAndroid Build Coastguard Worker VersionInfo info;
369*e1eccf28SAndroid Build Coastguard Worker if (!info.scan(scanner, maxApiLevel)) {
370*e1eccf28SAndroid Build Coastguard Worker cout << "Skipping some " << name << " definitions.\n";
371*e1eccf28SAndroid Build Coastguard Worker scanner->skipUntilTag("end:");
372*e1eccf28SAndroid Build Coastguard Worker return;
373*e1eccf28SAndroid Build Coastguard Worker }
374*e1eccf28SAndroid Build Coastguard Worker
375*e1eccf28SAndroid Build Coastguard Worker bool created = false;
376*e1eccf28SAndroid Build Coastguard Worker Constant* constant = systemSpecification.findOrCreateConstant(name, &created);
377*e1eccf28SAndroid Build Coastguard Worker ConstantSpecification* spec = new ConstantSpecification(constant);
378*e1eccf28SAndroid Build Coastguard Worker constant->addSpecification(spec);
379*e1eccf28SAndroid Build Coastguard Worker constant->updateFinalVersion(info);
380*e1eccf28SAndroid Build Coastguard Worker specFile->addConstantSpecification(spec, created);
381*e1eccf28SAndroid Build Coastguard Worker spec->mVersionInfo = info;
382*e1eccf28SAndroid Build Coastguard Worker
383*e1eccf28SAndroid Build Coastguard Worker if (scanner->findTag("value:")) {
384*e1eccf28SAndroid Build Coastguard Worker spec->mValue = scanner->getValue();
385*e1eccf28SAndroid Build Coastguard Worker }
386*e1eccf28SAndroid Build Coastguard Worker if (scanner->findTag("type:")) {
387*e1eccf28SAndroid Build Coastguard Worker spec->mType = scanner->getValue();
388*e1eccf28SAndroid Build Coastguard Worker }
389*e1eccf28SAndroid Build Coastguard Worker constant->scanDocumentationTags(scanner, created, specFile);
390*e1eccf28SAndroid Build Coastguard Worker
391*e1eccf28SAndroid Build Coastguard Worker scanner->findTag("end:");
392*e1eccf28SAndroid Build Coastguard Worker }
393*e1eccf28SAndroid Build Coastguard Worker
scanTypeSpecification(Scanner * scanner,SpecFile * specFile,unsigned int maxApiLevel)394*e1eccf28SAndroid Build Coastguard Worker void TypeSpecification::scanTypeSpecification(Scanner* scanner, SpecFile* specFile,
395*e1eccf28SAndroid Build Coastguard Worker unsigned int maxApiLevel) {
396*e1eccf28SAndroid Build Coastguard Worker string name = scanner->getValue();
397*e1eccf28SAndroid Build Coastguard Worker VersionInfo info;
398*e1eccf28SAndroid Build Coastguard Worker if (!info.scan(scanner, maxApiLevel)) {
399*e1eccf28SAndroid Build Coastguard Worker cout << "Skipping some " << name << " definitions.\n";
400*e1eccf28SAndroid Build Coastguard Worker scanner->skipUntilTag("end:");
401*e1eccf28SAndroid Build Coastguard Worker return;
402*e1eccf28SAndroid Build Coastguard Worker }
403*e1eccf28SAndroid Build Coastguard Worker
404*e1eccf28SAndroid Build Coastguard Worker bool created = false;
405*e1eccf28SAndroid Build Coastguard Worker Type* type = systemSpecification.findOrCreateType(name, &created);
406*e1eccf28SAndroid Build Coastguard Worker TypeSpecification* spec = new TypeSpecification(type);
407*e1eccf28SAndroid Build Coastguard Worker type->addSpecification(spec);
408*e1eccf28SAndroid Build Coastguard Worker type->updateFinalVersion(info);
409*e1eccf28SAndroid Build Coastguard Worker specFile->addTypeSpecification(spec, created);
410*e1eccf28SAndroid Build Coastguard Worker spec->mVersionInfo = info;
411*e1eccf28SAndroid Build Coastguard Worker
412*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("simple:")) {
413*e1eccf28SAndroid Build Coastguard Worker spec->mKind = SIMPLE;
414*e1eccf28SAndroid Build Coastguard Worker spec->mSimpleType = scanner->getValue();
415*e1eccf28SAndroid Build Coastguard Worker }
416*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("rs_object:")) {
417*e1eccf28SAndroid Build Coastguard Worker spec->mKind = RS_OBJECT;
418*e1eccf28SAndroid Build Coastguard Worker }
419*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("struct:")) {
420*e1eccf28SAndroid Build Coastguard Worker spec->mKind = STRUCT;
421*e1eccf28SAndroid Build Coastguard Worker spec->mStructName = scanner->getValue();
422*e1eccf28SAndroid Build Coastguard Worker while (scanner->findOptionalTag("field:")) {
423*e1eccf28SAndroid Build Coastguard Worker string s = scanner->getValue();
424*e1eccf28SAndroid Build Coastguard Worker string comment;
425*e1eccf28SAndroid Build Coastguard Worker scanner->parseDocumentation(&s, &comment);
426*e1eccf28SAndroid Build Coastguard Worker spec->mFields.push_back(s);
427*e1eccf28SAndroid Build Coastguard Worker spec->mFieldComments.push_back(comment);
428*e1eccf28SAndroid Build Coastguard Worker }
429*e1eccf28SAndroid Build Coastguard Worker }
430*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("enum:")) {
431*e1eccf28SAndroid Build Coastguard Worker spec->mKind = ENUM;
432*e1eccf28SAndroid Build Coastguard Worker spec->mEnumName = scanner->getValue();
433*e1eccf28SAndroid Build Coastguard Worker while (scanner->findOptionalTag("value:")) {
434*e1eccf28SAndroid Build Coastguard Worker string s = scanner->getValue();
435*e1eccf28SAndroid Build Coastguard Worker string comment;
436*e1eccf28SAndroid Build Coastguard Worker scanner->parseDocumentation(&s, &comment);
437*e1eccf28SAndroid Build Coastguard Worker spec->mValues.push_back(s);
438*e1eccf28SAndroid Build Coastguard Worker spec->mValueComments.push_back(comment);
439*e1eccf28SAndroid Build Coastguard Worker }
440*e1eccf28SAndroid Build Coastguard Worker }
441*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("attrib:")) {
442*e1eccf28SAndroid Build Coastguard Worker spec->mAttribute = scanner->getValue();
443*e1eccf28SAndroid Build Coastguard Worker }
444*e1eccf28SAndroid Build Coastguard Worker type->scanDocumentationTags(scanner, created, specFile);
445*e1eccf28SAndroid Build Coastguard Worker
446*e1eccf28SAndroid Build Coastguard Worker scanner->findTag("end:");
447*e1eccf28SAndroid Build Coastguard Worker }
448*e1eccf28SAndroid Build Coastguard Worker
~FunctionSpecification()449*e1eccf28SAndroid Build Coastguard Worker FunctionSpecification::~FunctionSpecification() {
450*e1eccf28SAndroid Build Coastguard Worker for (auto i : mParameters) {
451*e1eccf28SAndroid Build Coastguard Worker delete i;
452*e1eccf28SAndroid Build Coastguard Worker }
453*e1eccf28SAndroid Build Coastguard Worker delete mReturn;
454*e1eccf28SAndroid Build Coastguard Worker for (auto i : mPermutations) {
455*e1eccf28SAndroid Build Coastguard Worker delete i;
456*e1eccf28SAndroid Build Coastguard Worker }
457*e1eccf28SAndroid Build Coastguard Worker }
458*e1eccf28SAndroid Build Coastguard Worker
expandRSTypeInString(const string & s,const string & pattern,const string & cTypeStr) const459*e1eccf28SAndroid Build Coastguard Worker string FunctionSpecification::expandRSTypeInString(const string &s,
460*e1eccf28SAndroid Build Coastguard Worker const string &pattern,
461*e1eccf28SAndroid Build Coastguard Worker const string &cTypeStr) const {
462*e1eccf28SAndroid Build Coastguard Worker // Find index of numerical type corresponding to cTypeStr. The case where
463*e1eccf28SAndroid Build Coastguard Worker // pattern is found in s but cTypeStr is not a numerical type is checked in
464*e1eccf28SAndroid Build Coastguard Worker // checkRSTPatternValidity.
465*e1eccf28SAndroid Build Coastguard Worker int typeIdx = findCType(cTypeStr);
466*e1eccf28SAndroid Build Coastguard Worker if (typeIdx == -1) {
467*e1eccf28SAndroid Build Coastguard Worker return s;
468*e1eccf28SAndroid Build Coastguard Worker }
469*e1eccf28SAndroid Build Coastguard Worker // If index exists, perform replacement.
470*e1eccf28SAndroid Build Coastguard Worker return stringReplace(s, pattern, TYPES[typeIdx].rsDataType);
471*e1eccf28SAndroid Build Coastguard Worker }
472*e1eccf28SAndroid Build Coastguard Worker
expandString(string s,int replacementIndexes[MAX_REPLACEABLES]) const473*e1eccf28SAndroid Build Coastguard Worker string FunctionSpecification::expandString(string s,
474*e1eccf28SAndroid Build Coastguard Worker int replacementIndexes[MAX_REPLACEABLES]) const {
475*e1eccf28SAndroid Build Coastguard Worker
476*e1eccf28SAndroid Build Coastguard Worker
477*e1eccf28SAndroid Build Coastguard Worker for (unsigned idx = 0; idx < mReplaceables.size(); idx ++) {
478*e1eccf28SAndroid Build Coastguard Worker string toString = mReplaceables[idx][replacementIndexes[idx]];
479*e1eccf28SAndroid Build Coastguard Worker
480*e1eccf28SAndroid Build Coastguard Worker // replace #RST_i patterns with RS datatype corresponding to toString
481*e1eccf28SAndroid Build Coastguard Worker s = expandRSTypeInString(s, kRSTypePatterns[idx], toString);
482*e1eccf28SAndroid Build Coastguard Worker
483*e1eccf28SAndroid Build Coastguard Worker // replace #i patterns with C type from mReplaceables
484*e1eccf28SAndroid Build Coastguard Worker s = stringReplace(s, kCTypePatterns[idx], toString);
485*e1eccf28SAndroid Build Coastguard Worker }
486*e1eccf28SAndroid Build Coastguard Worker
487*e1eccf28SAndroid Build Coastguard Worker return s;
488*e1eccf28SAndroid Build Coastguard Worker }
489*e1eccf28SAndroid Build Coastguard Worker
expandStringVector(const vector<string> & in,int replacementIndexes[MAX_REPLACEABLES],vector<string> * out) const490*e1eccf28SAndroid Build Coastguard Worker void FunctionSpecification::expandStringVector(const vector<string>& in,
491*e1eccf28SAndroid Build Coastguard Worker int replacementIndexes[MAX_REPLACEABLES],
492*e1eccf28SAndroid Build Coastguard Worker vector<string>* out) const {
493*e1eccf28SAndroid Build Coastguard Worker out->clear();
494*e1eccf28SAndroid Build Coastguard Worker for (vector<string>::const_iterator iter = in.begin(); iter != in.end(); iter++) {
495*e1eccf28SAndroid Build Coastguard Worker out->push_back(expandString(*iter, replacementIndexes));
496*e1eccf28SAndroid Build Coastguard Worker }
497*e1eccf28SAndroid Build Coastguard Worker }
498*e1eccf28SAndroid Build Coastguard Worker
createPermutations(Function * function,Scanner * scanner)499*e1eccf28SAndroid Build Coastguard Worker void FunctionSpecification::createPermutations(Function* function, Scanner* scanner) {
500*e1eccf28SAndroid Build Coastguard Worker int start[MAX_REPLACEABLES];
501*e1eccf28SAndroid Build Coastguard Worker int end[MAX_REPLACEABLES];
502*e1eccf28SAndroid Build Coastguard Worker for (int i = 0; i < MAX_REPLACEABLES; i++) {
503*e1eccf28SAndroid Build Coastguard Worker if (i < (int)mReplaceables.size()) {
504*e1eccf28SAndroid Build Coastguard Worker start[i] = 0;
505*e1eccf28SAndroid Build Coastguard Worker end[i] = mReplaceables[i].size();
506*e1eccf28SAndroid Build Coastguard Worker } else {
507*e1eccf28SAndroid Build Coastguard Worker start[i] = -1;
508*e1eccf28SAndroid Build Coastguard Worker end[i] = 0;
509*e1eccf28SAndroid Build Coastguard Worker }
510*e1eccf28SAndroid Build Coastguard Worker }
511*e1eccf28SAndroid Build Coastguard Worker int replacementIndexes[MAX_REPLACEABLES];
512*e1eccf28SAndroid Build Coastguard Worker // TODO: These loops assume that MAX_REPLACEABLES is 4.
513*e1eccf28SAndroid Build Coastguard Worker for (replacementIndexes[3] = start[3]; replacementIndexes[3] < end[3];
514*e1eccf28SAndroid Build Coastguard Worker replacementIndexes[3]++) {
515*e1eccf28SAndroid Build Coastguard Worker for (replacementIndexes[2] = start[2]; replacementIndexes[2] < end[2];
516*e1eccf28SAndroid Build Coastguard Worker replacementIndexes[2]++) {
517*e1eccf28SAndroid Build Coastguard Worker for (replacementIndexes[1] = start[1]; replacementIndexes[1] < end[1];
518*e1eccf28SAndroid Build Coastguard Worker replacementIndexes[1]++) {
519*e1eccf28SAndroid Build Coastguard Worker for (replacementIndexes[0] = start[0]; replacementIndexes[0] < end[0];
520*e1eccf28SAndroid Build Coastguard Worker replacementIndexes[0]++) {
521*e1eccf28SAndroid Build Coastguard Worker auto p = new FunctionPermutation(function, this, replacementIndexes, scanner);
522*e1eccf28SAndroid Build Coastguard Worker mPermutations.push_back(p);
523*e1eccf28SAndroid Build Coastguard Worker }
524*e1eccf28SAndroid Build Coastguard Worker }
525*e1eccf28SAndroid Build Coastguard Worker }
526*e1eccf28SAndroid Build Coastguard Worker }
527*e1eccf28SAndroid Build Coastguard Worker }
528*e1eccf28SAndroid Build Coastguard Worker
getName(int replacementIndexes[MAX_REPLACEABLES]) const529*e1eccf28SAndroid Build Coastguard Worker string FunctionSpecification::getName(int replacementIndexes[MAX_REPLACEABLES]) const {
530*e1eccf28SAndroid Build Coastguard Worker return expandString(mUnexpandedName, replacementIndexes);
531*e1eccf28SAndroid Build Coastguard Worker }
532*e1eccf28SAndroid Build Coastguard Worker
getReturn(int replacementIndexes[MAX_REPLACEABLES],std::string * retType,int * lineNumber) const533*e1eccf28SAndroid Build Coastguard Worker void FunctionSpecification::getReturn(int replacementIndexes[MAX_REPLACEABLES],
534*e1eccf28SAndroid Build Coastguard Worker std::string* retType, int* lineNumber) const {
535*e1eccf28SAndroid Build Coastguard Worker *retType = expandString(mReturn->type, replacementIndexes);
536*e1eccf28SAndroid Build Coastguard Worker *lineNumber = mReturn->lineNumber;
537*e1eccf28SAndroid Build Coastguard Worker }
538*e1eccf28SAndroid Build Coastguard Worker
getParam(size_t index,int replacementIndexes[MAX_REPLACEABLES],std::string * type,std::string * name,std::string * testOption,int * lineNumber) const539*e1eccf28SAndroid Build Coastguard Worker void FunctionSpecification::getParam(size_t index, int replacementIndexes[MAX_REPLACEABLES],
540*e1eccf28SAndroid Build Coastguard Worker std::string* type, std::string* name, std::string* testOption,
541*e1eccf28SAndroid Build Coastguard Worker int* lineNumber) const {
542*e1eccf28SAndroid Build Coastguard Worker ParameterEntry* p = mParameters[index];
543*e1eccf28SAndroid Build Coastguard Worker *type = expandString(p->type, replacementIndexes);
544*e1eccf28SAndroid Build Coastguard Worker *name = p->name;
545*e1eccf28SAndroid Build Coastguard Worker *testOption = expandString(p->testOption, replacementIndexes);
546*e1eccf28SAndroid Build Coastguard Worker *lineNumber = p->lineNumber;
547*e1eccf28SAndroid Build Coastguard Worker }
548*e1eccf28SAndroid Build Coastguard Worker
getInlines(int replacementIndexes[MAX_REPLACEABLES],std::vector<std::string> * inlines) const549*e1eccf28SAndroid Build Coastguard Worker void FunctionSpecification::getInlines(int replacementIndexes[MAX_REPLACEABLES],
550*e1eccf28SAndroid Build Coastguard Worker std::vector<std::string>* inlines) const {
551*e1eccf28SAndroid Build Coastguard Worker expandStringVector(mInline, replacementIndexes, inlines);
552*e1eccf28SAndroid Build Coastguard Worker }
553*e1eccf28SAndroid Build Coastguard Worker
parseTest(Scanner * scanner)554*e1eccf28SAndroid Build Coastguard Worker void FunctionSpecification::parseTest(Scanner* scanner) {
555*e1eccf28SAndroid Build Coastguard Worker const string value = scanner->getValue();
556*e1eccf28SAndroid Build Coastguard Worker if (value == "scalar" || value == "vector" || value == "noverify" || value == "custom" ||
557*e1eccf28SAndroid Build Coastguard Worker value == "none") {
558*e1eccf28SAndroid Build Coastguard Worker mTest = value;
559*e1eccf28SAndroid Build Coastguard Worker } else if (value.compare(0, 7, "limited") == 0) {
560*e1eccf28SAndroid Build Coastguard Worker mTest = "limited";
561*e1eccf28SAndroid Build Coastguard Worker if (value.compare(7, 1, "(") == 0) {
562*e1eccf28SAndroid Build Coastguard Worker size_t pParen = value.find(')');
563*e1eccf28SAndroid Build Coastguard Worker if (pParen == string::npos) {
564*e1eccf28SAndroid Build Coastguard Worker scanner->error() << "Incorrect test: \"" << value << "\"\n";
565*e1eccf28SAndroid Build Coastguard Worker } else {
566*e1eccf28SAndroid Build Coastguard Worker mPrecisionLimit = value.substr(8, pParen - 8);
567*e1eccf28SAndroid Build Coastguard Worker }
568*e1eccf28SAndroid Build Coastguard Worker }
569*e1eccf28SAndroid Build Coastguard Worker } else {
570*e1eccf28SAndroid Build Coastguard Worker scanner->error() << "Unrecognized test option: \"" << value << "\"\n";
571*e1eccf28SAndroid Build Coastguard Worker }
572*e1eccf28SAndroid Build Coastguard Worker }
573*e1eccf28SAndroid Build Coastguard Worker
hasTests(unsigned int versionOfTestFiles) const574*e1eccf28SAndroid Build Coastguard Worker bool FunctionSpecification::hasTests(unsigned int versionOfTestFiles) const {
575*e1eccf28SAndroid Build Coastguard Worker if (mVersionInfo.maxVersion != 0 && mVersionInfo.maxVersion < versionOfTestFiles) {
576*e1eccf28SAndroid Build Coastguard Worker return false;
577*e1eccf28SAndroid Build Coastguard Worker }
578*e1eccf28SAndroid Build Coastguard Worker if (mTest == "none") {
579*e1eccf28SAndroid Build Coastguard Worker return false;
580*e1eccf28SAndroid Build Coastguard Worker }
581*e1eccf28SAndroid Build Coastguard Worker return true;
582*e1eccf28SAndroid Build Coastguard Worker }
583*e1eccf28SAndroid Build Coastguard Worker
checkRSTPatternValidity(const string & inlineStr,bool allow,Scanner * scanner)584*e1eccf28SAndroid Build Coastguard Worker void FunctionSpecification::checkRSTPatternValidity(const string &inlineStr, bool allow,
585*e1eccf28SAndroid Build Coastguard Worker Scanner *scanner) {
586*e1eccf28SAndroid Build Coastguard Worker for (int i = 0; i < MAX_REPLACEABLES; i ++) {
587*e1eccf28SAndroid Build Coastguard Worker bool patternFound = inlineStr.find(kRSTypePatterns[i]) != string::npos;
588*e1eccf28SAndroid Build Coastguard Worker
589*e1eccf28SAndroid Build Coastguard Worker if (patternFound) {
590*e1eccf28SAndroid Build Coastguard Worker if (!allow) {
591*e1eccf28SAndroid Build Coastguard Worker scanner->error() << "RST_i pattern not allowed here\n";
592*e1eccf28SAndroid Build Coastguard Worker }
593*e1eccf28SAndroid Build Coastguard Worker else if (mIsRSTAllowed[i] == false) {
594*e1eccf28SAndroid Build Coastguard Worker scanner->error() << "Found pattern \"" << kRSTypePatterns[i]
595*e1eccf28SAndroid Build Coastguard Worker << "\" in spec. But some entry in the corresponding"
596*e1eccf28SAndroid Build Coastguard Worker << " parameter list cannot be translated to an RS type\n";
597*e1eccf28SAndroid Build Coastguard Worker }
598*e1eccf28SAndroid Build Coastguard Worker }
599*e1eccf28SAndroid Build Coastguard Worker }
600*e1eccf28SAndroid Build Coastguard Worker }
601*e1eccf28SAndroid Build Coastguard Worker
scanFunctionSpecification(Scanner * scanner,SpecFile * specFile,unsigned int maxApiLevel)602*e1eccf28SAndroid Build Coastguard Worker void FunctionSpecification::scanFunctionSpecification(Scanner* scanner, SpecFile* specFile,
603*e1eccf28SAndroid Build Coastguard Worker unsigned int maxApiLevel) {
604*e1eccf28SAndroid Build Coastguard Worker // Some functions like convert have # part of the name. Truncate at that point.
605*e1eccf28SAndroid Build Coastguard Worker const string& unexpandedName = scanner->getValue();
606*e1eccf28SAndroid Build Coastguard Worker string name = unexpandedName;
607*e1eccf28SAndroid Build Coastguard Worker size_t p = name.find('#');
608*e1eccf28SAndroid Build Coastguard Worker if (p != string::npos) {
609*e1eccf28SAndroid Build Coastguard Worker if (p > 0 && name[p - 1] == '_') {
610*e1eccf28SAndroid Build Coastguard Worker p--;
611*e1eccf28SAndroid Build Coastguard Worker }
612*e1eccf28SAndroid Build Coastguard Worker name.erase(p);
613*e1eccf28SAndroid Build Coastguard Worker }
614*e1eccf28SAndroid Build Coastguard Worker VersionInfo info;
615*e1eccf28SAndroid Build Coastguard Worker if (!info.scan(scanner, maxApiLevel)) {
616*e1eccf28SAndroid Build Coastguard Worker cout << "Skipping some " << name << " definitions.\n";
617*e1eccf28SAndroid Build Coastguard Worker scanner->skipUntilTag("end:");
618*e1eccf28SAndroid Build Coastguard Worker return;
619*e1eccf28SAndroid Build Coastguard Worker }
620*e1eccf28SAndroid Build Coastguard Worker
621*e1eccf28SAndroid Build Coastguard Worker bool created = false;
622*e1eccf28SAndroid Build Coastguard Worker Function* function = systemSpecification.findOrCreateFunction(name, &created);
623*e1eccf28SAndroid Build Coastguard Worker FunctionSpecification* spec = new FunctionSpecification(function);
624*e1eccf28SAndroid Build Coastguard Worker function->addSpecification(spec);
625*e1eccf28SAndroid Build Coastguard Worker function->updateFinalVersion(info);
626*e1eccf28SAndroid Build Coastguard Worker specFile->addFunctionSpecification(spec, created);
627*e1eccf28SAndroid Build Coastguard Worker
628*e1eccf28SAndroid Build Coastguard Worker spec->mUnexpandedName = unexpandedName;
629*e1eccf28SAndroid Build Coastguard Worker spec->mTest = "scalar"; // default
630*e1eccf28SAndroid Build Coastguard Worker spec->mVersionInfo = info;
631*e1eccf28SAndroid Build Coastguard Worker
632*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("internal:")) {
633*e1eccf28SAndroid Build Coastguard Worker spec->mInternal = (scanner->getValue() == "true");
634*e1eccf28SAndroid Build Coastguard Worker }
635*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("intrinsic:")) {
636*e1eccf28SAndroid Build Coastguard Worker spec->mIntrinsic = (scanner->getValue() == "true");
637*e1eccf28SAndroid Build Coastguard Worker }
638*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("attrib:")) {
639*e1eccf28SAndroid Build Coastguard Worker spec->mAttribute = scanner->getValue();
640*e1eccf28SAndroid Build Coastguard Worker }
641*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("w:")) {
642*e1eccf28SAndroid Build Coastguard Worker vector<string> t;
643*e1eccf28SAndroid Build Coastguard Worker if (scanner->getValue().find("1") != string::npos) {
644*e1eccf28SAndroid Build Coastguard Worker t.push_back("");
645*e1eccf28SAndroid Build Coastguard Worker }
646*e1eccf28SAndroid Build Coastguard Worker if (scanner->getValue().find("2") != string::npos) {
647*e1eccf28SAndroid Build Coastguard Worker t.push_back("2");
648*e1eccf28SAndroid Build Coastguard Worker }
649*e1eccf28SAndroid Build Coastguard Worker if (scanner->getValue().find("3") != string::npos) {
650*e1eccf28SAndroid Build Coastguard Worker t.push_back("3");
651*e1eccf28SAndroid Build Coastguard Worker }
652*e1eccf28SAndroid Build Coastguard Worker if (scanner->getValue().find("4") != string::npos) {
653*e1eccf28SAndroid Build Coastguard Worker t.push_back("4");
654*e1eccf28SAndroid Build Coastguard Worker }
655*e1eccf28SAndroid Build Coastguard Worker spec->mReplaceables.push_back(t);
656*e1eccf28SAndroid Build Coastguard Worker // RST_i pattern not applicable for width.
657*e1eccf28SAndroid Build Coastguard Worker spec->mIsRSTAllowed.push_back(false);
658*e1eccf28SAndroid Build Coastguard Worker }
659*e1eccf28SAndroid Build Coastguard Worker
660*e1eccf28SAndroid Build Coastguard Worker while (scanner->findOptionalTag("t:")) {
661*e1eccf28SAndroid Build Coastguard Worker spec->mReplaceables.push_back(convertToTypeVector(scanner->getValue()));
662*e1eccf28SAndroid Build Coastguard Worker spec->mIsRSTAllowed.push_back(isRSTValid(spec->mReplaceables.back()));
663*e1eccf28SAndroid Build Coastguard Worker }
664*e1eccf28SAndroid Build Coastguard Worker
665*e1eccf28SAndroid Build Coastguard Worker // Disallow RST_* pattern in function name
666*e1eccf28SAndroid Build Coastguard Worker // FIXME the line number for this error would be wrong
667*e1eccf28SAndroid Build Coastguard Worker spec->checkRSTPatternValidity(unexpandedName, false, scanner);
668*e1eccf28SAndroid Build Coastguard Worker
669*e1eccf28SAndroid Build Coastguard Worker if (scanner->findTag("ret:")) {
670*e1eccf28SAndroid Build Coastguard Worker ParameterEntry* p = scanner->parseArgString(true);
671*e1eccf28SAndroid Build Coastguard Worker function->addReturn(p, scanner);
672*e1eccf28SAndroid Build Coastguard Worker spec->mReturn = p;
673*e1eccf28SAndroid Build Coastguard Worker
674*e1eccf28SAndroid Build Coastguard Worker // Disallow RST_* pattern in return type
675*e1eccf28SAndroid Build Coastguard Worker spec->checkRSTPatternValidity(p->type, false, scanner);
676*e1eccf28SAndroid Build Coastguard Worker }
677*e1eccf28SAndroid Build Coastguard Worker while (scanner->findOptionalTag("arg:")) {
678*e1eccf28SAndroid Build Coastguard Worker ParameterEntry* p = scanner->parseArgString(false);
679*e1eccf28SAndroid Build Coastguard Worker function->addParameter(p, scanner);
680*e1eccf28SAndroid Build Coastguard Worker spec->mParameters.push_back(p);
681*e1eccf28SAndroid Build Coastguard Worker
682*e1eccf28SAndroid Build Coastguard Worker // Disallow RST_* pattern in parameter type or testOption
683*e1eccf28SAndroid Build Coastguard Worker spec->checkRSTPatternValidity(p->type, false, scanner);
684*e1eccf28SAndroid Build Coastguard Worker spec->checkRSTPatternValidity(p->testOption, false, scanner);
685*e1eccf28SAndroid Build Coastguard Worker }
686*e1eccf28SAndroid Build Coastguard Worker
687*e1eccf28SAndroid Build Coastguard Worker function->scanDocumentationTags(scanner, created, specFile);
688*e1eccf28SAndroid Build Coastguard Worker
689*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("inline:")) {
690*e1eccf28SAndroid Build Coastguard Worker scanner->checkNoValue();
691*e1eccf28SAndroid Build Coastguard Worker while (scanner->findOptionalTag("")) {
692*e1eccf28SAndroid Build Coastguard Worker spec->mInline.push_back(scanner->getValue());
693*e1eccf28SAndroid Build Coastguard Worker
694*e1eccf28SAndroid Build Coastguard Worker // Allow RST_* pattern in inline definitions
695*e1eccf28SAndroid Build Coastguard Worker spec->checkRSTPatternValidity(spec->mInline.back(), true, scanner);
696*e1eccf28SAndroid Build Coastguard Worker }
697*e1eccf28SAndroid Build Coastguard Worker }
698*e1eccf28SAndroid Build Coastguard Worker if (scanner->findOptionalTag("test:")) {
699*e1eccf28SAndroid Build Coastguard Worker spec->parseTest(scanner);
700*e1eccf28SAndroid Build Coastguard Worker }
701*e1eccf28SAndroid Build Coastguard Worker
702*e1eccf28SAndroid Build Coastguard Worker scanner->findTag("end:");
703*e1eccf28SAndroid Build Coastguard Worker
704*e1eccf28SAndroid Build Coastguard Worker spec->createPermutations(function, scanner);
705*e1eccf28SAndroid Build Coastguard Worker }
706*e1eccf28SAndroid Build Coastguard Worker
FunctionPermutation(Function * func,FunctionSpecification * spec,int replacementIndexes[MAX_REPLACEABLES],Scanner * scanner)707*e1eccf28SAndroid Build Coastguard Worker FunctionPermutation::FunctionPermutation(Function* func, FunctionSpecification* spec,
708*e1eccf28SAndroid Build Coastguard Worker int replacementIndexes[MAX_REPLACEABLES], Scanner* scanner)
709*e1eccf28SAndroid Build Coastguard Worker : mReturn(nullptr), mInputCount(0), mOutputCount(0) {
710*e1eccf28SAndroid Build Coastguard Worker // We expand the strings now to make capitalization easier. The previous code preserved
711*e1eccf28SAndroid Build Coastguard Worker // the #n
712*e1eccf28SAndroid Build Coastguard Worker // markers just before emitting, which made capitalization difficult.
713*e1eccf28SAndroid Build Coastguard Worker mName = spec->getName(replacementIndexes);
714*e1eccf28SAndroid Build Coastguard Worker mNameTrunk = func->getName();
715*e1eccf28SAndroid Build Coastguard Worker mTest = spec->getTest();
716*e1eccf28SAndroid Build Coastguard Worker mPrecisionLimit = spec->getPrecisionLimit();
717*e1eccf28SAndroid Build Coastguard Worker spec->getInlines(replacementIndexes, &mInline);
718*e1eccf28SAndroid Build Coastguard Worker
719*e1eccf28SAndroid Build Coastguard Worker mHasFloatAnswers = false;
720*e1eccf28SAndroid Build Coastguard Worker for (size_t i = 0; i < spec->getNumberOfParams(); i++) {
721*e1eccf28SAndroid Build Coastguard Worker string type, name, testOption;
722*e1eccf28SAndroid Build Coastguard Worker int lineNumber = 0;
723*e1eccf28SAndroid Build Coastguard Worker spec->getParam(i, replacementIndexes, &type, &name, &testOption, &lineNumber);
724*e1eccf28SAndroid Build Coastguard Worker ParameterDefinition* def = new ParameterDefinition();
725*e1eccf28SAndroid Build Coastguard Worker def->parseParameterDefinition(type, name, testOption, lineNumber, false, scanner);
726*e1eccf28SAndroid Build Coastguard Worker if (def->isOutParameter) {
727*e1eccf28SAndroid Build Coastguard Worker mOutputCount++;
728*e1eccf28SAndroid Build Coastguard Worker } else {
729*e1eccf28SAndroid Build Coastguard Worker mInputCount++;
730*e1eccf28SAndroid Build Coastguard Worker }
731*e1eccf28SAndroid Build Coastguard Worker
732*e1eccf28SAndroid Build Coastguard Worker if (def->typeIndex < 0 && mTest != "none") {
733*e1eccf28SAndroid Build Coastguard Worker scanner->error(lineNumber)
734*e1eccf28SAndroid Build Coastguard Worker << "Could not find " << def->rsBaseType
735*e1eccf28SAndroid Build Coastguard Worker << " while generating automated tests. Use test: none if not needed.\n";
736*e1eccf28SAndroid Build Coastguard Worker }
737*e1eccf28SAndroid Build Coastguard Worker if (def->isOutParameter && def->isFloatType) {
738*e1eccf28SAndroid Build Coastguard Worker mHasFloatAnswers = true;
739*e1eccf28SAndroid Build Coastguard Worker }
740*e1eccf28SAndroid Build Coastguard Worker mParams.push_back(def);
741*e1eccf28SAndroid Build Coastguard Worker }
742*e1eccf28SAndroid Build Coastguard Worker
743*e1eccf28SAndroid Build Coastguard Worker string retType;
744*e1eccf28SAndroid Build Coastguard Worker int lineNumber = 0;
745*e1eccf28SAndroid Build Coastguard Worker spec->getReturn(replacementIndexes, &retType, &lineNumber);
746*e1eccf28SAndroid Build Coastguard Worker if (!retType.empty()) {
747*e1eccf28SAndroid Build Coastguard Worker mReturn = new ParameterDefinition();
748*e1eccf28SAndroid Build Coastguard Worker mReturn->parseParameterDefinition(retType, "", "", lineNumber, true, scanner);
749*e1eccf28SAndroid Build Coastguard Worker if (mReturn->isFloatType) {
750*e1eccf28SAndroid Build Coastguard Worker mHasFloatAnswers = true;
751*e1eccf28SAndroid Build Coastguard Worker }
752*e1eccf28SAndroid Build Coastguard Worker mOutputCount++;
753*e1eccf28SAndroid Build Coastguard Worker }
754*e1eccf28SAndroid Build Coastguard Worker }
755*e1eccf28SAndroid Build Coastguard Worker
~FunctionPermutation()756*e1eccf28SAndroid Build Coastguard Worker FunctionPermutation::~FunctionPermutation() {
757*e1eccf28SAndroid Build Coastguard Worker for (auto i : mParams) {
758*e1eccf28SAndroid Build Coastguard Worker delete i;
759*e1eccf28SAndroid Build Coastguard Worker }
760*e1eccf28SAndroid Build Coastguard Worker delete mReturn;
761*e1eccf28SAndroid Build Coastguard Worker }
762*e1eccf28SAndroid Build Coastguard Worker
SpecFile(const string & specFileName)763*e1eccf28SAndroid Build Coastguard Worker SpecFile::SpecFile(const string& specFileName) : mSpecFileName(specFileName) {
764*e1eccf28SAndroid Build Coastguard Worker string core = mSpecFileName;
765*e1eccf28SAndroid Build Coastguard Worker // Remove .spec
766*e1eccf28SAndroid Build Coastguard Worker size_t l = core.length();
767*e1eccf28SAndroid Build Coastguard Worker const char SPEC[] = ".spec";
768*e1eccf28SAndroid Build Coastguard Worker const int SPEC_SIZE = sizeof(SPEC) - 1;
769*e1eccf28SAndroid Build Coastguard Worker const int start = l - SPEC_SIZE;
770*e1eccf28SAndroid Build Coastguard Worker if (start >= 0 && core.compare(start, SPEC_SIZE, SPEC) == 0) {
771*e1eccf28SAndroid Build Coastguard Worker core.erase(start);
772*e1eccf28SAndroid Build Coastguard Worker }
773*e1eccf28SAndroid Build Coastguard Worker
774*e1eccf28SAndroid Build Coastguard Worker // The header file name should have the same base but with a ".rsh" extension.
775*e1eccf28SAndroid Build Coastguard Worker mHeaderFileName = core + ".rsh";
776*e1eccf28SAndroid Build Coastguard Worker mDetailedDocumentationUrl = core + ".html";
777*e1eccf28SAndroid Build Coastguard Worker }
778*e1eccf28SAndroid Build Coastguard Worker
addConstantSpecification(ConstantSpecification * spec,bool hasDocumentation)779*e1eccf28SAndroid Build Coastguard Worker void SpecFile::addConstantSpecification(ConstantSpecification* spec, bool hasDocumentation) {
780*e1eccf28SAndroid Build Coastguard Worker mConstantSpecificationsList.push_back(spec);
781*e1eccf28SAndroid Build Coastguard Worker if (hasDocumentation) {
782*e1eccf28SAndroid Build Coastguard Worker Constant* constant = spec->getConstant();
783*e1eccf28SAndroid Build Coastguard Worker mDocumentedConstants.insert(pair<string, Constant*>(constant->getName(), constant));
784*e1eccf28SAndroid Build Coastguard Worker }
785*e1eccf28SAndroid Build Coastguard Worker }
786*e1eccf28SAndroid Build Coastguard Worker
addTypeSpecification(TypeSpecification * spec,bool hasDocumentation)787*e1eccf28SAndroid Build Coastguard Worker void SpecFile::addTypeSpecification(TypeSpecification* spec, bool hasDocumentation) {
788*e1eccf28SAndroid Build Coastguard Worker mTypeSpecificationsList.push_back(spec);
789*e1eccf28SAndroid Build Coastguard Worker if (hasDocumentation) {
790*e1eccf28SAndroid Build Coastguard Worker Type* type = spec->getType();
791*e1eccf28SAndroid Build Coastguard Worker mDocumentedTypes.insert(pair<string, Type*>(type->getName(), type));
792*e1eccf28SAndroid Build Coastguard Worker }
793*e1eccf28SAndroid Build Coastguard Worker }
794*e1eccf28SAndroid Build Coastguard Worker
addFunctionSpecification(FunctionSpecification * spec,bool hasDocumentation)795*e1eccf28SAndroid Build Coastguard Worker void SpecFile::addFunctionSpecification(FunctionSpecification* spec, bool hasDocumentation) {
796*e1eccf28SAndroid Build Coastguard Worker mFunctionSpecificationsList.push_back(spec);
797*e1eccf28SAndroid Build Coastguard Worker if (hasDocumentation) {
798*e1eccf28SAndroid Build Coastguard Worker Function* function = spec->getFunction();
799*e1eccf28SAndroid Build Coastguard Worker mDocumentedFunctions.insert(pair<string, Function*>(function->getName(), function));
800*e1eccf28SAndroid Build Coastguard Worker }
801*e1eccf28SAndroid Build Coastguard Worker }
802*e1eccf28SAndroid Build Coastguard Worker
803*e1eccf28SAndroid Build Coastguard Worker // Read the specification, adding the definitions to the global functions map.
readSpecFile(unsigned int maxApiLevel)804*e1eccf28SAndroid Build Coastguard Worker bool SpecFile::readSpecFile(unsigned int maxApiLevel) {
805*e1eccf28SAndroid Build Coastguard Worker FILE* specFile = fopen(mSpecFileName.c_str(), "rte");
806*e1eccf28SAndroid Build Coastguard Worker if (!specFile) {
807*e1eccf28SAndroid Build Coastguard Worker cerr << "Error opening input file: " << mSpecFileName << "\n";
808*e1eccf28SAndroid Build Coastguard Worker return false;
809*e1eccf28SAndroid Build Coastguard Worker }
810*e1eccf28SAndroid Build Coastguard Worker
811*e1eccf28SAndroid Build Coastguard Worker Scanner scanner(mSpecFileName, specFile);
812*e1eccf28SAndroid Build Coastguard Worker
813*e1eccf28SAndroid Build Coastguard Worker // Scan the header that should start the file.
814*e1eccf28SAndroid Build Coastguard Worker scanner.skipBlankEntries();
815*e1eccf28SAndroid Build Coastguard Worker if (scanner.findTag("header:")) {
816*e1eccf28SAndroid Build Coastguard Worker if (scanner.findTag("summary:")) {
817*e1eccf28SAndroid Build Coastguard Worker mBriefDescription = scanner.getValue();
818*e1eccf28SAndroid Build Coastguard Worker }
819*e1eccf28SAndroid Build Coastguard Worker if (scanner.findTag("description:")) {
820*e1eccf28SAndroid Build Coastguard Worker scanner.checkNoValue();
821*e1eccf28SAndroid Build Coastguard Worker while (scanner.findOptionalTag("")) {
822*e1eccf28SAndroid Build Coastguard Worker mFullDescription.push_back(scanner.getValue());
823*e1eccf28SAndroid Build Coastguard Worker }
824*e1eccf28SAndroid Build Coastguard Worker }
825*e1eccf28SAndroid Build Coastguard Worker if (scanner.findOptionalTag("include:")) {
826*e1eccf28SAndroid Build Coastguard Worker scanner.checkNoValue();
827*e1eccf28SAndroid Build Coastguard Worker while (scanner.findOptionalTag("")) {
828*e1eccf28SAndroid Build Coastguard Worker mVerbatimInclude.push_back(scanner.getValue());
829*e1eccf28SAndroid Build Coastguard Worker }
830*e1eccf28SAndroid Build Coastguard Worker }
831*e1eccf28SAndroid Build Coastguard Worker scanner.findTag("end:");
832*e1eccf28SAndroid Build Coastguard Worker }
833*e1eccf28SAndroid Build Coastguard Worker
834*e1eccf28SAndroid Build Coastguard Worker while (1) {
835*e1eccf28SAndroid Build Coastguard Worker scanner.skipBlankEntries();
836*e1eccf28SAndroid Build Coastguard Worker if (scanner.atEnd()) {
837*e1eccf28SAndroid Build Coastguard Worker break;
838*e1eccf28SAndroid Build Coastguard Worker }
839*e1eccf28SAndroid Build Coastguard Worker const string tag = scanner.getNextTag();
840*e1eccf28SAndroid Build Coastguard Worker if (tag == "function:") {
841*e1eccf28SAndroid Build Coastguard Worker FunctionSpecification::scanFunctionSpecification(&scanner, this, maxApiLevel);
842*e1eccf28SAndroid Build Coastguard Worker } else if (tag == "type:") {
843*e1eccf28SAndroid Build Coastguard Worker TypeSpecification::scanTypeSpecification(&scanner, this, maxApiLevel);
844*e1eccf28SAndroid Build Coastguard Worker } else if (tag == "constant:") {
845*e1eccf28SAndroid Build Coastguard Worker ConstantSpecification::scanConstantSpecification(&scanner, this, maxApiLevel);
846*e1eccf28SAndroid Build Coastguard Worker } else {
847*e1eccf28SAndroid Build Coastguard Worker scanner.error() << "Expected function:, type:, or constant:. Found: " << tag << "\n";
848*e1eccf28SAndroid Build Coastguard Worker return false;
849*e1eccf28SAndroid Build Coastguard Worker }
850*e1eccf28SAndroid Build Coastguard Worker }
851*e1eccf28SAndroid Build Coastguard Worker
852*e1eccf28SAndroid Build Coastguard Worker fclose(specFile);
853*e1eccf28SAndroid Build Coastguard Worker return scanner.getErrorCount() == 0;
854*e1eccf28SAndroid Build Coastguard Worker }
855*e1eccf28SAndroid Build Coastguard Worker
~SystemSpecification()856*e1eccf28SAndroid Build Coastguard Worker SystemSpecification::~SystemSpecification() {
857*e1eccf28SAndroid Build Coastguard Worker for (auto i : mConstants) {
858*e1eccf28SAndroid Build Coastguard Worker delete i.second;
859*e1eccf28SAndroid Build Coastguard Worker }
860*e1eccf28SAndroid Build Coastguard Worker for (auto i : mTypes) {
861*e1eccf28SAndroid Build Coastguard Worker delete i.second;
862*e1eccf28SAndroid Build Coastguard Worker }
863*e1eccf28SAndroid Build Coastguard Worker for (auto i : mFunctions) {
864*e1eccf28SAndroid Build Coastguard Worker delete i.second;
865*e1eccf28SAndroid Build Coastguard Worker }
866*e1eccf28SAndroid Build Coastguard Worker for (auto i : mSpecFiles) {
867*e1eccf28SAndroid Build Coastguard Worker delete i;
868*e1eccf28SAndroid Build Coastguard Worker }
869*e1eccf28SAndroid Build Coastguard Worker }
870*e1eccf28SAndroid Build Coastguard Worker
871*e1eccf28SAndroid Build Coastguard Worker // Returns the named entry in the map. Creates it if it's not there.
872*e1eccf28SAndroid Build Coastguard Worker template <class T>
findOrCreate(const string & name,map<string,T * > * map,bool * created)873*e1eccf28SAndroid Build Coastguard Worker T* findOrCreate(const string& name, map<string, T*>* map, bool* created) {
874*e1eccf28SAndroid Build Coastguard Worker auto iter = map->find(name);
875*e1eccf28SAndroid Build Coastguard Worker if (iter != map->end()) {
876*e1eccf28SAndroid Build Coastguard Worker *created = false;
877*e1eccf28SAndroid Build Coastguard Worker return iter->second;
878*e1eccf28SAndroid Build Coastguard Worker }
879*e1eccf28SAndroid Build Coastguard Worker *created = true;
880*e1eccf28SAndroid Build Coastguard Worker T* f = new T(name);
881*e1eccf28SAndroid Build Coastguard Worker map->insert(pair<string, T*>(name, f));
882*e1eccf28SAndroid Build Coastguard Worker return f;
883*e1eccf28SAndroid Build Coastguard Worker }
884*e1eccf28SAndroid Build Coastguard Worker
findOrCreateConstant(const string & name,bool * created)885*e1eccf28SAndroid Build Coastguard Worker Constant* SystemSpecification::findOrCreateConstant(const string& name, bool* created) {
886*e1eccf28SAndroid Build Coastguard Worker return findOrCreate<Constant>(name, &mConstants, created);
887*e1eccf28SAndroid Build Coastguard Worker }
888*e1eccf28SAndroid Build Coastguard Worker
findOrCreateType(const string & name,bool * created)889*e1eccf28SAndroid Build Coastguard Worker Type* SystemSpecification::findOrCreateType(const string& name, bool* created) {
890*e1eccf28SAndroid Build Coastguard Worker return findOrCreate<Type>(name, &mTypes, created);
891*e1eccf28SAndroid Build Coastguard Worker }
892*e1eccf28SAndroid Build Coastguard Worker
findOrCreateFunction(const string & name,bool * created)893*e1eccf28SAndroid Build Coastguard Worker Function* SystemSpecification::findOrCreateFunction(const string& name, bool* created) {
894*e1eccf28SAndroid Build Coastguard Worker return findOrCreate<Function>(name, &mFunctions, created);
895*e1eccf28SAndroid Build Coastguard Worker }
896*e1eccf28SAndroid Build Coastguard Worker
readSpecFile(const string & fileName,unsigned int maxApiLevel)897*e1eccf28SAndroid Build Coastguard Worker bool SystemSpecification::readSpecFile(const string& fileName, unsigned int maxApiLevel) {
898*e1eccf28SAndroid Build Coastguard Worker SpecFile* spec = new SpecFile(fileName);
899*e1eccf28SAndroid Build Coastguard Worker if (!spec->readSpecFile(maxApiLevel)) {
900*e1eccf28SAndroid Build Coastguard Worker cerr << fileName << ": Failed to parse.\n";
901*e1eccf28SAndroid Build Coastguard Worker return false;
902*e1eccf28SAndroid Build Coastguard Worker }
903*e1eccf28SAndroid Build Coastguard Worker mSpecFiles.push_back(spec);
904*e1eccf28SAndroid Build Coastguard Worker return true;
905*e1eccf28SAndroid Build Coastguard Worker }
906*e1eccf28SAndroid Build Coastguard Worker
907*e1eccf28SAndroid Build Coastguard Worker
updateMaxApiLevel(const VersionInfo & info,unsigned int * maxApiLevel)908*e1eccf28SAndroid Build Coastguard Worker static void updateMaxApiLevel(const VersionInfo& info, unsigned int* maxApiLevel) {
909*e1eccf28SAndroid Build Coastguard Worker if (info.minVersion == VersionInfo::kUnreleasedVersion) {
910*e1eccf28SAndroid Build Coastguard Worker // Ignore development API level in consideration of max API level.
911*e1eccf28SAndroid Build Coastguard Worker return;
912*e1eccf28SAndroid Build Coastguard Worker }
913*e1eccf28SAndroid Build Coastguard Worker *maxApiLevel = max(*maxApiLevel, max(info.minVersion, info.maxVersion));
914*e1eccf28SAndroid Build Coastguard Worker }
915*e1eccf28SAndroid Build Coastguard Worker
getMaximumApiLevel()916*e1eccf28SAndroid Build Coastguard Worker unsigned int SystemSpecification::getMaximumApiLevel() {
917*e1eccf28SAndroid Build Coastguard Worker unsigned int maxApiLevel = 0;
918*e1eccf28SAndroid Build Coastguard Worker for (auto i : mConstants) {
919*e1eccf28SAndroid Build Coastguard Worker for (auto j: i.second->getSpecifications()) {
920*e1eccf28SAndroid Build Coastguard Worker updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel);
921*e1eccf28SAndroid Build Coastguard Worker }
922*e1eccf28SAndroid Build Coastguard Worker }
923*e1eccf28SAndroid Build Coastguard Worker for (auto i : mTypes) {
924*e1eccf28SAndroid Build Coastguard Worker for (auto j: i.second->getSpecifications()) {
925*e1eccf28SAndroid Build Coastguard Worker updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel);
926*e1eccf28SAndroid Build Coastguard Worker }
927*e1eccf28SAndroid Build Coastguard Worker }
928*e1eccf28SAndroid Build Coastguard Worker for (auto i : mFunctions) {
929*e1eccf28SAndroid Build Coastguard Worker for (auto j: i.second->getSpecifications()) {
930*e1eccf28SAndroid Build Coastguard Worker updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel);
931*e1eccf28SAndroid Build Coastguard Worker }
932*e1eccf28SAndroid Build Coastguard Worker }
933*e1eccf28SAndroid Build Coastguard Worker return maxApiLevel;
934*e1eccf28SAndroid Build Coastguard Worker }
935*e1eccf28SAndroid Build Coastguard Worker
generateFiles(unsigned int maxApiLevel) const936*e1eccf28SAndroid Build Coastguard Worker bool SystemSpecification::generateFiles(unsigned int maxApiLevel) const {
937*e1eccf28SAndroid Build Coastguard Worker bool success = generateHeaderFiles("include") &&
938*e1eccf28SAndroid Build Coastguard Worker generateDocumentation("docs") &&
939*e1eccf28SAndroid Build Coastguard Worker generateTestFiles("test", maxApiLevel) &&
940*e1eccf28SAndroid Build Coastguard Worker generateRSFunctionsList("slangtest", maxApiLevel);
941*e1eccf28SAndroid Build Coastguard Worker if (success) {
942*e1eccf28SAndroid Build Coastguard Worker cout << "Successfully processed " << mTypes.size() << " types, " << mConstants.size()
943*e1eccf28SAndroid Build Coastguard Worker << " constants, and " << mFunctions.size() << " functions.\n";
944*e1eccf28SAndroid Build Coastguard Worker }
945*e1eccf28SAndroid Build Coastguard Worker return success;
946*e1eccf28SAndroid Build Coastguard Worker }
947*e1eccf28SAndroid Build Coastguard Worker
getHtmlAnchor(const string & name) const948*e1eccf28SAndroid Build Coastguard Worker string SystemSpecification::getHtmlAnchor(const string& name) const {
949*e1eccf28SAndroid Build Coastguard Worker Definition* d = nullptr;
950*e1eccf28SAndroid Build Coastguard Worker auto c = mConstants.find(name);
951*e1eccf28SAndroid Build Coastguard Worker if (c != mConstants.end()) {
952*e1eccf28SAndroid Build Coastguard Worker d = c->second;
953*e1eccf28SAndroid Build Coastguard Worker } else {
954*e1eccf28SAndroid Build Coastguard Worker auto t = mTypes.find(name);
955*e1eccf28SAndroid Build Coastguard Worker if (t != mTypes.end()) {
956*e1eccf28SAndroid Build Coastguard Worker d = t->second;
957*e1eccf28SAndroid Build Coastguard Worker } else {
958*e1eccf28SAndroid Build Coastguard Worker auto f = mFunctions.find(name);
959*e1eccf28SAndroid Build Coastguard Worker if (f != mFunctions.end()) {
960*e1eccf28SAndroid Build Coastguard Worker d = f->second;
961*e1eccf28SAndroid Build Coastguard Worker } else {
962*e1eccf28SAndroid Build Coastguard Worker return string();
963*e1eccf28SAndroid Build Coastguard Worker }
964*e1eccf28SAndroid Build Coastguard Worker }
965*e1eccf28SAndroid Build Coastguard Worker }
966*e1eccf28SAndroid Build Coastguard Worker ostringstream stream;
967*e1eccf28SAndroid Build Coastguard Worker stream << "<a href='" << d->getUrl() << "'>" << name << "</a>";
968*e1eccf28SAndroid Build Coastguard Worker return stream.str();
969*e1eccf28SAndroid Build Coastguard Worker }
970