1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_RS_API_GENERATOR_SPECIFICATION_H
18 #define ANDROID_RS_API_GENERATOR_SPECIFICATION_H
19 
20 // See Generator.cpp for documentation of the .spec file format.
21 
22 #include <climits>
23 #include <fstream>
24 #include <list>
25 #include <map>
26 #include <string>
27 #include <vector>
28 
29 class Constant;
30 class ConstantSpecification;
31 class Function;
32 class FunctionPermutation;
33 class FunctionSpecification;
34 class SpecFile;
35 class Specification;
36 class Scanner;
37 class SystemSpecification;
38 class Type;
39 class TypeSpecification;
40 
41 enum NumberKind { SIGNED_INTEGER, UNSIGNED_INTEGER, FLOATING_POINT };
42 
43 // Table of type equivalences.
44 struct NumericalType {
45     const char* specType;    // Name found in the .spec file
46     const char* rsDataType;  // RS data type
47     const char* cType;       // Type in a C file
48     const char* javaType;    // Type in a Java file
49     NumberKind kind;
50     /* For integers, number of bits of the number, excluding the sign bit.
51      * For floats, number of implied bits of the mantissa.
52      */
53     int significantBits;
54     // For floats, number of bits of the exponent.  0 for integer types.
55     int exponentBits;
56 };
57 
58 /* Corresponds to one parameter line in a .spec file.  These will be parsed when
59  * we instantiate the FunctionPermutation(s) that correspond to one FunctionSpecification.
60  */
61 struct ParameterEntry {
62     std::string type;
63     std::string name;
64     /* Optional information on how to generate test values for this parameter.  Can be:
65      * - range(low, high): Generates values between these two limits only.
66      * - above(other_parameter): The values must be greater than those of the named parameter.
67      *       Used for clamp.
68      * - compatible(type): The values must also be fully representable in the specified type.
69      * - conditional: Don't verify this value the function return NaN.
70      */
71     std::string testOption;
72     std::string documentation;
73     int lineNumber;
74 };
75 
76 /* Information about a parameter to a function.  The values of all the fields should only be set by
77  * parseParameterDefinition.
78  */
79 struct ParameterDefinition {
80     std::string rsType;        // The Renderscript type, e.g. "uint3"
81     std::string rsBaseType;    // As above but without the number, e.g. "uint"
82     std::string javaBaseType;  // The type we need to declare in Java, e.g. "unsigned int"
83     std::string specType;      // The type found in the spec, e.g. "f16"
84     bool isFloatType;          // True if it's a floating point value
85     /* The number of entries in the vector.  It should be either "1", "2", "3", or "4".  It's also
86      * "1" for scalars.
87      */
88     std::string mVectorSize;
89     /* The space the vector takes in an array.  It's the same as the vector size, except for size
90      * "3", where the width is "4".
91      */
92     std::string vectorWidth;
93 
94     std::string specName;       // e.g. x, as found in the spec file
95     std::string variableName;   // e.g. inX, used both in .rs and .java
96     std::string rsAllocName;    // e.g. gAllocInX
97     std::string javaAllocName;  // e.g. inX
98     std::string javaArrayName;  // e.g. arrayInX
99     std::string doubleVariableName; // e.g. inXDouble, used in .java for storing Float16 parameters
100                                     // in double.
101 
102     // If non empty, the mininum and maximum values to be used when generating the test data.
103     std::string minValue;
104     std::string maxValue;
105     /* If non empty, contains the name of another parameter that should be smaller or equal to this
106      * parameter, i.e.  value(smallerParameter) <= value(this).  This is used when testing clamp.
107      */
108     std::string smallerParameter;
109 
110     bool isOutParameter;       // True if this parameter returns data from the script.
111     bool undefinedIfOutIsNan;  // If true, we don't validate if 'out' is NaN.
112 
113     int typeIndex;            // Index in the TYPES array. Negative if not found in the array.
114     int compatibleTypeIndex;  // Index in TYPES for which the test data must also fit.
115 
116     /* Fill this object from the type, name, and testOption.
117      * isReturn is true if we're processing the "return:"
118      */
119     void parseParameterDefinition(const std::string& type, const std::string& name,
120                                   const std::string& testOption, int lineNumber, bool isReturn,
121                                   Scanner* scanner);
122 
isFloat16ParameterParameterDefinition123     bool isFloat16Parameter() const { return specType.compare("f16") == 0; }
124 };
125 
126 struct VersionInfo {
127     /* The range of versions a specification applies to. Zero if there's no restriction,
128      * so an API that became available at 12 and is still valid would have min:12 max:0.
129      * If non zero, both versions should be at least 9, the API level that introduced
130      * RenderScript.
131      */
132     unsigned int minVersion;
133     unsigned int maxVersion;
134     // Either 0, 32 or 64.  If 0, this definition is valid for both 32 and 64 bits.
135     int intSize;
136 
VersionInfoVersionInfo137     VersionInfo() : minVersion(0), maxVersion(0), intSize(0) {}
138     /* Scan the version info from the spec file.  maxApiLevel specifies the maximum level
139      * we are interested in.  This may alter maxVersion.  This method returns false if the
140      * minVersion is greater than the maxApiLevel.
141      */
142     bool scan(Scanner* scanner, unsigned int maxApiLevel);
143     /* Return true if the target can be found whitin the range. */
includesVersionVersionInfo144     bool includesVersion(int target) const {
145         return (minVersion == 0 || target >= minVersion) &&
146                (maxVersion == 0 || target <= maxVersion);
147     }
148 
149     static constexpr unsigned int kUnreleasedVersion = UINT_MAX;
150 };
151 
152 // We have three type of definitions
153 class Definition {
154 protected:
155     std::string mName;
156     /* If greater than 0, this definition is deprecated.  It's the API level at which
157      * we added the deprecation warning.
158      */
159     int mDeprecatedApiLevel;
160     std::string mDeprecatedMessage;         // Optional specific warning if the API is deprecated
161     bool mHidden;                           // True if it should not be documented
162     std::string mSummary;                   // A one-line description
163     std::vector<std::string> mDescription;  // The comments to be included in the header
164     std::string mUrl;                       // The URL of the detailed documentation
165     int mFinalVersion;  // API level at which this API was removed, 0 if API is still valid
166 
167 public:
168     Definition(const std::string& name);
169 
getName()170     std::string getName() const { return mName; }
deprecated()171     bool deprecated() const { return mDeprecatedApiLevel > 0; }
getDeprecatedApiLevel()172     int getDeprecatedApiLevel() const { return mDeprecatedApiLevel; }
getDeprecatedMessage()173     std::string getDeprecatedMessage() const { return mDeprecatedMessage; }
hidden()174     bool hidden() const { return mHidden; }
getSummary()175     std::string getSummary() const { return mSummary; }
getDescription()176     const std::vector<std::string>& getDescription() const { return mDescription; }
getUrl()177     std::string getUrl() const { return mUrl; }
getFinalVersion()178     int getFinalVersion() const { return mFinalVersion; }
179 
180     void scanDocumentationTags(Scanner* scanner, bool firstOccurence, const SpecFile* specFile);
181     // Keep track of the final version of this API, if any.
182     void updateFinalVersion(const VersionInfo& info);
183 };
184 
185 /* Represents a constant, like M_PI.  This is a grouping of the version specific specifications.
186  * We'll only have one instance of Constant for each name.
187  */
188 class Constant : public Definition {
189 private:
190     std::vector<ConstantSpecification*> mSpecifications;  // Owned
191 
192 public:
Constant(const std::string & name)193     Constant(const std::string& name) : Definition(name) {}
194     ~Constant();
195 
getSpecifications()196     const std::vector<ConstantSpecification*> getSpecifications() const { return mSpecifications; }
197     // This method should only be called by the scanning code.
addSpecification(ConstantSpecification * spec)198     void addSpecification(ConstantSpecification* spec) { mSpecifications.push_back(spec); }
199 };
200 
201 /* Represents a type, like "float4".  This is a grouping of the version specific specifications.
202  * We'll only have one instance of Type for each name.
203  */
204 class Type : public Definition {
205 private:
206     std::vector<TypeSpecification*> mSpecifications;  // Owned
207 
208 public:
Type(const std::string & name)209     Type(const std::string& name) : Definition(name) {}
210     ~Type();
211 
getSpecifications()212     const std::vector<TypeSpecification*> getSpecifications() const { return mSpecifications; }
213     // This method should only be called by the scanning code.
addSpecification(TypeSpecification * spec)214     void addSpecification(TypeSpecification* spec) { mSpecifications.push_back(spec); }
215 };
216 
217 /* Represents a function, like "clamp".  Even though the spec file contains many entries for clamp,
218  * we'll only have one clamp instance.
219  */
220 class Function : public Definition {
221 private:
222     // mName in the base class contains the lower case name, e.g. native_log
223     std::string mCapitalizedName;  // The capitalized name, e.g. NativeLog
224 
225     // The unique parameters between all the specifications.  NOT OWNED.
226     std::vector<ParameterEntry*> mParameters;
227     std::string mReturnDocumentation;
228 
229     std::vector<FunctionSpecification*> mSpecifications;  // Owned
230 
231 public:
232     Function(const std::string& name);
233     ~Function();
234 
getCapitalizedName()235     std::string getCapitalizedName() const { return mCapitalizedName; }
getParameters()236     const std::vector<ParameterEntry*>& getParameters() const { return mParameters; }
getReturnDocumentation()237     std::string getReturnDocumentation() const { return mReturnDocumentation; }
getSpecifications()238     const std::vector<FunctionSpecification*> getSpecifications() const { return mSpecifications; }
239 
240     bool someParametersAreDocumented() const;
241 
242     // The following methods should only be called by the scanning code.
243     void addParameter(ParameterEntry* entry, Scanner* scanner);
244     void addReturn(ParameterEntry* entry, Scanner* scanner);
addSpecification(FunctionSpecification * spec)245     void addSpecification(FunctionSpecification* spec) { mSpecifications.push_back(spec); }
246 };
247 
248 /* Base class for TypeSpecification, ConstantSpecification, and FunctionSpecification.
249  * A specification can be specific to a range of RenderScript version or 32bits vs 64 bits.
250  * This base class contains code to parse and store this version information.
251  */
252 class Specification {
253 protected:
254     VersionInfo mVersionInfo;
255     void scanVersionInfo(Scanner* scanner);
256 
257 public:
getVersionInfo()258     VersionInfo getVersionInfo() const { return mVersionInfo; }
259 };
260 
261 /* Defines one of the many variations of a constant.  There's a one to one correspondance between
262  * ConstantSpecification objects and entries in the spec file.
263  */
264 class ConstantSpecification : public Specification {
265 private:
266     Constant* mConstant;  // Not owned
267 
268     std::string mValue;  // E.g. "3.1415"
269 public:
ConstantSpecification(Constant * constant)270     ConstantSpecification(Constant* constant) : mConstant(constant) {}
271 
getConstant()272     Constant* getConstant() const { return mConstant; }
getValue()273     std::string getValue() const { return mValue; }
274 
275     // Parse a constant specification and add it to specFile.
276     static void scanConstantSpecification(Scanner* scanner, SpecFile* specFile, unsigned int maxApiLevel);
277 };
278 
279 enum TypeKind {
280     SIMPLE,
281     RS_OBJECT,
282     STRUCT,
283     ENUM,
284 };
285 
286 /* Defines one of the many variations of a type.  There's a one to one correspondance between
287  * TypeSpecification objects and entries in the spec file.
288  */
289 class TypeSpecification : public Specification {
290 private:
291     Type* mType;  // Not owned
292 
293     TypeKind mKind;  // The kind of type specification
294 
295     // If mKind is SIMPLE:
296     std::string mSimpleType;  // The definition of the type
297 
298     // If mKind is STRUCT:
299     std::string mStructName;                  // The name found after the struct keyword
300     std::vector<std::string> mFields;         // One entry per struct field
301     std::vector<std::string> mFieldComments;  // One entry per struct field
302     std::string mAttribute;                   // Some structures may have attributes
303 
304     // If mKind is ENUM:
305     std::string mEnumName;                    // The name found after the enum keyword
306     std::vector<std::string> mValues;         // One entry per enum value
307     std::vector<std::string> mValueComments;  // One entry per enum value
308 public:
TypeSpecification(Type * type)309     TypeSpecification(Type* type) : mType(type) {}
310 
getType()311     Type* getType() const { return mType; }
getKind()312     TypeKind getKind() const { return mKind; }
getSimpleType()313     std::string getSimpleType() const { return mSimpleType; }
getStructName()314     std::string getStructName() const { return mStructName; }
getFields()315     const std::vector<std::string>& getFields() const { return mFields; }
getFieldComments()316     const std::vector<std::string>& getFieldComments() const { return mFieldComments; }
getAttribute()317     std::string getAttribute() const { return mAttribute; }
getEnumName()318     std::string getEnumName() const { return mEnumName; }
getValues()319     const std::vector<std::string>& getValues() const { return mValues; }
getValueComments()320     const std::vector<std::string>& getValueComments() const { return mValueComments; }
321 
322     // Parse a type specification and add it to specFile.
323     static void scanTypeSpecification(Scanner* scanner, SpecFile* specFile, unsigned int maxApiLevel);
324 };
325 
326 // Maximum number of placeholders (like #1, #2) in function specifications.
327 const int MAX_REPLACEABLES = 4;
328 
329 /* Defines one of the many variations of the function.  There's a one to one correspondance between
330  * FunctionSpecification objects and entries in the spec file.  Some of the strings that are parts
331  * of a FunctionSpecification can include placeholders, which are "#1", "#2", "#3", and "#4".  We'll
332  * replace these by values before generating the files.
333  */
334 class FunctionSpecification : public Specification {
335 private:
336     Function* mFunction;  // Not owned
337 
338     /* How to test.  One of:
339      * "scalar": Generate test code that checks entries of each vector indepently.  E.g. for
340      *           sin(float3), the test code will call the CoreMathVerfier.computeSin 3 times.
341      * "limited": Like "scalar" but we don't generate extreme values.  This is not currently
342      *            enabled as we were generating to many errors.
343      * "custom": Like "scalar" but instead of calling CoreMathVerifier.computeXXX() to compute
344      *           the expected value, we call instead CoreMathVerifier.verifyXXX().  This method
345      *           returns a string that contains the error message, null if there's no error.
346      * "vector": Generate test code that calls the CoreMathVerifier only once for each vector.
347      *           This is useful for APIs like dot() or length().
348      * "noverify": Generate test code that calls the API but don't verify the returned value.
349      *             This can discover unresolved references.
350      * "": Don't test.  This is the default.
351      */
352     std::string mTest;
353     bool mInternal;               // Internal. Not visible to users. (Default: false)
354     bool mIntrinsic;              // Compiler intrinsic that is lowered to an internal API.
355                                   // (Default: false)
356     std::string mAttribute;       // Function attributes.
357     std::string mPrecisionLimit;  // Maximum precision required when checking output of this
358                                   // function.
359 
360     // The vectors of values with which we'll replace #1, #2, ...
361     std::vector<std::vector<std::string> > mReplaceables;
362 
363     // i-th entry is true if each entry in mReplaceables[i] has an equivalent
364     // RS numerical type (i.e. present in TYPES global)
365     std::vector<bool> mIsRSTAllowed;
366 
367     /* The collection of permutations for this specification, i.e. this class instantianted
368      * for specific values of #1, #2, etc.  Owned.
369      */
370     std::vector<FunctionPermutation*> mPermutations;
371 
372     // The following fields may contain placeholders that will be replaced using the mReplaceables.
373 
374     /* As of this writing, convert_... is the only function with #1 in its name.
375      * The related Function object contains the name of the function without #n, e.g. convert.
376      * This is the name with the #, e.g. convert_#1_#2
377      */
378     std::string mUnexpandedName;
379     ParameterEntry* mReturn;                   // The return type. The name should be empty.  Owned.
380     std::vector<ParameterEntry*> mParameters;  // The parameters.  Owned.
381     std::vector<std::string> mInline;          // The inline code to be included in the header
382 
383     /* Substitute the placeholders in the strings (e.g. #1, #2, ...) by the
384      * corresponding entries in mReplaceables.  Substitute placeholders for RS
385      * types (#RST_1, #RST_2, ...) by the RS Data type strings (UNSIGNED_8,
386      * FLOAT_32 etc.) of the corresponding types in mReplaceables.
387      * indexOfReplaceable1 selects with value to use for #1, same for 2, 3, and
388      * 4.
389      */
390     std::string expandString(std::string s, int indexOfReplaceable[MAX_REPLACEABLES]) const;
391     void expandStringVector(const std::vector<std::string>& in,
392                             int replacementIndexes[MAX_REPLACEABLES],
393                             std::vector<std::string>* out) const;
394 
395     // Helper function used by expandString to perform #RST_* substitution
396     std::string expandRSTypeInString(const std::string &s,
397                                      const std::string &pattern,
398                                      const std::string &cTypeStr) const;
399 
400     // Fill the mPermutations field.
401     void createPermutations(Function* function, Scanner* scanner);
402 
403 public:
FunctionSpecification(Function * function)404     FunctionSpecification(Function* function) : mFunction(function), mInternal(false),
405         mIntrinsic(false), mReturn(nullptr) {}
406     ~FunctionSpecification();
407 
getFunction()408     Function* getFunction() const { return mFunction; }
isInternal()409     bool isInternal() const { return mInternal; }
isIntrinsic()410     bool isIntrinsic() const { return mIntrinsic; }
getAttribute()411     std::string getAttribute() const { return mAttribute; }
getTest()412     std::string getTest() const { return mTest; }
getPrecisionLimit()413     std::string getPrecisionLimit() const { return mPrecisionLimit; }
414 
getPermutations()415     const std::vector<FunctionPermutation*>& getPermutations() const { return mPermutations; }
416 
417     std::string getName(int replacementIndexes[MAX_REPLACEABLES]) const;
418     void getReturn(int replacementIndexes[MAX_REPLACEABLES], std::string* retType,
419                    int* lineNumber) const;
getNumberOfParams()420     size_t getNumberOfParams() const { return mParameters.size(); }
421     void getParam(size_t index, int replacementIndexes[MAX_REPLACEABLES], std::string* type,
422                   std::string* name, std::string* testOption, int* lineNumber) const;
423     void getInlines(int replacementIndexes[MAX_REPLACEABLES],
424                     std::vector<std::string>* inlines) const;
425 
426     // Parse the "test:" line.
427     void parseTest(Scanner* scanner);
428 
429     // Return true if we need to generate tests for this function.
430     bool hasTests(unsigned int versionOfTestFiles) const;
431 
hasInline()432     bool hasInline() const { return mInline.size() > 0; }
433 
434     /* Return true if this function can be overloaded.  This is added by default to all
435      * specifications, so except for the very few exceptions that start the attributes
436      * with an '=' to avoid this, we'll return true.
437      */
isOverloadable()438     bool isOverloadable() const {
439         return mAttribute.empty() || mAttribute[0] != '=';
440     }
441 
442     /* Check if RST_i is present in 's' and report an error if 'allow' is false
443      * or the i-th replacement list is not a valid candidate for RST_i
444      * replacement
445      */
446     void checkRSTPatternValidity(const std::string &s, bool allow, Scanner *scanner);
447 
448     // Parse a function specification and add it to specFile.
449     static void scanFunctionSpecification(Scanner* scanner, SpecFile* specFile, unsigned int maxApiLevel);
450 };
451 
452 /* A concrete version of a function specification, where all placeholders have been replaced by
453  * actual values.
454  */
455 class FunctionPermutation {
456 private:
457     // These are the expanded version of those found on FunctionSpecification
458     std::string mName;
459     std::string mNameTrunk;  // The name without any expansion, e.g. convert
460     std::string mTest;       // How to test.  One of "scalar", "vector", "noverify", "limited", and
461                              // "none".
462     std::string mPrecisionLimit;  // Maximum precision required when checking output of this
463                                   // function.
464 
465     // The parameters of the function.  This does not include the return type.  Owned.
466     std::vector<ParameterDefinition*> mParams;
467     // The return type.  nullptr if a void function.  Owned.
468     ParameterDefinition* mReturn;
469 
470     // The number of input and output parameters.  mOutputCount counts the return type.
471     int mInputCount;
472     int mOutputCount;
473 
474     // Whether one of the output parameters is a float.
475     bool mHasFloatAnswers;
476 
477     // The inline code that implements this function.  Will be empty if not an inline.
478     std::vector<std::string> mInline;
479 
480 public:
481     FunctionPermutation(Function* function, FunctionSpecification* specification,
482                         int replacementIndexes[MAX_REPLACEABLES], Scanner* scanner);
483     ~FunctionPermutation();
484 
getName()485     std::string getName() const { return mName; }
getNameTrunk()486     std::string getNameTrunk() const { return mNameTrunk; }
getTest()487     std::string getTest() const { return mTest; }
getPrecisionLimit()488     std::string getPrecisionLimit() const { return mPrecisionLimit; }
489 
getInline()490     const std::vector<std::string>& getInline() const { return mInline; }
getReturn()491     const ParameterDefinition* getReturn() const { return mReturn; }
getInputCount()492     int getInputCount() const { return mInputCount; }
getOutputCount()493     int getOutputCount() const { return mOutputCount; }
hasFloatAnswers()494     bool hasFloatAnswers() const { return mHasFloatAnswers; }
495 
getParams()496     const std::vector<ParameterDefinition*> getParams() const { return mParams; }
497 };
498 
499 // An entire spec file and the methods to process it.
500 class SpecFile {
501 private:
502     std::string mSpecFileName;
503     std::string mHeaderFileName;
504     std::string mDetailedDocumentationUrl;
505     std::string mBriefDescription;
506     std::vector<std::string> mFullDescription;
507     // Text to insert as-is in the generated header.
508     std::vector<std::string> mVerbatimInclude;
509 
510     /* The constants, types, and functions specifications declared in this
511      *  file, in the order they are found in the file.  This matters for
512      * header generation, as some types and inline functions depend
513      * on each other.  Pointers not owned.
514      */
515     std::list<ConstantSpecification*> mConstantSpecificationsList;
516     std::list<TypeSpecification*> mTypeSpecificationsList;
517     std::list<FunctionSpecification*> mFunctionSpecificationsList;
518 
519     /* The constants, types, and functions that are documented in this file.
520      * In very rare cases, specifications for an API are split across multiple
521      * files, e.g. currently for ClearObject().  The documentation for
522      * that function must be found in the first spec file encountered, so the
523      * order of the files on the command line matters.
524      */
525     std::map<std::string, Constant*> mDocumentedConstants;
526     std::map<std::string, Type*> mDocumentedTypes;
527     std::map<std::string, Function*> mDocumentedFunctions;
528 
529 public:
530     explicit SpecFile(const std::string& specFileName);
531 
getSpecFileName()532     std::string getSpecFileName() const { return mSpecFileName; }
getHeaderFileName()533     std::string getHeaderFileName() const { return mHeaderFileName; }
getDetailedDocumentationUrl()534     std::string getDetailedDocumentationUrl() const { return mDetailedDocumentationUrl; }
getBriefDescription()535     const std::string getBriefDescription() const { return mBriefDescription; }
getFullDescription()536     const std::vector<std::string>& getFullDescription() const { return mFullDescription; }
getVerbatimInclude()537     const std::vector<std::string>& getVerbatimInclude() const { return mVerbatimInclude; }
538 
getConstantSpecifications()539     const std::list<ConstantSpecification*>& getConstantSpecifications() const {
540         return mConstantSpecificationsList;
541     }
getTypeSpecifications()542     const std::list<TypeSpecification*>& getTypeSpecifications() const {
543         return mTypeSpecificationsList;
544     }
getFunctionSpecifications()545     const std::list<FunctionSpecification*>& getFunctionSpecifications() const {
546         return mFunctionSpecificationsList;
547     }
getDocumentedConstants()548     const std::map<std::string, Constant*>& getDocumentedConstants() const {
549         return mDocumentedConstants;
550     }
getDocumentedTypes()551     const std::map<std::string, Type*>& getDocumentedTypes() const { return mDocumentedTypes; }
getDocumentedFunctions()552     const std::map<std::string, Function*>& getDocumentedFunctions() const {
553         return mDocumentedFunctions;
554     }
555 
hasSpecifications()556     bool hasSpecifications() const {
557         return !mDocumentedConstants.empty() || !mDocumentedTypes.empty() ||
558                !mDocumentedFunctions.empty();
559     }
560 
561     bool readSpecFile(unsigned int maxApiLevel);
562 
563     /* These are called by the parser to keep track of the specifications defined in this file.
564      * hasDocumentation is true if this specification containes the documentation.
565      */
566     void addConstantSpecification(ConstantSpecification* spec, bool hasDocumentation);
567     void addTypeSpecification(TypeSpecification* spec, bool hasDocumentation);
568     void addFunctionSpecification(FunctionSpecification* spec, bool hasDocumentation);
569 };
570 
571 // The collection of all the spec files.
572 class SystemSpecification {
573 private:
574     std::vector<SpecFile*> mSpecFiles;
575 
576     /* Entries in the table of contents.  We accumulate them in a map to sort them.
577      * Pointers are owned.
578      */
579     std::map<std::string, Constant*> mConstants;
580     std::map<std::string, Type*> mTypes;
581     std::map<std::string, Function*> mFunctions;
582 
583 public:
584     ~SystemSpecification();
585 
586     /* These are called the parser to create unique instances per name.  Set *created to true
587      * if the named specification did not already exist.
588      */
589     Constant* findOrCreateConstant(const std::string& name, bool* created);
590     Type* findOrCreateType(const std::string& name, bool* created);
591     Function* findOrCreateFunction(const std::string& name, bool* created);
592 
593     /* Parse the spec file and create the object hierarchy, adding a pointer to mSpecFiles.
594      * We won't include information passed the specified level.
595      */
596     bool readSpecFile(const std::string& fileName, unsigned int maxApiLevel);
597     // Generate all the files.
598     bool generateFiles(bool forVerification, unsigned int maxApiLevel) const;
599 
getSpecFiles()600     const std::vector<SpecFile*>& getSpecFiles() const { return mSpecFiles; }
getConstants()601     const std::map<std::string, Constant*>& getConstants() const { return mConstants; }
getTypes()602     const std::map<std::string, Type*>& getTypes() const { return mTypes; }
getFunctions()603     const std::map<std::string, Function*>& getFunctions() const { return mFunctions; }
604 
605     // Returns "<a href='...'> for the named specification, or empty if not found.
606     std::string getHtmlAnchor(const std::string& name) const;
607 
608     // Returns the maximum API level specified in any spec file.
609     unsigned int getMaximumApiLevel();
610 };
611 
612 // Singleton that represents the collection of all the specs we're processing.
613 extern SystemSpecification systemSpecification;
614 
615 // Table of equivalences of numerical types.
616 extern const NumericalType TYPES[];
617 extern const int NUM_TYPES;
618 
619 /* Given a renderscript type (string) calculate the vector size and base type. If the type
620  * is not a vector the vector size is 1 and baseType is just the type itself.
621  */
622 void getVectorSizeAndBaseType(const std::string& type, std::string& vectorSize,
623                               std::string& baseType);
624 
625 #endif  // ANDROID_RS_API_GENERATOR_SPECIFICATION_H
626