aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/bookmaker/includeParser.cpp
diff options
context:
space:
mode:
authorGravatar Cary Clark <caryclark@skia.org>2018-04-16 08:37:38 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-04-16 16:26:20 +0000
commit2d4bf5f288d91f8d2371c7a970bdfa70dacdd78a (patch)
tree1aa90b6825682da0963bb48c9325d6912e3923c0 /tools/bookmaker/includeParser.cpp
parentffbe93296838c3a93a87261cae7f7229b56f1f8a (diff)
document SkColor.h
SkColor.h uses #define liberally, and has many global symbols, two things bookmaker hasn't seen in other includes. Revised .h -> .bmh converter to work with SkColor.h as well as updating how .bmh indices are built. Generated SkColor_Reference.bmh for globals, and SkColor4f_Reference.bmh for class. Other than the existing comments, this doesn't update the documentation or add new examples. Docs-Preview: https://skia.org/?cl=118985 TBR=caryclark@google.com Bug: skia:6898 Change-Id: I5978257ee0e51319823efbe8dfc467a08c99ffe0 Reviewed-on: https://skia-review.googlesource.com/118985 Commit-Queue: Cary Clark <caryclark@skia.org> Reviewed-by: Cary Clark <caryclark@skia.org>
Diffstat (limited to 'tools/bookmaker/includeParser.cpp')
-rw-r--r--tools/bookmaker/includeParser.cpp713
1 files changed, 457 insertions, 256 deletions
diff --git a/tools/bookmaker/includeParser.cpp b/tools/bookmaker/includeParser.cpp
index 033599977c..982f7b3a78 100644
--- a/tools/bookmaker/includeParser.cpp
+++ b/tools/bookmaker/includeParser.cpp
@@ -161,6 +161,10 @@ bool IncludeParser::checkForWord() {
switch (keyWord) {
// these do not link to other # directives
case KeyWord::kDefine:
+ if (!fInBrace) {
+ SkASSERT(!fInDefine);
+ fInDefine = true;
+ }
case KeyWord::kInclude:
case KeyWord::kError:
break;
@@ -259,7 +263,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
const Definition* def = root->find(fullName, RootDefinition::AllowParens::kYes);
switch (token.fMarkType) {
case MarkType::kMethod: {
- if (this->internalName(token)) {
+ if (this->isInternalName(token)) {
continue;
}
if (!def) {
@@ -378,7 +382,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
firstMember.skipWhiteSpace();
SkASSERT('k' == firstMember.peek());
const char* savePos = firstMember.fChar;
- firstMember.skipToNonAlphaNum();
+ firstMember.skipToNonName();
const char* wordEnd = firstMember.fChar;
firstMember.fChar = savePos;
const char* lastUnderscore = nullptr;
@@ -499,7 +503,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
}
IClassDefinition* IncludeParser::defineClass(const Definition& includeDef,
- const string& name) {
+ string name) {
string className;
const Definition* test = fParent;
while (Definition::Type::kFileType != test->fType) {
@@ -539,9 +543,7 @@ void IncludeParser::dumpClassTokens(IClassDefinition& classDef) {
continue;
}
if (MarkType::kMember != token.fMarkType) {
- this->writeString(
- "# ------------------------------------------------------------------------------");
- this->lf(2);
+ this->writeBlockSeparator();
}
switch (token.fMarkType) {
case MarkType::kEnum:
@@ -549,7 +551,7 @@ void IncludeParser::dumpClassTokens(IClassDefinition& classDef) {
this->dumpEnum(token, token.fName);
break;
case MarkType::kMethod:
- this->dumpMethod(token);
+ this->dumpMethod(token, classDef.fName);
break;
case MarkType::kMember:
this->dumpMember(token);
@@ -558,33 +560,7 @@ void IncludeParser::dumpClassTokens(IClassDefinition& classDef) {
default:
SkASSERT(0);
}
- this->lf(2);
- this->writeTag("Example");
- this->lf(1);
- this->writeString("// incomplete");
- this->lf(1);
- this->writeEndTag();
- this->lf(2);
- this->writeTag("SeeAlso");
- this->writeSpace();
- this->writeString("incomplete");
- this->lf(2);
- switch (token.fMarkType) {
- case MarkType::kEnum:
- case MarkType::kEnumClass:
- this->writeEndTag("Enum");
- break;
- case MarkType::kMethod:
- this->writeEndTag("Method");
- break;
- case MarkType::kMember:
- this->writeEndTag("Member");
- continue;
- break;
- default:
- SkASSERT(0);
- }
- this->lf(2);
+ this->dumpCommonTail(token);
}
}
void IncludeParser::dumpComment(const Definition& token) {
@@ -751,10 +727,55 @@ void IncludeParser::dumpComment(const Definition& token) {
}
}
-void IncludeParser::dumpEnum(const Definition& token, const string& name) {
+void IncludeParser::dumpCommonTail(const Definition& token) {
+ this->lf(2);
+ this->writeTag("Example");
+ this->lf(1);
+ this->writeString("// incomplete");
+ this->lf(1);
+ this->writeEndTag();
+ this->lf(2);
+ this->writeTag("SeeAlso");
+ this->writeSpace();
+ this->writeString("incomplete");
+ this->lf(2);
+ this->writeEndTag(BmhParser::kMarkProps[(int) token.fMarkType].fName);
+ this->lf(2);
+}
+
+void IncludeParser::dumpDefine(const Definition& token) {
+ this->writeTag("Define", token.fName);
+ this->lf(2);
+ this->writeTag("Code");
+ this->lfAlways(1);
+ this->writeString("###$");
+ this->lfAlways(1);
+ this->indentToColumn(4);
+ this->writeBlock(token.fTerminator - token.fStart, token.fStart);
+ this->lf(1);
+ this->indentToColumn(0);
+ this->writeString("$$$#");
+
+ this->writeEndTag();
+ this->lf(2);
+ this->dumpComment(token);
+ for (auto& child : token.fTokens) {
+ if (MarkType::kComment == child.fMarkType) {
+ continue;
+ }
+ this->writeTag("Param", child.fName);
+ this->writeSpace();
+ this->writeString("incomplete");
+ this->writeSpace();
+ this->writeString("##");
+ this->lf(1);
+ }
+}
+
+void IncludeParser::dumpEnum(const Definition& token, string name) {
this->writeTag("Enum", name);
this->lf(2);
- this->writeString("#Code");
+ this->writeTag("Code");
this->lfAlways(1);
this->indentToColumn(4);
this->writeString("enum");
@@ -787,7 +808,7 @@ void IncludeParser::dumpEnum(const Definition& token, const string& name) {
// start here;
// get comments before
// or after const values
- this->writeString("#Const");
+ this->writeTag("Const");
this->writeSpace();
this->writeString(child->fName);
TextParser val(child);
@@ -827,35 +848,203 @@ void IncludeParser::dumpEnum(const Definition& token, const string& name) {
this->lf(2);
}
-void IncludeParser::dumpMethod(const Definition& token) {
- this->writeString("#Method");
- this->writeSpace();
- if ("SK_TO_STRING_NONVIRT" == token.fName) {
- this->writeString("void toString(SkString* str) const;");
+bool IncludeParser::dumpGlobals() {
+ size_t lastBSlash = fFileName.rfind('\\');
+ size_t lastSlash = fFileName.rfind('/');
+ size_t lastDotH = fFileName.rfind(".h");
+ SkASSERT(string::npos != lastDotH);
+ if (string::npos != lastBSlash && (string::npos == lastSlash
+ || lastBSlash < lastSlash)) {
+ lastSlash = lastBSlash;
+ } else if (string::npos == lastSlash) {
+ lastSlash = -1;
+ }
+ lastSlash += 1;
+ string globalsName = fFileName.substr(lastSlash, lastDotH - lastSlash);
+ string fileName = globalsName + "_Reference.bmh";
+ fOut = fopen(fileName.c_str(), "wb");
+ if (!fOut) {
+ SkDebugf("could not open output file %s\n", globalsName.c_str());
+ return false;
+ }
+ string prefixName = globalsName.substr(0, 2);
+ string topicName = globalsName.length() > 2 && isupper(globalsName[2]) &&
+ ("Sk" == prefixName || "Gr" == prefixName) ? globalsName.substr(2) : globalsName;
+ this->writeTagNoLF("Topic", topicName);
+ this->writeTag("Alias", topicName + "_Reference");
+ this->lf(2);
+ this->writeTag("Subtopic", "Overview");
+ fIndent += 4;
+ this->writeTag("Subtopic", "Subtopic");
+ fIndent += 4;
+ this->writeTag("Populate");
+ fIndent -= 4;
+ this->writeEndTag();
+ fIndent -= 4;
+ this->writeEndTag();
+ this->lf(2);
+ if (!fIDefineMap.empty()) {
+ this->writeTag("Subtopic", "Define");
+ this->writeTag("Populate");
+ this->writeEndTag();
this->lf(2);
- this->writeEndTag("DefinedBy", "void toString(SkString* str) const;");
+ }
+ if (!fIFunctionMap.empty()) {
+ this->writeTag("Subtopic", "Function");
+ this->writeTag("Populate");
+ this->writeEndTag();
this->lf(2);
- this->writeTag("Private");
- this->lf(1);
- this->writeString("macro expands to: void toString(SkString* str) const;");
+ }
+ if (!fIEnumMap.empty()) {
+ this->writeTag("Subtopic", "Enum");
+ this->writeTag("Populate");
this->writeEndTag();
this->lf(2);
- const char desc[] =
- "Creates string representation. The representation is read by\n"
- "internal debugging tools. The interface and implementation may be\n"
- "suppressed by defining SK_IGNORE_TO_STRING.";
- this->writeBlock(sizeof(desc) - 1, desc);
+ }
+ if (!fITemplateMap.empty()) {
+ this->writeTag("Subtopic", "Template");
+ this->writeTag("Populate");
+ this->writeEndTag();
this->lf(2);
- this->writeTag("Param", "str");
- this->writeSpace(2);
- this->writeString("storage for string representation");
- this->writeSpace();
- this->writeString("##");
+ }
+ if (!fITypedefMap.empty()) {
+ this->writeTag("Subtopic", "Typedef");
+ this->writeTag("Populate");
+ this->writeEndTag();
this->lf(2);
- return;
}
- this->writeBlock(token.length(), token.fStart);
- this->lf(1);
+ if (!fIUnionMap.empty()) {
+ this->writeTag("Subtopic", "Union");
+ this->writeTag("Populate");
+ this->writeEndTag();
+ this->lf(2);
+ }
+ std::map<int, Definition*> sortedDefs;
+ for (const auto& entry : fIDefineMap) {
+ sortedDefs[entry.second->fLineCount] = entry.second;
+ }
+ for (const auto& entry : fIFunctionMap) {
+ sortedDefs[entry.second->fLineCount] = entry.second;
+ }
+ for (const auto& entry : fIEnumMap) {
+ sortedDefs[entry.second->fLineCount] = entry.second;
+ }
+ for (const auto& entry : fITemplateMap) {
+ sortedDefs[entry.second->fLineCount] = entry.second;
+ }
+ for (const auto& entry : fITypedefMap) {
+ sortedDefs[entry.second->fLineCount] = entry.second;
+ }
+ for (const auto& entry : fIUnionMap) {
+ sortedDefs[entry.second->fLineCount] = entry.second;
+ }
+ for (const auto& entry : sortedDefs) {
+ const Definition* def = entry.second;
+ this->writeBlockSeparator();
+ switch (def->fMarkType) {
+ case MarkType::kDefine:
+ this->dumpDefine(*def);
+ break;
+ case MarkType::kMethod:
+ this->dumpMethod(*def, globalsName);
+ break;
+ case MarkType::kEnum:
+ case MarkType::kEnumClass:
+ this->dumpEnum(*def, globalsName);
+ break;
+ case MarkType::kTemplate:
+ SkASSERT(0); // incomplete
+ break;
+ case MarkType::kTypedef: {
+ this->writeTag("Typedef");
+ this->writeSpace();
+ TextParser parser(def);
+ if (!parser.skipExact("typedef")) {
+ return false;
+ }
+ if (!parser.skipSpace()) {
+ return false;
+ }
+ this->writeBlock(parser.fEnd - parser.fChar, parser.fChar);
+ this->lf(2);
+ this->dumpComment(*def);
+ this->writeEndTag(BmhParser::kMarkProps[(int) entry.second->fMarkType].fName);
+ this->lf(2);
+ } continue;
+ case MarkType::kUnion:
+ SkASSERT(0); // incomplete
+ break;
+ default:
+ SkASSERT(0);
+ }
+ this->dumpCommonTail(*def);
+ }
+ this->writeEndTag("Topic", topicName);
+ this->lfAlways(1);
+ fclose(fOut);
+ SkDebugf("wrote %s\n", fileName.c_str());
+ return true;
+}
+
+bool IncludeParser::isClone(const Definition& token) {
+ string name = token.fName;
+ return name[name.length() - 2] == '_' && isdigit(name[name.length() - 1]);
+}
+
+bool IncludeParser::isConstructor(const Definition& token, string className) {
+ string name = token.fName;
+ return 0 == name.find(className) || '~' == name[0];
+}
+
+bool IncludeParser::isInternalName(const Definition& token) {
+ string name = token.fName;
+ // exception for this SkCanvas function .. for now
+ if (0 == token.fName.find("androidFramework_setDeviceClipRestriction")) {
+ return false;
+ }
+ return name.substr(0, 7) == "android"
+ || 0 == token.fName.find("internal_")
+ || 0 == token.fName.find("Internal_")
+ || 0 == token.fName.find("legacy_")
+ || 0 == token.fName.find("temporary_")
+ || 0 == token.fName.find("private_");
+}
+
+bool IncludeParser::isOperator(const Definition& token) {
+ return "operator" == token.fName.substr(0, 8);
+}
+
+void IncludeParser::dumpMethod(const Definition& token, string className) {
+ this->writeTag("Method");
+ this->writeSpace();
+
+ string name = string(token.fStart ? token.fStart : token.fContentStart,
+ token.length());
+ if (this->isOperator(token)) {
+ string spaceConst(" const");
+ size_t constPos = name.rfind(spaceConst);
+ if (name.length() - spaceConst.length() == constPos) {
+ name = name.substr(0, constPos) + "_const";
+ }
+ }
+ this->writeString(name);
+ string inType;
+ if (this->isConstructor(token, className)) {
+ inType = "Constructor";
+ } else if (this->isOperator(token)) {
+ inType = "Operator";
+ } else {
+ inType = "incomplete";
+ }
+ this->writeTag("In", inType);
+ this->writeTag("Line");
+ this->writeSpace(1);
+ this->writeString("#");
+ this->writeSpace(1);
+ this->writeString("incomplete");
+ this->writeSpace(1);
+ this->writeString("##");
+ this->lf(2);
this->dumpComment(token);
}
@@ -871,12 +1060,15 @@ void IncludeParser::dumpMember(const Definition& token) {
lf(2);
}
-bool IncludeParser::dumpTokens(const string& dir) {
+bool IncludeParser::dumpTokens() {
+ if (!this->dumpGlobals()) {
+ return false;
+ }
for (const auto& member : fIClassMap) {
if (string::npos != member.first.find("::")) {
continue;
}
- if (!this->dumpTokens(dir, member.first)) {
+ if (!this->dumpTokens(member.first)) {
return false;
}
}
@@ -884,12 +1076,8 @@ bool IncludeParser::dumpTokens(const string& dir) {
}
// dump equivalent markup
-bool IncludeParser::dumpTokens(const string& dir, const string& skClassName) {
- string fileName = dir;
- if (dir.length() && '/' != dir[dir.length() - 1]) {
- fileName += '/';
- }
- fileName += skClassName + "_Reference.bmh";
+bool IncludeParser::dumpTokens(string skClassName) {
+ string fileName = skClassName + "_Reference.bmh";
fOut = fopen(fileName.c_str(), "wb");
if (!fOut) {
SkDebugf("could not open output file %s\n", fileName.c_str());
@@ -915,160 +1103,82 @@ bool IncludeParser::dumpTokens(const string& dir, const string& skClassName) {
this->lf(1);
}
this->lf(2);
- string className(skClassName.substr(2));
- vector<string> classNames;
- vector<string> constNames;
- vector<string> constructorNames;
- vector<string> memberNames;
- vector<string> operatorNames;
- size_t classMaxLen = 0;
- size_t constMaxLen = 0;
- size_t constructorMaxLen = 0;
- size_t memberMaxLen = 0;
- size_t operatorMaxLen = 0;
+ bool hasClass = false;
+ bool hasConst = !fIEnumMap.empty();
+ bool hasConstructor = false;
+ bool hasMember = false;
+ bool hasOperator = false;
for (const auto& oneClass : fIClassMap) {
if (skClassName + "::" != oneClass.first.substr(0, skClassName.length() + 2)) {
continue;
}
- string structName = oneClass.first.substr(skClassName.length() + 2);
- classMaxLen = SkTMax(classMaxLen, structName.length());
- classNames.emplace_back(structName);
- }
- for (const auto& oneEnum : fIEnumMap) {
- string enumName = oneEnum.first;
- constMaxLen = SkTMax(constMaxLen, enumName.length());
- constNames.emplace_back(enumName);
+ hasClass = true;
+ break;
}
for (const auto& token : classMap.fTokens) {
if (Definition::Type::kMark != token.fType || MarkType::kMethod != token.fMarkType) {
continue;
}
- string name = token.fName;
- if (name.substr(0, 7) == "android" || string::npos != name.find("nternal_")) {
+ if (this->isInternalName(token)) {
continue;
}
- if ((name.substr(0, 2) == "Sk" && 2 == name.find(className)) || '~' == name[0]) {
- name = string(token.fContentStart, (int) (token.fContentEnd - token.fContentStart));
- constructorMaxLen = SkTMax(constructorMaxLen, name.length());
- constructorNames.emplace_back(name);
+ if (this->isConstructor(token, skClassName)) {
+ hasConstructor = true;
continue;
}
- if (name.substr(0, 8) == "operator") {
- name = string(token.fContentStart, (int) (token.fContentEnd - token.fContentStart));
- operatorMaxLen = SkTMax(operatorMaxLen, name.length());
- operatorNames.emplace_back(name);
+ if (this->isOperator(token)) {
+ hasOperator = true;
continue;
}
- if (name[name.length() - 2] == '_' && isdigit(name[name.length() - 1])) {
+ if (this->isClone(token)) {
continue;
}
- if ("SK_TO_STRING_NONVIRT" == name) {
- name = "toString";
- }
- size_t paren = name.find('(');
- size_t funcLen = string::npos == paren ? name.length() : paren;
- memberMaxLen = SkTMax(memberMaxLen, funcLen);
- memberNames.emplace_back(name);
+ hasMember = true;
}
- this->writeTag("Topic", "Overview");
- this->lf(2);
- this->writeTag("Subtopic", "Subtopics");
- string classesName = classMaxLen ? "Classes_and_Structs" : "";
- string constsName = constructorMaxLen ? "Constants" : "";
- string constructorsName = constructorMaxLen ? "Constructors" : "";
- string membersName = memberMaxLen ? "Member_Functions" : "";
- string operatorsName = operatorMaxLen ? "Operators" : "";
- size_t nameLen = SkTMax(classesName.size(), SkTMax(constsName.size(),
- SkTMax(constructorsName.size(), SkTMax(membersName.size(), operatorsName.size()))));
- this->writeTableHeader("name", nameLen, "description");
- string classDesc = classMaxLen ? "embedded struct and class members" : "";
- string constDesc = constMaxLen ? "enum and enum class, const values" : "";
- string constructorDesc = constructorMaxLen ? "functions that construct " + className : "";
- string memberDesc = memberMaxLen ? "static functions and member methods" : "";
- string operatorDesc = operatorMaxLen ? "operator overloading methods" : "";
- size_t descLen = SkTMax(classDesc.size(), SkTMax(constDesc.size(), SkTMax(constructorDesc.size(),
- SkTMax(memberDesc.size(), operatorDesc.size()))));
- if (classMaxLen) {
- this->writeTableRow(nameLen, classesName, descLen, classDesc);
- }
- if (constMaxLen) {
- this->writeTableRow(nameLen, constsName, descLen, constDesc);
- }
- if (constructorMaxLen) {
- this->writeTableRow(nameLen, constructorsName, descLen, constructorDesc);
- }
- if (memberMaxLen) {
- this->writeTableRow(nameLen, membersName, descLen, memberDesc);
- }
- if (operatorMaxLen) {
- this->writeTableRow(nameLen, operatorsName, descLen, operatorDesc);
- }
- this->writeTableTrailer();
+ this->writeTag("Subtopic", "Overview");
+ fIndent += 4;
+ this->writeTag("Subtopic", "Subtopic");
+ fIndent += 4;
+ this->writeTag("Populate");
+ fIndent -= 4;
+ this->writeEndTag();
+ fIndent -= 4;
this->writeEndTag();
this->lf(2);
- if (classMaxLen) {
- std::sort(classNames.begin(), classNames.end());
- this->writeTag("Subtopic", "Classes_and_Structs");
- this->writeTableHeader("name", classMaxLen, "description");
- for (auto& name : classNames) {
- this->writeTableRow(classMaxLen, name);
- }
- this->writeTableTrailer();
- this->writeEndTag("Subtopic");
+
+ if (hasClass) {
+ this->writeTag("Subtopic", "Class_or_Struct");
+ this->writeTag("Populate");
+ this->writeEndTag();
this->lf(2);
}
- if (constMaxLen) {
- std::sort(constNames.begin(), constNames.end());
- this->writeTag("Subtopic", "Constants");
- this->writeTableHeader("name", constMaxLen, "description");
- for (auto& name : constNames) {
- this->writeTableRow(constMaxLen, name);
- }
- this->writeTableTrailer();
- this->writeEndTag("Subtopic");
+ if (hasConst) {
+ this->writeTag("Subtopic", "Constant");
+ this->writeTag("Populate");
+ this->writeEndTag();
this->lf(2);
}
- if (constructorMaxLen) {
- std::sort(constructorNames.begin(), constructorNames.end());
- this->writeTag("Subtopic", "Constructors");
- this->writeTableHeader("name", constructorMaxLen, "description");
- for (auto& name : constructorNames) {
- this->writeTableRow(constructorMaxLen, name);
- }
- this->writeTableTrailer();
- this->writeEndTag("Subtopic");
+ if (hasConstructor) {
+ this->writeTag("Subtopic", "Constructor");
+ this->writeTag("Populate");
+ this->writeEndTag();
this->lf(2);
}
- if (operatorMaxLen) {
- std::sort(operatorNames.begin(), operatorNames.end());
- this->writeTag("Subtopic", "Operators");
- this->writeTableHeader("name", operatorMaxLen, "description");
- for (auto& name : operatorNames) {
- this->writeTableRow(operatorMaxLen, name);
- }
- this->writeTableTrailer();
- this->writeEndTag("Subtopic");
+ if (hasOperator) {
+ this->writeTag("Subtopic", "Operator");
+ this->writeTag("Populate");
+ this->writeEndTag();
this->lf(2);
}
- if (memberMaxLen) {
- std::sort(memberNames.begin(), memberNames.end());
- this->writeTag("Subtopic", "Member_Functions");
- this->writeTableHeader("name", memberMaxLen, "description");
- for (auto& name : memberNames) {
- size_t paren = name.find('(');
- size_t funcLen = string::npos == paren ? name.length() : paren;
- this->writeTableRow(memberMaxLen, name.substr(0, funcLen));
- }
- this->writeTableTrailer();
- this->writeEndTag("Subtopic");
+ if (hasMember) {
+ this->writeTag("Subtopic", "Member_Function");
+ this->writeTag("Populate");
+ this->writeEndTag();
this->lf(2);
}
- this->writeEndTag("Topic");
- this->lf(2);
for (auto& oneEnum : fIEnumMap) {
- this->writeString(
- "# ------------------------------------------------------------------------------");
- this->dumpEnum(oneEnum.second, oneEnum.first);
+ this->writeBlockSeparator();
+ this->dumpEnum(*oneEnum.second, oneEnum.first);
this->lf(2);
this->writeTag("Example");
this->lfcr();
@@ -1085,9 +1195,7 @@ bool IncludeParser::dumpTokens(const string& dir, const string& skClassName) {
continue;
}
string innerName = oneClass.first.substr(skClassName.length() + 2);
- this->writeString(
- "# ------------------------------------------------------------------------------");
- this->lf(2);
+ this->writeBlockSeparator();
KeyWord keyword = oneClass.second.fKeyWord;
SkASSERT(KeyWord::kClass == keyword || KeyWord::kStruct == keyword);
const char* containerType = KeyWord::kClass == keyword ? "Class" : "Struct";
@@ -1159,14 +1267,6 @@ bool IncludeParser::findComments(const Definition& includeDef, Definition* marku
return true;
}
-bool IncludeParser::internalName(const Definition& token) const {
- return 0 == token.fName.find("internal_")
- || 0 == token.fName.find("Internal_")
- || 0 == token.fName.find("legacy_")
- || 0 == token.fName.find("temporary_")
- || 0 == token.fName.find("private_");
-}
-
// caller calls reportError, so just return false here
bool IncludeParser::parseClass(Definition* includeDef, IsStruct isStruct) {
SkASSERT(includeDef->fTokens.size() > 0);
@@ -1267,7 +1367,7 @@ bool IncludeParser::parseClass(Definition* includeDef, IsStruct isStruct) {
return true;
}
-bool IncludeParser::parseComment(const string& filename, const char* start, const char* end,
+bool IncludeParser::parseComment(string filename, const char* start, const char* end,
int lineCount, Definition* markupDef) {
TextParser parser(filename, start, end, lineCount);
// parse doxygen if present
@@ -1277,14 +1377,26 @@ bool IncludeParser::parseComment(const string& filename, const char* start, cons
parser.skipWhiteSpace();
if ('\\' == parser.peek()) {
parser.next();
- if (!parser.skipWord(kKeyWords[(int) markupDef->fKeyWord].fName)) {
- return reportError<bool>("missing object type");
- }
- if (!parser.skipWord(markupDef->fName.c_str()) &&
- KeyWord::kEnum != markupDef->fKeyWord) {
- return reportError<bool>("missing object name");
+ // Doxygen tag may be "file" or "fn" in addition to "class", "enum", "struct"
+ if (parser.skipExact("file")) {
+ if (Definition::Type::kFileType != fParent->fType) {
+ return reportError<bool>("expected parent is file");
+ }
+ string filename = markupDef->fileName();
+ if (!parser.skipWord(filename.c_str())) {
+ return reportError<bool>("missing object type");
+ }
+ } else if (parser.skipExact("fn")) {
+ SkASSERT(0); // incomplete
+ } else {
+ if (!parser.skipWord(kKeyWords[(int) markupDef->fKeyWord].fName)) {
+ return reportError<bool>("missing object type");
+ }
+ if (!parser.skipWord(markupDef->fName.c_str()) &&
+ KeyWord::kEnum != markupDef->fKeyWord) {
+ return reportError<bool>("missing object name");
+ }
}
-
}
}
// remove leading '*' if present
@@ -1308,8 +1420,87 @@ bool IncludeParser::parseComment(const string& filename, const char* start, cons
return true;
}
-bool IncludeParser::parseDefine() {
-
+bool IncludeParser::parseDefine(Definition* child, Definition* markupDef) {
+ TextParser parser(child);
+ if (!parser.skipExact("#define")) {
+ return false;
+ }
+ if (!parser.skipSpace()) {
+ return false;
+ }
+ const char* nameStart = parser.fChar;
+ parser.skipToNonAlphaNum(); // FIXME: just want to skip isalnum() and '_'
+ if (parser.eof()) {
+ return true; // do nothing if #define doesn't define anything
+ }
+ string nameStr(nameStart, parser.fChar - nameStart);
+ struct Param {
+ const char* fStart;
+ const char* fEnd;
+ };
+ vector<Param> params;
+ if ('(' == parser.peek()) {
+ parser.next();
+ if (!parser.skipSpace()) {
+ return false;
+ }
+ do {
+ const char* paramStart = parser.fChar;
+ if (!parser.skipExact("...")) {
+ parser.skipToNonAlphaNum();
+ }
+ if (parser.eof()) {
+ return false;
+ }
+ params.push_back({paramStart, parser.fChar});
+ if (!parser.skipSpace()) {
+ return false;
+ }
+ if (')' == parser.peek()) {
+ parser.next();
+ break;
+ }
+ if (',' != parser.next()) {
+ return false;
+ }
+ if (!parser.skipSpace()) {
+ return false;
+ }
+ } while (true);
+ }
+ if (!parser.skipSpace()) {
+ return false;
+ }
+ if (!markupDef) {
+ fGlobals.emplace_back(MarkType::kDefine, nameStart, child->fContentEnd,
+ child->fLineCount, fParent, '\0');
+ Definition* globalMarkupChild = &fGlobals.back();
+ string globalUniqueName = this->uniqueName(fIDefineMap, nameStr);
+ globalMarkupChild->fName = globalUniqueName;
+ globalMarkupChild->fTerminator = child->fContentEnd;
+ if (!this->findComments(*child, globalMarkupChild)) {
+ return false;
+ }
+ fIDefineMap[globalUniqueName] = globalMarkupChild;
+ for (Param param : params) {
+ globalMarkupChild->fTokens.emplace_back(MarkType::kParam, param.fStart, param.fEnd,
+ child->fLineCount, globalMarkupChild, '\0');
+ Definition* paramChild = &globalMarkupChild->fTokens.back();
+ paramChild->fName = string(param.fStart, param.fEnd - param.fStart);
+ paramChild->fTerminator = param.fEnd;
+ }
+ return true;
+ }
+ markupDef->fTokens.emplace_back(MarkType::kDefine, child->fContentStart, child->fContentEnd,
+ child->fLineCount, markupDef, '\0');
+ Definition* markupChild = &markupDef->fTokens.back();
+ markupChild->fName = nameStr;
+ markupChild->fTerminator = markupChild->fContentEnd;
+ IClassDefinition& classDef = fIClassMap[markupDef->fName];
+ if (!this->findComments(*child, markupChild)) {
+ return false;
+ }
+ classDef.fDefines[nameStr] = markupChild;
return true;
}
@@ -1332,17 +1523,13 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) {
}
Definition* markupChild;
if (!markupDef) {
- auto finder = fIEnumMap.find(nameStr);
- if (fIEnumMap.end() != finder) {
- return child->reportError<bool>("duplicate global enum name");
- }
- markupChild = &fIEnumMap[nameStr];
- markupChild->fContentStart = child->fContentStart;
- markupChild->fName = nameStr;
- markupChild->fFiddle = nameStr;
- markupChild->fContentEnd = child->fContentEnd;
- markupChild->fFileName = child->fFileName;
- markupChild->fLineCount = child->fLineCount;
+ fGlobals.emplace_back(MarkType::kEnum, child->fContentStart, child->fContentEnd,
+ child->fLineCount, fParent, '\0');
+ markupChild = &fGlobals.back();
+ string globalUniqueName = this->uniqueName(fIEnumMap, nameStr);
+ markupChild->fName = globalUniqueName;
+ markupChild->fTerminator = child->fContentEnd;
+ fIEnumMap[globalUniqueName] = markupChild;
} else {
markupDef->fTokens.emplace_back(MarkType::kEnum, child->fContentStart, child->fContentEnd,
child->fLineCount, markupDef, '\0');
@@ -1407,7 +1594,7 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) {
}
// if there's comment on same the line as member def, output first as if it was before
- parser.skipToNonAlphaNum();
+ parser.skipToNonName();
string memberName(memberStart, parser.fChar);
if (parser.eof() || !parser.skipWhiteSpace()) {
return this->reportError<bool>("enum member must end with comma 1");
@@ -1486,7 +1673,7 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) {
return true;
}
-bool IncludeParser::parseInclude(const string& name) {
+bool IncludeParser::parseInclude(string name) {
fParent = &fIncludeMap[name];
fParent->fName = name;
fParent->fFileName = fFileName;
@@ -1513,7 +1700,7 @@ bool IncludeParser::parseMember(Definition* child, Definition* markupDef) {
child->fLineCount, markupDef, '\0');
Definition* markupChild = &markupDef->fTokens.back();
TextParser nameParser(child);
- nameParser.skipToNonAlphaNum();
+ nameParser.skipToNonName();
string nameStr = string(child->fContentStart, nameParser.fChar - child->fContentStart);
IClassDefinition& classDef = fIClassMap[markupDef->fName];
string uniqueName = this->uniqueName(classDef.fMethods, nameStr);
@@ -1667,19 +1854,15 @@ bool IncludeParser::parseMethod(Definition* child, Definition* markupDef) {
if (nameParser.skipToEndBracket(':') && nameParser.startsWith("::")) {
return true; // expect this is inline class definition outside of class
}
- string name(nameParser.fLine, nameParser.lineLength());
- auto finder = fIFunctionMap.find(name);
- if (fIFunctionMap.end() != finder) {
- // create unique name
- SkASSERT(0); // incomplete
- }
- auto globalFunction = &fIFunctionMap[name];
- globalFunction->fContentStart = start;
- globalFunction->fName = name;
- globalFunction->fFiddle = name;
- globalFunction->fContentEnd = end;
- globalFunction->fMarkType = MarkType::kMethod;
- globalFunction->fLineCount = tokenIter->fLineCount;
+ fGlobals.emplace_back(MarkType::kMethod, start, end, tokenIter->fLineCount,
+ fParent, '\0');
+ Definition* globalMarkupChild = &fGlobals.back();
+ string globalUniqueName = this->uniqueName(fIFunctionMap, nameStr);
+ globalMarkupChild->fName = globalUniqueName;
+ if (!this->findComments(*child, globalMarkupChild)) {
+ return false;
+ }
+ fIFunctionMap[globalUniqueName] = globalMarkupChild;
return true;
}
markupDef->fTokens.emplace_back(MarkType::kMethod, start, end, tokenIter->fLineCount,
@@ -1799,7 +1982,7 @@ bool IncludeParser::parseObject(Definition* child, Definition* markupDef) {
case KeyWord::kIf:
case KeyWord::kIfndef:
case KeyWord::kIfdef:
- if (child->boilerplateIfDef(fParent)) {
+ if (child->boilerplateIfDef()) {
if (!this->parseObjects(child, markupDef)) {
return false;
}
@@ -1807,7 +1990,7 @@ bool IncludeParser::parseObject(Definition* child, Definition* markupDef) {
}
goto preproError;
case KeyWord::kDefine:
- if (child->boilerplateDef(fParent)) {
+ if (this->parseDefine(child, markupDef)) {
break;
}
goto preproError;
@@ -1873,16 +2056,15 @@ bool IncludeParser::parseTypedef(Definition* child, Definition* markupDef) {
typedefParser.skipWhiteSpace();
string nameStr = typedefParser.typedefName();
if (!markupDef) {
- Definition& typedefDef = fITypedefMap[nameStr];
- SkASSERT(!typedefDef.fStart);
- typedefDef.fStart = child->fContentStart;
- typedefDef.fContentStart = child->fContentStart;
- typedefDef.fName = nameStr;
- typedefDef.fFiddle = nameStr;
- typedefDef.fContentEnd = child->fContentEnd;
- typedefDef.fTerminator = child->fContentEnd;
- typedefDef.fMarkType = MarkType::kTypedef;
- typedefDef.fLineCount = child->fLineCount;
+ fGlobals.emplace_back(MarkType::kTypedef, child->fContentStart, child->fContentEnd,
+ child->fLineCount, fParent, '\0');
+ Definition* globalMarkupChild = &fGlobals.back();
+ string globalUniqueName = this->uniqueName(fITypedefMap, nameStr);
+ globalMarkupChild->fName = globalUniqueName;
+ if (!this->findComments(*child, globalMarkupChild)) {
+ return false;
+ }
+ fITypedefMap[globalUniqueName] = globalMarkupChild;
return true;
}
markupDef->fTokens.emplace_back(MarkType::kTypedef, child->fContentStart, child->fContentEnd,
@@ -1927,9 +2109,17 @@ bool IncludeParser::parseChar() {
if (KeyWord::kNone == keyWord) {
return this->reportError<bool>("unhandled preprocessor directive");
}
+ if (fInDefine) {
+ SkASSERT(KeyWord::kDefine == keyWord);
+ fInDefine = false;
+ }
if (KeyWord::kInclude == keyWord || KeyWord::kDefine == keyWord || KeyWord::kError == keyWord) {
this->popBracket();
}
+ if (fInBrace) {
+ SkASSERT(KeyWord::kDefine == fInBrace->fKeyWord);
+ fInBrace = nullptr;
+ }
} else if (Bracket::kSlashSlash == this->topBracket()) {
this->popBracket();
}
@@ -1986,18 +2176,21 @@ bool IncludeParser::parseChar() {
this->pushBracket(Bracket::kString);
}
break;
- case ':':
case '(':
- case '[':
- case '{': {
- if (fIncludeWord && '(' == test && fChar - fIncludeWord >= 10 &&
+ if (fIncludeWord && fChar - fIncludeWord >= 10 &&
!strncmp("SkDEBUGCODE", fIncludeWord, 10)) {
this->pushBracket(Bracket::kDebugCode);
break;
}
+ case ':':
+ case '[':
+ case '{': {
if (fInCharCommentString) {
break;
}
+ if (fInDefine && fInBrace) {
+ break;
+ }
if (':' == test && (fInBrace || ':' == fChar[-1] || ':' == fChar[1])) {
break;
}
@@ -2051,6 +2244,9 @@ bool IncludeParser::parseChar() {
if (fInCharCommentString) {
break;
}
+ if (fInDefine && fInBrace) {
+ break;
+ }
if (!fInBrace) {
if (!this->checkForWord()) {
return false;
@@ -2104,9 +2300,14 @@ bool IncludeParser::parseChar() {
this->pushBracket(Bracket::kPound);
break;
}
+ case ' ':
+ if (fInDefine && !fInBrace && Bracket::kPound == this->topBracket()) {
+ SkASSERT(KeyWord::kDefine == fParent->fKeyWord);
+ fInBrace = fParent;
+ // delimiting brackets are space ... unescaped-linefeed
+ }
case '&':
case ',':
- case ' ':
case '+':
case '=':
case '-':
@@ -2260,7 +2461,7 @@ bool IncludeParser::parseChar() {
std::advance(tokenWalker, 1);
if (tokenWalker != fParent->fTokens.end()) {
TextParser tp(fFileName, nameStart, tokenWalker->fStart, fLineCount);
- tp.skipToNonAlphaNum();
+ tp.skipToNonName();
start->fName = string(nameStart, tp.fChar - nameStart);
start->fContentEnd = fChar;
priorEnum->fChildren.emplace_back(start);