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