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