aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/bookmaker
diff options
context:
space:
mode:
authorGravatar Cary Clark <caryclark@skia.org>2018-04-03 08:43:27 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-04-03 16:09:56 +0000
commit186d08f621efcaf9960ffe4a1dd9e6703de8a698 (patch)
tree7087f2b1a18ef61e26103389a3aab051c9d923f3 /tools/bookmaker
parentba31640427659ea2c096be1a26976e34348619cf (diff)
fix bugs exposed by documenting SkImageInfo
- More rigorous symbol identification creates additional links, and finds spurious errors like unnecessary parentheses. - Fixed code to allow preprocessor directives in #Code blocks (still more to do). - Fixed examples waiting on fiddle updates. - Make SkImageInfo officially documented (update in status.json). - Fixed enum indentation. Docs-Preview: https://skia.org/?cl=115656 Bug: skia:6898 Change-Id: Ifcf5cfd3f6c03b3b83155c898b2b035a2f3d443c Reviewed-on: https://skia-review.googlesource.com/115656 Commit-Queue: Cary Clark <caryclark@skia.org> Reviewed-by: Cary Clark <caryclark@skia.org>
Diffstat (limited to 'tools/bookmaker')
-rw-r--r--tools/bookmaker/bookmaker.cpp51
-rw-r--r--tools/bookmaker/bookmaker.h106
-rw-r--r--tools/bookmaker/cataloger.cpp2
-rw-r--r--tools/bookmaker/definition.cpp6
-rw-r--r--tools/bookmaker/includeParser.cpp28
-rw-r--r--tools/bookmaker/includeWriter.cpp150
-rw-r--r--tools/bookmaker/mdOut.cpp135
-rw-r--r--tools/bookmaker/parserCommon.cpp4
8 files changed, 294 insertions, 188 deletions
diff --git a/tools/bookmaker/bookmaker.cpp b/tools/bookmaker/bookmaker.cpp
index 4016a19439..223c5b521a 100644
--- a/tools/bookmaker/bookmaker.cpp
+++ b/tools/bookmaker/bookmaker.cpp
@@ -50,6 +50,9 @@ trouble with aliases, plurals
need to keep first letter of includeWriter @param / @return lowercase
Quad -> quad, Quads -> quads
deprecated methods should be sorted down in md out, and show include "Deprecated." text body.
+rewrap text to fit in some number of columns
+#Literal is inflexible, making the entire #Code block link-less (see $Literal in SkImageInfo)
+ would rather keep links for boby above #Literal, and/or make it a block and not a one-liner
see head of selfCheck.cpp for additional todos
*/
@@ -639,7 +642,7 @@ string BmhParser::className(MarkType markType) {
const char* end = this->lineEnd();
const char* mc = this->strnchr(fMC, end);
string classID;
- TextParser::Save savePlace(this);
+ TextParserSave savePlace(this);
this->skipSpace();
const char* wordStart = fChar;
this->skipToNonAlphaNum();
@@ -1054,9 +1057,6 @@ bool BmhParser::findDefinitions() {
const char* lastMC = nullptr;
fParent = nullptr;
while (!this->eof()) {
- if (195 == fLineCount && "docs\\SkImageInfo_Reference.bmh" == fFileName) {
- SkDebugf("");
- }
if (this->peek() == fMC) {
lastMC = fChar;
this->next();
@@ -1570,7 +1570,7 @@ string BmhParser::methodName() {
bool addConst = false;
if (isConstructor || expectOperator) {
paren = this->strnchr(')', end) + 1;
- TextParser::Save saveState(this);
+ TextParserSave saveState(this);
this->skipTo(paren);
if (this->skipExact("_const")) {
addConst = true;
@@ -1593,7 +1593,7 @@ string BmhParser::methodName() {
}
this->next();
}
- TextParser::Save saveState(this);
+ TextParserSave saveState(this);
this->skipWhiteSpace();
if (this->startsWith("const")) {
this->skipName("const");
@@ -1739,6 +1739,22 @@ void TextParser::reportWarning(const char* errorStr) const {
}
}
+void TextParser::setForErrorReporting(const Definition* definition, const char* str) {
+ fFileName = definition->fFileName;
+ fStart = definition->fContentStart;
+ fLine = str;
+ while (fLine > fStart && fLine[-1] != '\n') {
+ --fLine;
+ }
+ fChar = str;
+ fEnd = definition->fContentEnd;
+ fLineCount = definition->fLineCount;
+ const char* lineInc = fStart;
+ while (lineInc < str) {
+ fLineCount += '\n' == *lineInc++;
+ }
+}
+
string TextParser::typedefName() {
// look for typedef as one of three forms:
// typedef return-type (*NAME)(params);
@@ -2289,7 +2305,7 @@ int main(int argc, char** const argv) {
if (FLAGS_tokens) {
IncludeParser::RemoveFile(FLAGS_bmh[0], FLAGS_include[0]);
}
- if (!bmhParser.parseFile(FLAGS_bmh[0], ".bmh")) {
+ if (!bmhParser.parseFile(FLAGS_bmh[0], ".bmh", ParserCommon::OneFile::kNo)) {
return -1;
}
} else if (!FLAGS_status.isEmpty()) {
@@ -2304,7 +2320,7 @@ int main(int argc, char** const argv) {
return 1;
}
HackParser hacker(bmhParser);
- if (!hacker.parseFile(FLAGS_bmh[0], ".bmh")) {
+ if (!hacker.parseFile(FLAGS_bmh[0], ".bmh", ParserCommon::OneFile::kNo)) {
SkDebugf("hack failed\n");
return -1;
}
@@ -2317,7 +2333,7 @@ int main(int argc, char** const argv) {
if (!FLAGS_include.isEmpty() && FLAGS_tokens) {
IncludeParser includeParser;
includeParser.validate();
- if (!includeParser.parseFile(FLAGS_include[0], ".h")) {
+ if (!includeParser.parseFile(FLAGS_include[0], ".h", ParserCommon::OneFile::kNo)) {
return -1;
}
if (FLAGS_tokens) {
@@ -2332,7 +2348,7 @@ int main(int argc, char** const argv) {
IncludeParser includeParser;
includeParser.validate();
if (!FLAGS_include.isEmpty() &&
- !includeParser.parseFile(FLAGS_include[0], ".h")) {
+ !includeParser.parseFile(FLAGS_include[0], ".h", ParserCommon::OneFile::kNo)) {
return -1;
}
if (!FLAGS_status.isEmpty() && !includeParser.parseStatus(FLAGS_status[0], ".h",
@@ -2347,7 +2363,7 @@ int main(int argc, char** const argv) {
IncludeWriter includeWriter;
includeWriter.validate();
if (!FLAGS_include.isEmpty() &&
- !includeWriter.parseFile(FLAGS_include[0], ".h")) {
+ !includeWriter.parseFile(FLAGS_include[0], ".h", ParserCommon::OneFile::kNo)) {
return -1;
}
if (!FLAGS_status.isEmpty() && !includeWriter.parseStatus(FLAGS_status[0], ".h",
@@ -2364,7 +2380,7 @@ int main(int argc, char** const argv) {
}
if (!done && !FLAGS_fiddle.isEmpty() && FLAGS_examples.isEmpty()) {
FiddleParser fparser(&bmhParser);
- if (!fparser.parseFile(FLAGS_fiddle[0], ".txt")) {
+ if (!fparser.parseFile(FLAGS_fiddle[0], ".txt", ParserCommon::OneFile::kNo)) {
return -1;
}
}
@@ -2377,7 +2393,7 @@ int main(int argc, char** const argv) {
if (!FLAGS_status.isEmpty() && !cparser.openStatus(FLAGS_status[0], FLAGS_ref[0])) {
return -1;
}
- if (!cparser.parseFile(FLAGS_fiddle[0], ".txt")) {
+ if (!cparser.parseFile(FLAGS_fiddle[0], ".txt", ParserCommon::OneFile::kNo)) {
return -1;
}
if (!cparser.closeCatalog()) {
@@ -2387,9 +2403,16 @@ int main(int argc, char** const argv) {
done = true;
}
if (!done && !FLAGS_ref.isEmpty() && FLAGS_examples.isEmpty()) {
+ IncludeParser includeParser;
+ includeParser.validate();
+ if (!FLAGS_include.isEmpty() && !includeParser.parseFile(FLAGS_include[0], ".h",
+ ParserCommon::OneFile::kYes)) {
+ return -1;
+ }
MdOut mdOut(bmhParser);
mdOut.fDebugOut = FLAGS_stdout;
- if (!FLAGS_bmh.isEmpty() && mdOut.buildReferences(FLAGS_bmh[0], FLAGS_ref[0])) {
+ if (!FLAGS_bmh.isEmpty() && mdOut.buildReferences(includeParser,
+ FLAGS_bmh[0], FLAGS_ref[0])) {
bmhParser.fWroteOut = true;
}
if (!FLAGS_status.isEmpty() && mdOut.buildStatus(FLAGS_status[0], FLAGS_ref[0])) {
diff --git a/tools/bookmaker/bookmaker.h b/tools/bookmaker/bookmaker.h
index 968644f8b1..a0f6bca6a7 100644
--- a/tools/bookmaker/bookmaker.h
+++ b/tools/bookmaker/bookmaker.h
@@ -240,31 +240,11 @@ public:
class Definition;
class TextParser : public NonAssignable {
- TextParser() {} // only for ParserCommon to call
+ TextParser() {} // only for ParserCommon, TextParserSave
friend class ParserCommon;
+ friend class TextParserSave;
public:
virtual ~TextParser() {}
- class Save {
- public:
- Save(TextParser* parser) {
- fParser = parser;
- fLine = parser->fLine;
- fChar = parser->fChar;
- fLineCount = parser->fLineCount;
- }
-
- void restore() const {
- fParser->fLine = fLine;
- fParser->fChar = fChar;
- fParser->fLineCount = fLineCount;
- }
-
- private:
- TextParser* fParser;
- const char* fLine;
- const char* fChar;
- int fLineCount;
- };
TextParser(const string& fileName, const char* start, const char* end, int lineCount)
: fFileName(fileName)
@@ -417,6 +397,8 @@ public:
return true;
}
+ void setForErrorReporting(const Definition* , const char* );
+
bool skipToEndBracket(char endBracket, const char* end = nullptr) {
if (nullptr == end) {
end = fEnd;
@@ -690,6 +672,33 @@ public:
size_t fLineCount;
};
+class TextParserSave {
+public:
+ TextParserSave(TextParser* parser) {
+ fParser = parser;
+ fSave.fFileName = parser->fFileName;
+ fSave.fStart = parser->fStart;
+ fSave.fLine = parser->fLine;
+ fSave.fChar = parser->fChar;
+ fSave.fEnd = parser->fEnd;
+ fSave.fLineCount = parser->fLineCount;
+ }
+
+ void restore() const {
+ fParser->fFileName = fSave.fFileName;
+ fParser->fStart = fSave.fStart;
+ fParser->fLine = fSave.fLine;
+ fParser->fChar = fSave.fChar;
+ fParser->fEnd = fSave.fEnd;
+ fParser->fLineCount = fSave.fLineCount;
+ }
+
+private:
+ TextParser* fParser;
+ TextParser fSave;
+};
+
+
class EscapeParser : public TextParser {
public:
EscapeParser(const char* start, const char* end) :
@@ -1019,6 +1028,10 @@ struct TypeNames {
class ParserCommon : public TextParser {
public:
+ enum class OneFile {
+ kNo,
+ kYes,
+ };
ParserCommon() : TextParser()
, fParent(nullptr)
@@ -1078,7 +1091,7 @@ public:
fPendingSpace = 0;
}
- bool parseFile(const char* file, const char* suffix);
+ bool parseFile(const char* file, const char* suffix, OneFile );
bool parseStatus(const char* file, const char* suffix, StatusFilter filter);
virtual bool parseFromFile(const char* path) = 0;
bool parseSetup(const char* path);
@@ -1206,8 +1219,9 @@ public:
enum class Resolvable {
kNo, // neither resolved nor output
kYes, // resolved, output
- kOut, // not resolved, but output
- kLiteral, // output untouched (FIXME: is this really different from kOut?)
+ kOut, // mostly resolved, output (FIXME: is this really different from kYes?)
+ kFormula, // resolve methods as they are used, not as they are prototyped
+ kLiteral, // output untouched
kClone, // resolved, output, with references to clones as well
};
@@ -1252,6 +1266,7 @@ public:
#define R_Y Resolvable::kYes
#define R_N Resolvable::kNo
#define R_O Resolvable::kOut
+#define R_F Resolvable::kFormula
#define R_C Resolvable::kClone
#define E_Y Exemplary::kYes
@@ -1284,7 +1299,7 @@ public:
, { "Experimental", nullptr, MarkType::kExperimental, R_Y, E_N, 0 }
, { "External", nullptr, MarkType::kExternal, R_Y, E_N, M(Root) }
, { "File", nullptr, MarkType::kFile, R_N, E_N, M(Track) }
-, { "Formula", nullptr, MarkType::kFormula, R_O, E_N,
+, { "Formula", nullptr, MarkType::kFormula, R_F, E_N,
M(Column) | M_E | M_ST | M(Member) | M(Method) | M_D }
, { "Function", nullptr, MarkType::kFunction, R_O, E_N, M(Example) | M(NoExample) }
, { "Height", nullptr, MarkType::kHeight, R_N, E_N, M(Example) | M(NoExample) }
@@ -1301,7 +1316,7 @@ public:
, { "", nullptr, MarkType::kMarkChar, R_N, E_N, 0 }
, { "Member", nullptr, MarkType::kMember, R_Y, E_N, M_CSST }
, { "Method", &fMethodMap, MarkType::kMethod, R_Y, E_Y, M_CSST }
-, { "NoExample", nullptr, MarkType::kNoExample, R_O, E_N, M_CSST | M_E | M(Method) }
+, { "NoExample", nullptr, MarkType::kNoExample, R_N, E_N, M_CSST | M_E | M(Method) }
, { "Outdent", nullptr, MarkType::kOutdent, R_N, E_N, M(Code) }
, { "Param", nullptr, MarkType::kParam, R_Y, E_N, M(Method) }
, { "PhraseDef", nullptr, MarkType::kPhraseDef, R_Y, E_N, M(Subtopic) }
@@ -1338,6 +1353,8 @@ public:
#undef R_O
#undef R_N
#undef R_Y
+#undef R_F
+#undef R_C
#undef M_E
#undef M_CSST
@@ -1346,6 +1363,10 @@ public:
#undef M_D
#undef M
+#undef E_Y
+#undef E_N
+#undef E_O
+
~BmhParser() override {}
bool addDefinition(const char* defStart, bool hasEnd, MarkType markType,
@@ -1634,6 +1655,8 @@ public:
this->addDefinition(container);
}
+ bool references(const SkString& file) const;
+
static void RemoveFile(const char* docs, const char* includes);
static void RemoveOneFile(const char* docs, const char* includesFileOrPath);
@@ -1888,6 +1911,11 @@ public:
kChars,
};
+ enum class MemberPass {
+ kCount,
+ kOut,
+ };
+
struct IterState {
IterState (list<Definition>::iterator tIter, list<Definition>::iterator tIterEnd)
: fDefIter(tIter)
@@ -1902,6 +1930,17 @@ public:
const ParentPair* fPrev;
};
+ struct Preprocessor {
+ Preprocessor()
+ : fStart(nullptr)
+ , fEnd(nullptr)
+ , fWord(false) {
+ }
+ const char* fStart;
+ const char* fEnd;
+ bool fWord;
+ };
+
IncludeWriter() : IncludeParser() {
this->reset();
}
@@ -1924,7 +1963,10 @@ public:
void descriptionOut(const Definition* def, SkipFirstLine , Phrase );
void enumHeaderOut(const RootDefinition* root, const Definition& child);
void enumMembersOut(const RootDefinition* root, Definition& child);
+ bool enumPreprocessor(Definition* token, MemberPass pass,
+ vector<IterState>& iterStack, IterState** iterState, Preprocessor* );
void enumSizeItems(const Definition& child);
+ bool findEnumSubtopic(string undername, const Definition** ) const;
Definition* findMemberCommentBlock(const vector<Definition*>& bmhChildren, const string& name) const;
int lookupMethod(const PunctuationState punctuation, const Word word,
const int start, const int run, int lastWrite,
@@ -2101,7 +2143,7 @@ public:
this->reset();
}
- bool buildReferences(const char* docDir, const char* mdOutDirOrFile);
+ bool buildReferences(const IncludeParser& , const char* docDir, const char* mdOutDirOrFile);
bool buildStatus(const char* docDir, const char* mdOutDir);
static constexpr const char* kClassesAndStructs = "Class_or_Struct";
@@ -2137,7 +2179,7 @@ private:
void childrenOut(const Definition* def, const char* contentStart);
const Definition* csParent() const;
const Definition* findParamType();
- const Definition* isDefined(const TextParser& parser, const string& ref, bool report);
+ const Definition* isDefined(const TextParser& , const string& ref, BmhParser::Resolvable );
string linkName(const Definition* ) const;
string linkRef(const string& leadingSpaces, const Definition*, const string& ref,
BmhParser::Resolvable ) const;
@@ -2166,7 +2208,8 @@ private:
fHasFiddle = false;
fInDescription = false;
fInList = false;
- fRespectLeadingSpace = false;
+ fResolveAndIndent = false;
+ fLiteralAndIndent = false;
}
BmhParser::Resolvable resolvable(const Definition* definition) const {
@@ -2204,7 +2247,8 @@ private:
bool fInDescription; // FIXME: for now, ignore unfound camelCase in description since it may
// be defined in example which at present cannot be linked to
bool fInList;
- bool fRespectLeadingSpace;
+ bool fLiteralAndIndent;
+ bool fResolveAndIndent;
typedef ParserCommon INHERITED;
};
diff --git a/tools/bookmaker/cataloger.cpp b/tools/bookmaker/cataloger.cpp
index a564d3ee98..de46ecd1a7 100644
--- a/tools/bookmaker/cataloger.cpp
+++ b/tools/bookmaker/cataloger.cpp
@@ -86,7 +86,7 @@ bool Catalog::parseFromFile(const char* path) {
this->writeString("var text = {");
this->lf(1);
fTextOut = true;
- TextParser::Save save(this);
+ TextParserSave save(this);
if (!parseFiddles()) {
return false;
}
diff --git a/tools/bookmaker/definition.cpp b/tools/bookmaker/definition.cpp
index 14f6daab81..e3a5aa3bd5 100644
--- a/tools/bookmaker/definition.cpp
+++ b/tools/bookmaker/definition.cpp
@@ -200,7 +200,7 @@ bool Definition::parseOperator(size_t doubleColons, string& result) {
SkAssertResult(iParser.skipExact("operator"));
iParser.skipWhiteSpace();
fMethodType = Definition::MethodType::kOperator;
- TextParser::Save save(&iParser);
+ TextParserSave save(&iParser);
for (auto parser : opData) {
save.restore();
if (!iParser.skipExact(parser.fSymbol)) {
@@ -670,7 +670,7 @@ string Definition::formatFunction(Format format) const {
indent = (size_t) (lastEnd - lastStart);
}
// trim indent so longest line doesn't exceed box width
- TextParser::Save savePlace(&methodParser);
+ TextParserSave savePlace(&methodParser);
const char* saveStart = lastStart;
ptrdiff_t maxLine = 0;
do {
@@ -889,7 +889,7 @@ string Definition::methodName() const {
bool Definition::nextMethodParam(TextParser* methodParser, const char** nextEndPtr,
string* paramName) const {
int parenCount = 0;
- TextParser::Save saveState(methodParser);
+ TextParserSave saveState(methodParser);
while (true) {
if (methodParser->eof()) {
return methodParser->reportError<bool>("#Method function missing close paren");
diff --git a/tools/bookmaker/includeParser.cpp b/tools/bookmaker/includeParser.cpp
index 8365a82d1c..4040fb6d15 100644
--- a/tools/bookmaker/includeParser.cpp
+++ b/tools/bookmaker/includeParser.cpp
@@ -1363,9 +1363,6 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) {
markupChild->fName = markupDef->fName + "::" +
string(nameStart, (size_t) (enumName.fChar - nameStart));
}
- if (string::npos != markupChild->fName.find("SkColorType")) {
- SkDebugf("");
- }
if (!this->findComments(*child, markupChild)) {
return false;
}
@@ -1433,7 +1430,7 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) {
if ('/' == parser.next()) {
char slashStar = parser.next();
if ('/' == slashStar || '*' == slashStar) {
- TextParser::Save save(&parser);
+ TextParserSave save(&parser);
char doxCheck = parser.next();
if ((slashStar != doxCheck && '!' != doxCheck) || '<' != parser.next()) {
save.restore();
@@ -1954,7 +1951,7 @@ bool IncludeParser::parseChar() {
return reportError<bool>("malformed closing comment");
}
if (Bracket::kSlashStar == this->topBracket()) {
- TextParser::Save save(this);
+ TextParserSave save(this);
this->next(); // include close in bracket
this->popBracket();
save.restore(); // put things back so nothing is skipped
@@ -2316,6 +2313,27 @@ void IncludeParser::validate() const {
IncludeParser::ValidateKeyWords();
}
+bool IncludeParser::references(const SkString& file) const {
+ // if includes weren't passed one at a time, assume all references are valid
+ if (fIncludeMap.empty()) {
+ return true;
+ }
+ SkASSERT(file.endsWith(".bmh") );
+ string root(file.c_str(), file.size() - 4);
+ string kReference("_Reference");
+ if (string::npos != root.find(kReference)) {
+ root = root.substr(0, root.length() - kReference.length());
+ }
+ if (fIClassMap.end() != fIClassMap.find(root)) {
+ return true;
+ }
+ if (fIStructMap.end() != fIStructMap.find(root)) {
+ return true;
+ }
+ // TODO incomplete: probably need to look in other places for class-less includes like SkColor.h
+ return false;
+}
+
void IncludeParser::RemoveFile(const char* docs, const char* includes) {
if (!sk_isdir(includes)) {
IncludeParser::RemoveOneFile(docs, includes);
diff --git a/tools/bookmaker/includeWriter.cpp b/tools/bookmaker/includeWriter.cpp
index 067c014070..5b2f8076bc 100644
--- a/tools/bookmaker/includeWriter.cpp
+++ b/tools/bookmaker/includeWriter.cpp
@@ -375,43 +375,11 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child
vector<IterState> iterStack;
iterStack.emplace_back(child.fTokens.begin(), child.fTokens.end());
IterState* iterState = &iterStack[0];
- bool preprocessorWord = false;
- const char* preprocessStart = nullptr;
- const char* preprocessEnd = nullptr;
+ Preprocessor preprocessor;
for (int onePast = 0; onePast < 2; onePast += iterState->fDefIter == iterState->fDefEnd) {
Definition* token = onePast ? nullptr : &*iterState->fDefIter++;
- if (token && Definition::Type::kBracket == token->fType) {
- if (Bracket::kSlashSlash == token->fBracket) {
- fStart = token->fContentEnd;
- continue; // ignore old inline comments
- }
- if (Bracket::kSlashStar == token->fBracket) {
- fStart = token->fContentEnd + 1;
- continue; // ignore old inline comments
- }
- if (Bracket::kPound == token->fBracket) { // preprocessor wraps member
- preprocessStart = token->fContentStart;
- if (KeyWord::kIf == token->fKeyWord || KeyWord::kIfdef == token->fKeyWord) {
- iterStack.emplace_back(token->fTokens.begin(), token->fTokens.end());
- iterState = &iterStack.back();
- preprocessorWord = true;
- } else if (KeyWord::kEndif == token->fKeyWord) {
- iterStack.pop_back();
- iterState = &iterStack.back();
- preprocessEnd = token->fContentEnd;
- } else {
- SkASSERT(0); // incomplete
- }
- continue;
- }
- SkASSERT(0); // incomplete
- }
- if (token && Definition::Type::kWord != token->fType) {
- SkASSERT(0); // incomplete
- }
- if (preprocessorWord) {
- preprocessorWord = false;
- preprocessEnd = token->fContentEnd;
+ if (this->enumPreprocessor(token, MemberPass::kOut, iterStack, &iterState,
+ &preprocessor)) {
continue;
}
if (token && State::kItemName == state) {
@@ -462,16 +430,17 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child
fIndent -= 4;
}
this->lfcr();
- if (preprocessStart) {
- SkASSERT(preprocessEnd);
+ if (preprocessor.fStart) {
+ SkASSERT(preprocessor.fEnd);
int saveIndent = fIndent;
fIndent = SkTMax(0, fIndent - 8);
this->lf(2);
- this->writeBlock((int) (preprocessEnd - preprocessStart), preprocessStart);
+ this->writeBlock(
+ (int) (preprocessor.fEnd - preprocessor.fStart), preprocessor.fStart);
this->lfcr();
fIndent = saveIndent;
- preprocessStart = nullptr;
- preprocessEnd = nullptr;
+ preprocessor.fStart = nullptr;
+ preprocessor.fEnd = nullptr;
}
if (token && State::kItemValue == state) {
fStart = token->fContentStart;
@@ -538,8 +507,11 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child
this->writeString(currentEnumItem->fToBeDeprecated
? "To be deprecated soon." : "Deprecated.");
}
+ TextParserSave save(this);
+ this->setForErrorReporting(currentEnumItem, commentStart);
wroteLineFeed = Wrote::kLF ==
this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
+ save.restore();
fIndent -= 4;
if (wroteLineFeed || fColumn > 100 - 3 /* space * / */ ) {
this->lfcr();
@@ -559,6 +531,55 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child
}
}
+bool IncludeWriter::enumPreprocessor(Definition* token, MemberPass pass,
+ vector<IterState>& iterStack, IterState** iterState, Preprocessor* preprocessor) {
+ if (token && Definition::Type::kBracket == token->fType) {
+ if (Bracket::kSlashSlash == token->fBracket) {
+ if (MemberPass::kOut == pass) {
+ fStart = token->fContentEnd;
+ }
+ return true; // ignore old inline comments
+ }
+ if (Bracket::kSlashStar == token->fBracket) {
+ if (MemberPass::kOut == pass) {
+ fStart = token->fContentEnd + 1;
+ }
+ return true; // ignore old inline comments
+ }
+ if (Bracket::kPound == token->fBracket) { // preprocessor wraps member
+ preprocessor->fStart = token->fContentStart;
+ if (KeyWord::kIf == token->fKeyWord || KeyWord::kIfdef == token->fKeyWord) {
+ iterStack.emplace_back(token->fTokens.begin(), token->fTokens.end());
+ *iterState = &iterStack.back();
+ preprocessor->fWord = true;
+ } else if (KeyWord::kEndif == token->fKeyWord || KeyWord::kElif == token->fKeyWord
+ || KeyWord::kElse == token->fKeyWord) {
+ iterStack.pop_back();
+ *iterState = &iterStack.back();
+ preprocessor->fEnd = token->fContentEnd;
+ if (KeyWord::kElif == token->fKeyWord) {
+ iterStack.emplace_back(token->fTokens.begin(), token->fTokens.end());
+ *iterState = &iterStack.back();
+ preprocessor->fWord = true;
+ }
+ } else {
+ SkASSERT(0); // incomplete
+ }
+ return true;
+ }
+ return true;
+ }
+ if (token && Definition::Type::kWord != token->fType) {
+ SkASSERT(0); // incomplete
+ }
+ if (preprocessor->fWord) {
+ preprocessor->fWord = false;
+ preprocessor->fEnd = token->fContentEnd;
+ return true;
+ }
+ return false;
+}
+
void IncludeWriter::enumSizeItems(const Definition& child) {
enum class State {
kNoItem,
@@ -580,36 +601,11 @@ void IncludeWriter::enumSizeItems(const Definition& child) {
vector<IterState> iterStack;
iterStack.emplace_back(brace->fTokens.begin(), brace->fTokens.end());
IterState* iterState = &iterStack[0];
- bool preprocessorWord = false;
+ Preprocessor preprocessor;
while (iterState->fDefIter != iterState->fDefEnd) {
auto& token = *iterState->fDefIter++;
- if (Definition::Type::kBracket == token.fType) {
- if (Bracket::kSlashSlash == token.fBracket) {
- continue; // ignore old inline comments
- }
- if (Bracket::kSlashStar == token.fBracket) {
- continue; // ignore old inline comments
- }
- if (Bracket::kPound == token.fBracket) { // preprocessor wraps member
- if (KeyWord::kIf == token.fKeyWord || KeyWord::kIfdef == token.fKeyWord) {
- iterStack.emplace_back(token.fTokens.begin(), token.fTokens.end());
- iterState = &iterStack.back();
- preprocessorWord = true;
- } else if (KeyWord::kEndif == token.fKeyWord) {
- iterStack.pop_back();
- iterState = &iterStack.back();
- } else {
- SkASSERT(0); // incomplete
- }
- continue;
- }
- SkASSERT(0); // incomplete
- }
- if (Definition::Type::kWord != token.fType) {
- SkASSERT(0); // incomplete
- }
- if (preprocessorWord) {
- preprocessorWord = false;
+ if (this->enumPreprocessor(&token, MemberPass::kCount, iterStack, &iterState,
+ &preprocessor)) {
continue;
}
if (State::kItemName == state) {
@@ -763,6 +759,17 @@ void IncludeWriter::structOut(const Definition* root, const Definition& child,
this->writeCommentTrailer();
}
+bool IncludeWriter::findEnumSubtopic(string undername, const Definition** rootDefPtr) const {
+ const Definition* subtopic = fEnumDef->fParent;
+ string subcheck = subtopic->fFiddle + '_' + undername;
+ auto iter = fBmhParser->fTopicMap.find(subcheck);
+ if (iter == fBmhParser->fTopicMap.end()) {
+ return false;
+ }
+ *rootDefPtr = iter->second;
+ return true;
+}
+
Definition* IncludeWriter::findMemberCommentBlock(const vector<Definition*>& bmhChildren,
const string& name) const {
for (auto memberDef : bmhChildren) {
@@ -1038,9 +1045,6 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
const Definition* requireDense = nullptr;
const Definition* startDef = nullptr;
for (auto& child : def->fTokens) {
- if (51 == child.fLineCount) {
- SkDebugf("");
- }
if (KeyWord::kOperator == child.fKeyWord && method &&
Definition::MethodType::kOperator == method->fMethodType) {
eatOperator = true;
@@ -1728,8 +1732,10 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first,
auto aliasIter = fBmhParser->fAliasMap.find(undername);
if (fBmhParser->fAliasMap.end() != aliasIter) {
rootDef = aliasIter->second;
+ } else if (fInEnum && fEnumDef && this->findEnumSubtopic(undername, &rootDef)) {
+ ;
} else if (!first) {
- SkDebugf("unfound: %s\n", undername.c_str());
+ this->fChar = start;
this->reportError("reference unfound");
return "";
}
diff --git a/tools/bookmaker/mdOut.cpp b/tools/bookmaker/mdOut.cpp
index 80d3e21faa..4b4e2b89be 100644
--- a/tools/bookmaker/mdOut.cpp
+++ b/tools/bookmaker/mdOut.cpp
@@ -93,8 +93,7 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
continue;
}
ref = string(start, t.fChar - start);
- if (const Definition* def = this->isDefined(t, ref,
- BmhParser::Resolvable::kOut != resolvable)) {
+ if (const Definition* def = this->isDefined(t, ref, resolvable)) {
if (MarkType::kExternal == def->fMarkType) {
add_ref(leadingSpaces, ref, &result);
continue;
@@ -122,7 +121,7 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
}
string altTest = ref + '_';
altTest += suffix++;
- altDef = this->isDefined(t, altTest, false);
+ altDef = this->isDefined(t, altTest, BmhParser::Resolvable::kOut);
}
if (suffix > '9') {
t.reportError("too many alts");
@@ -130,13 +129,18 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
return result;
}
if (!foundMatch) {
- if (!(def = this->isDefined(t, fullRef,
- BmhParser::Resolvable::kOut != resolvable))) {
- if (!result.size()) {
+ if (!(def = this->isDefined(t, fullRef, resolvable))) {
+ if (BmhParser::Resolvable::kFormula == resolvable) {
+ // TODO: look for looser mapping -- if methods name match, look for
+ // unique mapping based on number of parameters
+ // for now, just look for function name match
+ def = this->isDefined(t, ref, resolvable);
+ }
+ if (!def && !result.size()) {
t.reportError("missing method");
fAddRefFailed = true;
+ return result;
}
- return result;
}
ref = fullRef;
}
@@ -145,6 +149,11 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
add_ref(leadingSpaces, ref, &result);
continue;
}
+ if (!def) {
+ t.reportError("missing method");
+ fAddRefFailed = true;
+ return result;
+ }
result += linkRef(leadingSpaces, def, ref, resolvable);
continue;
}
@@ -156,7 +165,7 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
}
t.next();
ref = string(start, t.fChar - start);
- if (const Definition* def = this->isDefined(t, ref, true)) {
+ if (const Definition* def = this->isDefined(t, ref, BmhParser::Resolvable::kYes)) {
SkASSERT(def->fFiddle.length());
result += linkRef(leadingSpaces, def, ref, resolvable);
continue;
@@ -173,15 +182,15 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
if (BmhParser::Resolvable::kOut != resolvable) {
t.reportError("missed Sk prefixed");
fAddRefFailed = true;
+ return result;
}
- return result;
}
if (!ref.compare(0, 2, "SK")) {
if (BmhParser::Resolvable::kOut != resolvable) {
t.reportError("missed SK prefixed");
fAddRefFailed = true;
+ return result;
}
- return result;
}
if (!isupper(start[0])) {
// TODO:
@@ -209,7 +218,8 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
}
}
}
- if (BmhParser::Resolvable::kOut != resolvable) {
+ if (BmhParser::Resolvable::kOut != resolvable &&
+ BmhParser::Resolvable::kFormula != resolvable) {
t.reportError("missed camelCase");
fAddRefFailed = true;
return result;
@@ -236,7 +246,7 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
if (isupper(t.fChar[1]) && startsSentence) {
TextParser next(t.fFileName, &t.fChar[1], t.fEnd, t.fLineCount);
string nextWord(next.fChar, next.wordEnd() - next.fChar);
- if (this->isDefined(t, nextWord, true)) {
+ if (this->isDefined(t, nextWord, BmhParser::Resolvable::kYes)) {
add_ref(leadingSpaces, ref, &result);
continue;
}
@@ -261,6 +271,8 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
if (BmhParser::Resolvable::kOut != resolvable) {
t.reportError("undefined reference");
fAddRefFailed = true;
+ } else {
+ add_ref(leadingSpaces, ref, &result);
}
}
} while (!t.eof());
@@ -269,25 +281,22 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
-bool MdOut::buildReferences(const char* docDir, const char* mdFileOrPath) {
+bool MdOut::buildReferences(const IncludeParser& includeParser, const char* docDir,
+ const char* mdFileOrPath) {
if (!sk_isdir(mdFileOrPath)) {
- SkString mdFile = SkOSPath::Basename(mdFileOrPath);
- SkString bmhFile = SkOSPath::Join(docDir, mdFile.c_str());
- bmhFile.remove(bmhFile.size() - 3, 3);
- bmhFile += ".bmh";
- SkString mdPath = SkOSPath::Dirname(mdFileOrPath);
- if (!this->buildRefFromFile(bmhFile.c_str(), mdPath.c_str())) {
- SkDebugf("failed to parse %s\n", mdFileOrPath);
- return false;
+ SkDebugf("must pass directory %s\n", mdFileOrPath);
+ SkDebugf("pass -i SkXXX.h to build references for a single include\n");
+ return false;
+ }
+ SkOSFile::Iter it(docDir, ".bmh");
+ for (SkString file; it.next(&file); ) {
+ if (!includeParser.references(file)) {
+ continue;
}
- } else {
- SkOSFile::Iter it(docDir, ".bmh");
- for (SkString file; it.next(&file); ) {
- SkString p = SkOSPath::Join(docDir, file.c_str());
- if (!this->buildRefFromFile(p.c_str(), mdFileOrPath)) {
- SkDebugf("failed to parse %s\n", p.c_str());
- return false;
- }
+ SkString p = SkOSPath::Join(docDir, file.c_str());
+ if (!this->buildRefFromFile(p.c_str(), mdFileOrPath)) {
+ SkDebugf("failed to parse %s\n", p.c_str());
+ return false;
}
}
return true;
@@ -409,7 +418,7 @@ bool MdOut::checkParamReturnBody(const Definition* def) {
if (!islower(descriptionStart[0]) && !isdigit(descriptionStart[0])) {
paramBody.skipToNonAlphaNum();
string ref = string(descriptionStart, paramBody.fChar - descriptionStart);
- if (!this->isDefined(paramBody, ref, true)) {
+ if (!this->isDefined(paramBody, ref, BmhParser::Resolvable::kYes)) {
string errorStr = MarkType::kReturn == def->fMarkType ? "return" : "param";
errorStr += " description must start with lower case";
paramBody.reportError(errorStr.c_str());
@@ -484,7 +493,8 @@ const Definition* MdOut::findParamType() {
SkASSERT(!parser.eof());
string name = string(word, parser.fChar - word);
if (fLastParam->fName == name) {
- const Definition* paramType = this->isDefined(parser, lastFull, false);
+ const Definition* paramType = this->isDefined(parser, lastFull,
+ BmhParser::Resolvable::kOut);
return paramType;
}
if (isupper(name[0])) {
@@ -494,7 +504,8 @@ const Definition* MdOut::findParamType() {
return nullptr;
}
-const Definition* MdOut::isDefined(const TextParser& parser, const string& ref, bool report) {
+const Definition* MdOut::isDefined(const TextParser& parser, const string& ref,
+ BmhParser::Resolvable resolvable) {
auto rootIter = fBmhParser.fClassMap.find(ref);
if (rootIter != fBmhParser.fClassMap.end()) {
return &rootIter->second;
@@ -613,7 +624,8 @@ const Definition* MdOut::isDefined(const TextParser& parser, const string& ref,
return nullptr;
}
} else {
- if (report) {
+ if (BmhParser::Resolvable::kOut != resolvable &&
+ BmhParser::Resolvable::kFormula != resolvable) {
parser.reportError("SK undefined");
fAddRefFailed = true;
}
@@ -643,7 +655,8 @@ const Definition* MdOut::isDefined(const TextParser& parser, const string& ref,
return definition;
}
}
- if (report) {
+ if (BmhParser::Resolvable::kOut != resolvable &&
+ BmhParser::Resolvable::kFormula != resolvable) {
parser.reportError("_ undefined");
fAddRefFailed = true;
}
@@ -797,6 +810,7 @@ void MdOut::markTypeOut(Definition* def) {
FPRINTF("<pre style=\"padding: 1em 1em 1em 1em;"
"width: 62.5em; background-color: #f0f0f0\">");
this->lf(1);
+ fResolveAndIndent = true;
break;
case MarkType::kColumn:
this->writePending();
@@ -889,7 +903,7 @@ void MdOut::markTypeOut(Definition* def) {
if (def->fWrapper.length() > 0) {
FPRINTF("%s", def->fWrapper.c_str());
}
- fRespectLeadingSpace = true;
+ fLiteralAndIndent = true;
}
} break;
case MarkType::kExperimental:
@@ -1107,7 +1121,8 @@ void MdOut::markTypeOut(Definition* def) {
case MarkType::kWidth:
break;
case MarkType::kPhraseDef:
- break;
+ // skip text and children
+ return;
case MarkType::kPhraseRef:
if (fBmhParser.fPhraseMap.end() == fBmhParser.fPhraseMap.find(def->fName)) {
def->reportError<void>("missing phrase definition");
@@ -1139,9 +1154,12 @@ void MdOut::markTypeOut(Definition* def) {
}
break;
case MarkType::kCode:
+ fIndent = 0;
+ this->lf(1);
this->writePending();
FPRINTF("</pre>");
this->lf(2);
+ fResolveAndIndent = false;
break;
case MarkType::kColumn:
if (fInList) {
@@ -1174,7 +1192,7 @@ void MdOut::markTypeOut(Definition* def) {
FPRINTF("</pre>");
}
this->lf(2);
- fRespectLeadingSpace = false;
+ fLiteralAndIndent = false;
break;
case MarkType::kLink:
this->writeString("</a>");
@@ -1317,10 +1335,16 @@ void MdOut::populateTables(const Definition* def) {
}
void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable resolvable) {
- if ((BmhParser::Resolvable::kLiteral == resolvable || fRespectLeadingSpace) && end > start) {
+ if ((BmhParser::Resolvable::kLiteral == resolvable || fLiteralAndIndent ||
+ fResolveAndIndent) && end > start) {
+ int linefeeds = 0;
while ('\n' == *start) {
+ ++linefeeds;
++start;
}
+ if (fResolveAndIndent && linefeeds) {
+ this->lf(linefeeds);
+ }
const char* spaceStart = start;
while (' ' == *start) {
++start;
@@ -1328,6 +1352,8 @@ void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable
if (start > spaceStart) {
fIndent = start - spaceStart;
}
+ }
+ if (BmhParser::Resolvable::kLiteral == resolvable || fLiteralAndIndent) {
this->writeBlockTrim(end - start, start);
if ('\n' == end[-1]) {
this->lf(1);
@@ -1347,14 +1373,20 @@ void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable
trim_end_spaces(resolved);
if (resolved.length()) {
TextParser paragraph(fFileName, &*resolved.begin(), &*resolved.end(), fLineCount);
- TextParser original(fFileName, start, end, fLineCount);
- while (!original.eof() && '\n' == original.peek()) {
- original.next();
- }
- original.skipSpace();
while (!paragraph.eof()) {
+ while ('\n' == paragraph.peek()) {
+ paragraph.next();
+ if (paragraph.eof()) {
+ return;
+ }
+ }
+ const char* lineStart = paragraph.fChar;
paragraph.skipWhiteSpace();
const char* contentStart = paragraph.fChar;
+ if (fResolveAndIndent && contentStart > lineStart) {
+ this->writePending();
+ this->indentToColumn(contentStart - lineStart);
+ }
paragraph.skipToEndBracket('\n');
ptrdiff_t lineLength = paragraph.fChar - contentStart;
if (lineLength) {
@@ -1364,17 +1396,6 @@ void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable
string str(contentStart, lineLength);
this->writeString(str.c_str());
}
-#if 0
- int linefeeds = 0;
- while (lineLength > 0 && '\n' == contentStart[--lineLength]) {
-
- ++linefeeds;
- }
- if (lineLength > 0) {
- this->nl();
- }
- fLinefeeds += linefeeds;
-#endif
if (paragraph.eof()) {
break;
}
@@ -1386,12 +1407,6 @@ void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable
this->lf(linefeeds);
}
}
-#if 0
- while (end > start && end[0] == '\n') {
- FPRINTF("\n");
- --end;
- }
-#endif
}
}
diff --git a/tools/bookmaker/parserCommon.cpp b/tools/bookmaker/parserCommon.cpp
index 2e9ad81e45..072c996df3 100644
--- a/tools/bookmaker/parserCommon.cpp
+++ b/tools/bookmaker/parserCommon.cpp
@@ -14,13 +14,13 @@ static void debug_out(int len, const char* data) {
SkDebugf("%.*s", len, data);
}
-bool ParserCommon::parseFile(const char* fileOrPath, const char* suffix) {
+bool ParserCommon::parseFile(const char* fileOrPath, const char* suffix, OneFile oneFile) {
if (!sk_isdir(fileOrPath)) {
if (!this->parseFromFile(fileOrPath)) {
SkDebugf("failed to parse %s\n", fileOrPath);
return false;
}
- } else {
+ } else if (OneFile::kNo == oneFile) {
SkOSFile::Iter it(fileOrPath, suffix);
for (SkString file; it.next(&file); ) {
SkString p = SkOSPath::Join(fileOrPath, file.c_str());