Allow specifications for a function to be found in more than one spec file.
To enable the upcoming change that has rsClearOjbect, rsIsObject,
and rsSetObject in two spec files (core & graphics), we need to change
the generator.
Change-Id: I87925dcbe199f11c217907343455b2e8a7a76ed4
diff --git a/api/GenerateHeaderFiles.cpp b/api/GenerateHeaderFiles.cpp
index 7475d6b..eb4c9dd 100644
--- a/api/GenerateHeaderFiles.cpp
+++ b/api/GenerateHeaderFiles.cpp
@@ -95,21 +95,20 @@
}
}
-static void writeConstant(GeneratedFile* file, const Constant& constant) {
+static void writeConstantComment(GeneratedFile* file, const Constant& constant) {
const string name = constant.getName();
writeComment(file, name, constant.getSummary(), constant.getDescription(), true);
-
- for (auto spec : constant.getSpecifications()) {
- VersionInfo info = spec->getVersionInfo();
- writeVersionGuardStart(file, info);
- *file << "#define " << name << " " << spec->getValue() << "\n";
- writeVersionGuardEnd(file, info);
- }
- *file << "\n";
}
-static void writeTypeSpecification(GeneratedFile* file, const string& typeName,
- const TypeSpecification& spec) {
+static void writeConstantSpecification(GeneratedFile* file, const ConstantSpecification& spec) {
+ VersionInfo info = spec.getVersionInfo();
+ writeVersionGuardStart(file, info);
+ *file << "#define " << spec.getConstant()->getName() << " " << spec.getValue() << "\n\n";
+ writeVersionGuardEnd(file, info);
+}
+
+static void writeTypeSpecification(GeneratedFile* file, const TypeSpecification& spec) {
+ const string& typeName = spec.getType()->getName();
const VersionInfo info = spec.getVersionInfo();
writeVersionGuardStart(file, info);
switch (spec.getKind()) {
@@ -170,14 +169,9 @@
*file << "\n";
}
-static void writeType(GeneratedFile* file, const Type& type) {
+static void writeTypeComment(GeneratedFile* file, const Type& type) {
const string name = type.getName();
writeComment(file, name, type.getSummary(), type.getDescription(), true);
-
- for (auto spec : type.getSpecifications()) {
- writeTypeSpecification(file, name, *spec);
- }
- *file << "\n";
}
static void writeFunctionPermutation(GeneratedFile* file, const FunctionSpecification& spec,
@@ -272,7 +266,7 @@
*file << "\n";
}
-static void writeFunction(GeneratedFile* file, const Function& function) {
+static void writeFunctionComment(GeneratedFile* file, const Function& function) {
// Write the generic documentation.
writeComment(file, function.getName(), function.getSummary(), function.getDescription(), false);
@@ -295,12 +289,12 @@
}
*file << " */\n";
+}
+static void writeFunctionSpecification(GeneratedFile* file, const FunctionSpecification& spec) {
// Write all the variants.
- for (auto spec : function.getSpecifications()) {
- for (auto permutation : spec->getPermutations()) {
- writeFunctionPermutation(file, *spec, *permutation);
- }
+ for (auto permutation : spec.getPermutations()) {
+ writeFunctionPermutation(file, spec, *permutation);
}
}
@@ -334,14 +328,33 @@
/* Write the constants, types, and functions in the same order as
* encountered in the spec file.
*/
- for (auto iter : specFile.getConstantsList()) {
- writeConstant(&file, *iter);
+ set<Constant*> documentedConstants;
+ for (auto spec : specFile.getConstantSpecifications()) {
+ Constant* constant = spec->getConstant();
+ if (documentedConstants.find(constant) == documentedConstants.end()) {
+ documentedConstants.insert(constant);
+ writeConstantComment(&file, *constant);
+ }
+ writeConstantSpecification(&file, *spec);
}
- for (auto iter : specFile.getTypesList()) {
- writeType(&file, *iter);
+ set<Type*> documentedTypes;
+ for (auto spec : specFile.getTypeSpecifications()) {
+ Type* type = spec->getType();
+ if (documentedTypes.find(type) == documentedTypes.end()) {
+ documentedTypes.insert(type);
+ writeTypeComment(&file, *type);
+ }
+ writeTypeSpecification(&file, *spec);
}
- for (auto iter : specFile.getFunctionsList()) {
- writeFunction(&file, *iter);
+
+ set<Function*> documentedFunctions;
+ for (auto spec : specFile.getFunctionSpecifications()) {
+ Function* function = spec->getFunction();
+ if (documentedFunctions.find(function) == documentedFunctions.end()) {
+ documentedFunctions.insert(function);
+ writeFunctionComment(&file, *function);
+ }
+ writeFunctionSpecification(&file, *spec);
}
file << "#endif // " << guard << "\n";
diff --git a/api/GenerateHtmlDocumentation.cpp b/api/GenerateHtmlDocumentation.cpp
index 359d785..a9e4d43 100644
--- a/api/GenerateHtmlDocumentation.cpp
+++ b/api/GenerateHtmlDocumentation.cpp
@@ -415,10 +415,8 @@
// Write the summary tables.
// file << "<h2>Summary</h2>\n";
- const auto& constants = specFile.getConstantsMap();
- const auto& types = specFile.getTypesMap();
- const auto& functions = specFile.getFunctionsMap();
- writeSummaryTables(file, constants, types, functions, false);
+ writeSummaryTables(file, specFile.getDocumentedConstants(), specFile.getDocumentedTypes(),
+ specFile.getDocumentedFunctions(), false);
return success;
}
@@ -620,9 +618,9 @@
// Write the summary tables.
file << "<h2>Summary</h2>\n";
- const auto& constants = specFile.getConstantsMap();
- const auto& types = specFile.getTypesMap();
- const auto& functions = specFile.getFunctionsMap();
+ const auto& constants = specFile.getDocumentedConstants();
+ const auto& types = specFile.getDocumentedTypes();
+ const auto& functions = specFile.getDocumentedFunctions();
writeSummaryTables(&file, constants, types, functions, false);
// Write the full details of each constant, type, and function.
diff --git a/api/GenerateTestFiles.cpp b/api/GenerateTestFiles.cpp
index f70c444..529bd2a 100644
--- a/api/GenerateTestFiles.cpp
+++ b/api/GenerateTestFiles.cpp
@@ -1030,11 +1030,9 @@
bool GenerateTestFiles(const string& directory, int versionOfTestFiles) {
bool success = true;
- for (auto specFile : systemSpecification.getSpecFiles()) {
- for (auto f : specFile->getFunctionsMap()) {
- if (!writeTestFilesForFunction(*f.second, directory, versionOfTestFiles)) {
- success = false;
- }
+ for (auto f : systemSpecification.getFunctions()) {
+ if (!writeTestFilesForFunction(*f.second, directory, versionOfTestFiles)) {
+ success = false;
}
}
return success;
diff --git a/api/Specification.cpp b/api/Specification.cpp
index a09495e..92d14d6 100644
--- a/api/Specification.cpp
+++ b/api/Specification.cpp
@@ -214,12 +214,11 @@
}
}
-Definition::Definition(const std::string& name, SpecFile* specFile) : mName(name), mHidden(false) {
- mSpecFileName = specFile->getSpecFileName();
- mUrl = specFile->getDetailedDocumentationUrl() + "#android_rs:" + name;
+Definition::Definition(const std::string& name) : mName(name), mHidden(false) {
}
-void Definition::scanDocumentationTags(Scanner* scanner, bool firstOccurence) {
+void Definition::scanDocumentationTags(Scanner* scanner, bool firstOccurence,
+ const SpecFile* specFile) {
if (scanner->findOptionalTag("hidden:")) {
scanner->checkNoValue();
mHidden = true;
@@ -234,6 +233,7 @@
mDescription.push_back(scanner->getValue());
}
}
+ mUrl = specFile->getDetailedDocumentationUrl() + "#android_rs:" + mName;
} else if (scanner->findOptionalTag("summary:")) {
scanner->error() << "Only the first specification should have a summary.\n";
}
@@ -251,7 +251,7 @@
}
}
-Function::Function(const string& name, SpecFile* specFile) : Definition(name, specFile) {
+Function::Function(const string& name) : Definition(name) {
mCapitalizedName = capitalize(mName);
}
@@ -303,16 +303,16 @@
string name = scanner->getValue();
bool created = false;
- Constant* constant = specFile->findOrCreateConstant(name, &created);
-
- ConstantSpecification* spec = new ConstantSpecification();
+ Constant* constant = systemSpecification.findOrCreateConstant(name, &created);
+ ConstantSpecification* spec = new ConstantSpecification(constant);
constant->addSpecification(spec);
+ specFile->addConstantSpecification(spec, created);
spec->scanVersionInfo(scanner);
if (scanner->findTag("value:")) {
spec->mValue = scanner->getValue();
}
- constant->scanDocumentationTags(scanner, created);
+ constant->scanDocumentationTags(scanner, created, specFile);
scanner->findTag("end:");
}
@@ -321,10 +321,10 @@
string name = scanner->getValue();
bool created = false;
- Type* type = specFile->findOrCreateType(name, &created);
-
- TypeSpecification* spec = new TypeSpecification();
+ Type* type = systemSpecification.findOrCreateType(name, &created);
+ TypeSpecification* spec = new TypeSpecification(type);
type->addSpecification(spec);
+ specFile->addTypeSpecification(spec, created);
spec->scanVersionInfo(scanner);
if (scanner->findOptionalTag("simple:")) {
@@ -356,7 +356,7 @@
spec->mValueComments.push_back(comment);
}
}
- type->scanDocumentationTags(scanner, created);
+ type->scanDocumentationTags(scanner, created, specFile);
scanner->findTag("end:");
}
@@ -497,10 +497,10 @@
}
bool created = false;
- Function* function = specFile->findOrCreateFunction(name, &created);
-
- FunctionSpecification* spec = new FunctionSpecification();
+ Function* function = systemSpecification.findOrCreateFunction(name, &created);
+ FunctionSpecification* spec = new FunctionSpecification(function);
function->addSpecification(spec);
+ specFile->addFunctionSpecification(spec, created);
spec->mUnexpandedName = scanner->getValue();
spec->mTest = "scalar"; // default
@@ -542,7 +542,7 @@
spec->mParameters.push_back(p);
}
- function->scanDocumentationTags(scanner, created);
+ function->scanDocumentationTags(scanner, created, specFile);
if (scanner->findOptionalTag("inline:")) {
scanner->checkNoValue();
@@ -633,15 +633,27 @@
mDetailedDocumentationUrl += core + ".html";
}
-SpecFile::~SpecFile() {
- for (auto i : mConstantsList) {
- delete i;
+void SpecFile::addConstantSpecification(ConstantSpecification* spec, bool hasDocumentation) {
+ mConstantSpecificationsList.push_back(spec);
+ if (hasDocumentation) {
+ Constant* constant = spec->getConstant();
+ mDocumentedConstants.insert(pair<string, Constant*>(constant->getName(), constant));
}
- for (auto i : mTypesList) {
- delete i;
+}
+
+void SpecFile::addTypeSpecification(TypeSpecification* spec, bool hasDocumentation) {
+ mTypeSpecificationsList.push_back(spec);
+ if (hasDocumentation) {
+ Type* type = spec->getType();
+ mDocumentedTypes.insert(pair<string, Type*>(type->getName(), type));
}
- for (auto i : mFunctionsList) {
- delete i;
+}
+
+void SpecFile::addFunctionSpecification(FunctionSpecification* spec, bool hasDocumentation) {
+ mFunctionSpecificationsList.push_back(spec);
+ if (hasDocumentation) {
+ Function* function = spec->getFunction();
+ mDocumentedFunctions.insert(pair<string, Function*>(function->getName(), function));
}
}
@@ -698,52 +710,45 @@
return scanner.getErrorCount() == 0;
}
+SystemSpecification::~SystemSpecification() {
+ for (auto i : mConstants) {
+ delete i.second;
+ }
+ for (auto i : mTypes) {
+ delete i.second;
+ }
+ for (auto i : mFunctions) {
+ delete i.second;
+ }
+ for (auto i : mSpecFiles) {
+ delete i;
+ }
+}
+
// Returns the named entry in the map. Creates it if it's not there.
template <class T>
-T* findOrCreate(const string& name, list<T*>* list, map<string, T*>* map, bool* created,
- SpecFile* specFile) {
+T* findOrCreate(const string& name, map<string, T*>* map, bool* created) {
auto iter = map->find(name);
if (iter != map->end()) {
*created = false;
return iter->second;
}
*created = true;
- T* f = new T(name, specFile);
+ T* f = new T(name);
map->insert(pair<string, T*>(name, f));
- list->push_back(f);
return f;
}
-Constant* SpecFile::findOrCreateConstant(const string& name, bool* created) {
- return findOrCreate<Constant>(name, &mConstantsList, &mConstantsMap, created, this);
+Constant* SystemSpecification::findOrCreateConstant(const string& name, bool* created) {
+ return findOrCreate<Constant>(name, &mConstants, created);
}
-Type* SpecFile::findOrCreateType(const string& name, bool* created) {
- return findOrCreate<Type>(name, &mTypesList, &mTypesMap, created, this);
+Type* SystemSpecification::findOrCreateType(const string& name, bool* created) {
+ return findOrCreate<Type>(name, &mTypes, created);
}
-Function* SpecFile::findOrCreateFunction(const string& name, bool* created) {
- return findOrCreate<Function>(name, &mFunctionsList, &mFunctionsMap, created, this);
-}
-
-SystemSpecification::~SystemSpecification() {
- for (auto i : mSpecFiles) {
- delete i;
- }
-}
-
-template <class T>
-static bool addDefinitionToMap(map<string, T*>* map, T* object) {
- const string& name = object->getName();
- auto i = map->find(name);
- if (i != map->end()) {
- T* existing = i->second;
- cerr << object->getSpecFileName() << ": Error. " << name << " has already been defined in "
- << existing->getSpecFileName() << "\n";
- return false;
- }
- (*map)[name] = object;
- return true;
+Function* SystemSpecification::findOrCreateFunction(const string& name, bool* created) {
+ return findOrCreate<Function>(name, &mFunctions, created);
}
bool SystemSpecification::readSpecFile(const string& fileName) {
@@ -753,26 +758,7 @@
return false;
}
mSpecFiles.push_back(spec);
-
- // Store links to the definitions in a global table.
- bool success = true;
- for (auto i : spec->getConstantsMap()) {
- if (!addDefinitionToMap(&mConstants, i.second)) {
- success = false;
- }
- }
- for (auto i : spec->getTypesMap()) {
- if (!addDefinitionToMap(&mTypes, i.second)) {
- success = false;
- }
- }
- for (auto i : spec->getFunctionsMap()) {
- if (!addDefinitionToMap(&mFunctions, i.second)) {
- success = false;
- }
- }
-
- return success;
+ return true;
}
bool SystemSpecification::generateFiles(int versionOfTestFiles) const {
diff --git a/api/Specification.h b/api/Specification.h
index 6146665..f5211f0 100644
--- a/api/Specification.h
+++ b/api/Specification.h
@@ -137,25 +137,21 @@
class Definition {
protected:
std::string mName;
- std::string mSpecFileName;
-
bool mHidden; // True if it should not be documented
std::string mSummary; // A one-line description
std::vector<std::string> mDescription; // The comments to be included in the header
std::string mUrl; // The URL of the detailed documentation
public:
- Definition(const std::string& name, SpecFile* specFile);
+ Definition(const std::string& name);
std::string getName() const { return mName; }
- std::string getSpecFileName() const { return mSpecFileName; }
-
bool hidden() const { return mHidden; }
std::string getSummary() const { return mSummary; }
const std::vector<std::string>& getDescription() const { return mDescription; }
std::string getUrl() const { return mUrl; }
- void scanDocumentationTags(Scanner* scanner, bool firstOccurence);
+ void scanDocumentationTags(Scanner* scanner, bool firstOccurence, const SpecFile* specFile);
};
/* Represents a constant, like M_PI. This is a grouping of the version specific specifications.
@@ -166,7 +162,7 @@
std::vector<ConstantSpecification*> mSpecifications; // Owned
public:
- Constant(const std::string& name, SpecFile* specFile) : Definition(name, specFile) {}
+ Constant(const std::string& name) : Definition(name) {}
~Constant();
const std::vector<ConstantSpecification*> getSpecifications() const { return mSpecifications; }
@@ -182,7 +178,7 @@
std::vector<TypeSpecification*> mSpecifications; // Owned
public:
- Type(const std::string& name, SpecFile* specFile) : Definition(name, specFile) {}
+ Type(const std::string& name) : Definition(name) {}
~Type();
const std::vector<TypeSpecification*> getSpecifications() const { return mSpecifications; }
@@ -205,7 +201,7 @@
std::vector<FunctionSpecification*> mSpecifications; // Owned
public:
- Function(const std::string& name, SpecFile* specFile);
+ Function(const std::string& name);
~Function();
std::string getCapitalizedName() const { return mCapitalizedName; }
@@ -239,8 +235,13 @@
*/
class ConstantSpecification : public Specification {
private:
+ Constant* mConstant; // Not owned
+
std::string mValue; // E.g. "3.1415"
public:
+ ConstantSpecification(Constant* constant) : mConstant(constant) {}
+
+ Constant* getConstant() const { return mConstant; }
std::string getValue() const { return mValue; }
// Parse a constant specification and add it to specFile.
@@ -258,6 +259,8 @@
*/
class TypeSpecification : public Specification {
private:
+ Type* mType; // Not owned
+
TypeKind mKind; // The kind of type specification
// If mKind is SIMPLE:
@@ -274,6 +277,9 @@
std::vector<std::string> mValues; // One entry per enum value
std::vector<std::string> mValueComments; // One entry per enum value
public:
+ TypeSpecification(Type* type) : mType(type) {}
+
+ Type* getType() const { return mType; }
TypeKind getKind() const { return mKind; }
std::string getSimpleType() const { return mSimpleType; }
std::string getStructName() const { return mStructName; }
@@ -298,6 +304,8 @@
*/
class FunctionSpecification : public Specification {
private:
+ Function* mFunction; // Not owned
+
/* How to test. One of:
* "scalar": Generate test code that checks entries of each vector indepently. E.g. for
* sin(float3), the test code will call the CoreMathVerfier.computeSin 3 times.
@@ -349,9 +357,10 @@
void createPermutations(Function* function, Scanner* scanner);
public:
- FunctionSpecification() : mReturn(nullptr) {}
+ FunctionSpecification(Function* function) : mFunction(function), mReturn(nullptr) {}
~FunctionSpecification();
+ Function* getFunction() { return mFunction; }
std::string getAttribute() const { return mAttribute; }
std::string getTest() const { return mTest; }
std::string getPrecisionLimit() const { return mPrecisionLimit; }
@@ -437,25 +446,27 @@
// Text to insert as-is in the generated header.
std::vector<std::string> mVerbatimInclude;
- /* The constants, types, and functions declared in this file,
- * in the order they are found in the file. This matters for
+ /* The constants, types, and functions specifications declared in this
+ * file, in the order they are found in the file. This matters for
* header generation, as some types and inline functions depend
- * on each other.
- *
- * Pointers are owned by this list.
+ * on each other. Pointers not owned.
*/
- std::list<Constant*> mConstantsList;
- std::list<Type*> mTypesList;
- std::list<Function*> mFunctionsList;
+ std::list<ConstantSpecification*> mConstantSpecificationsList;
+ std::list<TypeSpecification*> mTypeSpecificationsList;
+ std::list<FunctionSpecification*> mFunctionSpecificationsList;
- // Quick way to find entries in the previous lists. Pointers not owned.
- std::map<std::string, Constant*> mConstantsMap;
- std::map<std::string, Type*> mTypesMap;
- std::map<std::string, Function*> mFunctionsMap;
+ /* The constants, types, and functions that are documented in this file.
+ * In very rare cases, specifications for an API are split across multiple
+ * files, e.g. currently for ClearObject(). The documentation for
+ * that function must be found in the first spec file encountered, so the
+ * order of the files on the command line matters.
+ */
+ std::map<std::string, Constant*> mDocumentedConstants;
+ std::map<std::string, Type*> mDocumentedTypes;
+ std::map<std::string, Function*> mDocumentedFunctions;
public:
explicit SpecFile(const std::string& specFileName);
- ~SpecFile();
std::string getSpecFileName() const { return mSpecFileName; }
std::string getHeaderFileName() const { return mHeaderFileName; }
@@ -464,19 +475,31 @@
const std::vector<std::string>& getFullDescription() const { return mFullDescription; }
const std::vector<std::string>& getVerbatimInclude() const { return mVerbatimInclude; }
- const std::list<Constant*>& getConstantsList() const { return mConstantsList; }
- const std::list<Type*>& getTypesList() const { return mTypesList; }
- const std::list<Function*>& getFunctionsList() const { return mFunctionsList; }
-
- const std::map<std::string, Constant*>& getConstantsMap() const { return mConstantsMap; }
- const std::map<std::string, Type*>& getTypesMap() const { return mTypesMap; }
- const std::map<std::string, Function*>& getFunctionsMap() const { return mFunctionsMap; }
+ const std::list<ConstantSpecification*>& getConstantSpecifications() const {
+ return mConstantSpecificationsList;
+ }
+ const std::list<TypeSpecification*>& getTypeSpecifications() const {
+ return mTypeSpecificationsList;
+ }
+ const std::list<FunctionSpecification*>& getFunctionSpecifications() const {
+ return mFunctionSpecificationsList;
+ }
+ const std::map<std::string, Constant*>& getDocumentedConstants() const {
+ return mDocumentedConstants;
+ }
+ const std::map<std::string, Type*>& getDocumentedTypes() const { return mDocumentedTypes; }
+ const std::map<std::string, Function*>& getDocumentedFunctions() const {
+ return mDocumentedFunctions;
+ }
bool readSpecFile();
- Constant* findOrCreateConstant(const std::string& name, bool* created);
- Type* findOrCreateType(const std::string& name, bool* created);
- Function* findOrCreateFunction(const std::string& name, bool* created);
+ /* These are called by the parser to keep track of the specifications defined in this file.
+ * hasDocumentation is true if this specification containes the documentation.
+ */
+ void addConstantSpecification(ConstantSpecification* spec, bool hasDocumentation);
+ void addTypeSpecification(TypeSpecification* spec, bool hasDocumentation);
+ void addFunctionSpecification(FunctionSpecification* spec, bool hasDocumentation);
};
// The collection of all the spec files.
@@ -485,7 +508,7 @@
std::vector<SpecFile*> mSpecFiles;
/* Entries in the table of contents. We accumulate them in a map to sort them.
- * Pointers are not owned, they belong to the SpecFile object.
+ * Pointers are owned.
*/
std::map<std::string, Constant*> mConstants;
std::map<std::string, Type*> mTypes;
@@ -493,6 +516,14 @@
public:
~SystemSpecification();
+
+ /* These are called the parser to create unique instances per name. Set *created to true
+ * if the named specification did not already exist.
+ */
+ Constant* findOrCreateConstant(const std::string& name, bool* created);
+ Type* findOrCreateType(const std::string& name, bool* created);
+ Function* findOrCreateFunction(const std::string& name, bool* created);
+
// Parse the spec file and create the object hierarchy, adding a pointer to mSpecFiles.
bool readSpecFile(const std::string& fileName);
// Generate all the files.