diff options
Diffstat (limited to 'tools/bookmaker')
-rw-r--r-- | tools/bookmaker/bookmaker.cpp | 391 | ||||
-rw-r--r-- | tools/bookmaker/bookmaker.h | 95 | ||||
-rw-r--r-- | tools/bookmaker/cataloger.cpp | 4 | ||||
-rw-r--r-- | tools/bookmaker/definition.cpp | 254 | ||||
-rw-r--r-- | tools/bookmaker/includeParser.cpp | 22 | ||||
-rw-r--r-- | tools/bookmaker/includeWriter.cpp | 49 | ||||
-rw-r--r-- | tools/bookmaker/mdOut.cpp | 26 |
7 files changed, 505 insertions, 336 deletions
diff --git a/tools/bookmaker/bookmaker.cpp b/tools/bookmaker/bookmaker.cpp index 02dbbc1961..91e4cc2b23 100644 --- a/tools/bookmaker/bookmaker.cpp +++ b/tools/bookmaker/bookmaker.cpp @@ -6,6 +6,7 @@ */ #include "bookmaker.h" +#include "SkOSPath.h" #ifdef SK_BUILD_FOR_WIN #include <Windows.h> @@ -189,7 +190,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy if (!typeNameBuilder.size()) { return this->reportError<bool>("unnamed topic"); } - fTopics.emplace_front(markType, defStart, fLineCount, fParent); + fTopics.emplace_front(markType, defStart, fLineCount, fParent, fMC); RootDefinition* rootDefinition = &fTopics.front(); definition = rootDefinition; definition->fFileName = fFileName; @@ -277,6 +278,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy // may be one-liner case MarkType::kNoExample: case MarkType::kParam: + case MarkType::kPhraseDef: case MarkType::kReturn: case MarkType::kToDo: if (hasEnd) { @@ -289,22 +291,37 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy if (!this->popParentStack(fParent)) { // if not one liner, pop return false; } - if (MarkType::kParam == markType || MarkType::kReturn == markType) { + if (MarkType::kParam == markType || MarkType::kReturn == markType + || MarkType::kPhraseDef == markType) { if (!this->checkParamReturn(definition)) { return false; } } + if (MarkType::kPhraseDef == markType) { + string key = definition->fName; + if (fPhraseMap.end() != fPhraseMap.find(key)) { + this->reportError<bool>("duplicate phrase key"); + } + fPhraseMap[key] = definition; + } } else { - fMarkup.emplace_front(markType, defStart, fLineCount, fParent); + fMarkup.emplace_front(markType, defStart, fLineCount, fParent, fMC); definition = &fMarkup.front(); definition->fName = typeNameBuilder[0]; definition->fFiddle = fParent->fFiddle; definition->fContentStart = fChar; - definition->fContentEnd = this->trimmedBracketEnd(fMC); - this->skipToEndBracket(fMC); + string endBracket; + endBracket += fMC; + endBracket += fMC; + definition->fContentEnd = this->trimmedBracketEnd(endBracket); + this->skipToEndBracket(endBracket.c_str()); SkAssertResult(fMC == this->next()); SkAssertResult(fMC == this->next()); definition->fTerminator = fChar; + TextParser checkForChildren(definition); + if (checkForChildren.strnchr(fMC, definition->fContentEnd)) { + this->reportError<bool>("put ## on separate line"); + } fParent->fChildren.push_back(definition); } break; @@ -334,10 +351,11 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy return this->reportError<bool>("missing example body"); } } - definition->setWrapper(); +// can't do this here; phrase refs may not have been defined yet +// this->setWrapper(definition); } } else { - fMarkup.emplace_front(markType, defStart, fLineCount, fParent); + fMarkup.emplace_front(markType, defStart, fLineCount, fParent, fMC); definition = &fMarkup.front(); definition->fContentStart = fChar; definition->fName = typeNameBuilder[0]; @@ -395,7 +413,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy } else if (!hasEnd && MarkType::kAnchor == markType) { return this->reportError<bool>("anchor line must have end element last"); } - fMarkup.emplace_front(markType, defStart, fLineCount, fParent); + fMarkup.emplace_front(markType, defStart, fLineCount, fParent, fMC); definition = &fMarkup.front(); definition->fName = typeNameBuilder[0]; definition->fFiddle = Definition::NormalizedName(typeNameBuilder[0]); @@ -405,7 +423,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy fParent->fChildren.push_back(definition); if (MarkType::kAnchor == markType) { this->skipToEndBracket(fMC); - fMarkup.emplace_front(MarkType::kLink, fChar, fLineCount, definition); + fMarkup.emplace_front(MarkType::kLink, fChar, fLineCount, definition, fMC); SkAssertResult(fMC == this->next()); this->skipWhiteSpace(); Definition* link = &fMarkup.front(); @@ -437,7 +455,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy if (fMC != this->next() || fMC != this->next()) { return this->reportError<bool>("expected ## to delineate line"); } - fMarkup.emplace_front(MarkType::kText, start, fLineCount, definition); + fMarkup.emplace_front(MarkType::kText, start, fLineCount, definition, fMC); Definition* text = &fMarkup.front(); text->fContentStart = start; text->fContentEnd = end; @@ -690,7 +708,8 @@ bool BmhParser::collectExternals() { const char* wordStart = fChar; this->skipToNonAlphaNum(); if (fChar - wordStart > 0) { - fExternals.emplace_front(MarkType::kExternal, wordStart, fChar, fLineCount, fParent); + fExternals.emplace_front(MarkType::kExternal, wordStart, fChar, fLineCount, fParent, + fMC); RootDefinition* definition = &fExternals.front(); definition->fFileName = fFileName; definition->fName = string(wordStart ,fChar - wordStart); @@ -700,10 +719,10 @@ bool BmhParser::collectExternals() { return true; } -static bool dump_examples(FILE* fiddleOut, const Definition& def, bool* continuation) { +bool BmhParser::dumpExamples(FILE* fiddleOut, Definition& def, bool* continuation) const { if (MarkType::kExample == def.fMarkType) { string result; - if (!def.exampleToScript(&result, Definition::ExampleOptions::kAll)) { + if (!this->exampleToScript(&def, BmhParser::ExampleOptions::kAll, &result)) { return false; } if (result.length() > 0) { @@ -719,7 +738,7 @@ static bool dump_examples(FILE* fiddleOut, const Definition& def, bool* continua return true; } for (auto& child : def.fChildren ) { - if (!dump_examples(fiddleOut, *child, continuation)) { + if (!this->dumpExamples(fiddleOut, *child, continuation)) { return false; } } @@ -738,7 +757,7 @@ bool BmhParser::dumpExamples(const char* fiddleJsonFileName) const { if (topic.second->fParent) { continue; } - dump_examples(fiddleOut, *topic.second, &continuation); + this->dumpExamples(fiddleOut, *topic.second, &continuation); } fprintf(fiddleOut, "\n}\n"); fclose(fiddleOut); @@ -767,6 +786,262 @@ bool BmhParser::endTableColumn(const char* end, const char* terminator) { return true; } +static size_t count_indent(const string& text, size_t test, size_t end) { + size_t result = test; + while (test < end) { + if (' ' != text[test]) { + break; + } + ++test; + } + return test - result; +} + +static void add_code(const string& text, int pos, int end, + size_t outIndent, size_t textIndent, string& example) { + do { + // fix this to move whole paragraph in, out, but preserve doc indent + int nextIndent = count_indent(text, pos, end); + size_t len = text.find('\n', pos); + if (string::npos == len) { + len = end; + } + if ((size_t) (pos + nextIndent) < len) { + size_t indent = outIndent + nextIndent; + SkASSERT(indent >= textIndent); + indent -= textIndent; + for (size_t index = 0; index < indent; ++index) { + example += ' '; + } + pos += nextIndent; + while ((size_t) pos < len) { + example += '"' == text[pos] ? "\\\"" : + '\\' == text[pos] ? "\\\\" : + text.substr(pos, 1); + ++pos; + } + example += "\\n"; + } else { + pos += nextIndent; + } + if ('\n' == text[pos]) { + ++pos; + } + } while (pos < end); +} + +bool BmhParser::exampleToScript(Definition* def, ExampleOptions exampleOptions, + string* result) const { + bool hasFiddle = true; + const Definition* platform = def->hasChild(MarkType::kPlatform); + if (platform) { + TextParser platParse(platform); + hasFiddle = !platParse.strnstr("!fiddle", platParse.fEnd); + } + if (!hasFiddle) { + *result = ""; + return true; + } + string text = this->extractText(def, TrimExtract::kNo); + bool textOut = string::npos != text.find("SkDebugf(") + || string::npos != text.find("dump(") + || string::npos != text.find("dumpHex("); + string heightStr = "256"; + string widthStr = "256"; + string normalizedName(def->fFiddle); + string code; + string imageStr = "0"; + string srgbStr = "false"; + string durationStr = "0"; + for (auto iter : def->fChildren) { + switch (iter->fMarkType) { + case MarkType::kDuration: + durationStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart); + break; + case MarkType::kHeight: + heightStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart); + break; + case MarkType::kWidth: + widthStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart); + break; + case MarkType::kDescription: + // ignore for now + break; + case MarkType::kFunction: { + // emit this, but don't wrap this in draw() + string funcText = this->extractText(&*iter, TrimExtract::kNo); + size_t pos = 0; + while (pos < funcText.length() && ' ' > funcText[pos]) { + ++pos; + } + size_t indent = count_indent(funcText, pos, funcText.length()); + add_code(funcText, pos, funcText.length(), 0, indent, code); + code += "\\n"; + } break; + case MarkType::kComment: + break; + case MarkType::kImage: + imageStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart); + break; + case MarkType::kToDo: + break; + case MarkType::kBug: + case MarkType::kMarkChar: + case MarkType::kPlatform: + case MarkType::kPhraseRef: + // ignore for now + break; + case MarkType::kSet: + if ("sRGB" == string(iter->fContentStart, + iter->fContentEnd - iter->fContentStart)) { + srgbStr = "true"; + } else { + SkASSERT(0); // more work to do + return false; + } + break; + case MarkType::kStdOut: + textOut = true; + break; + default: + SkASSERT(0); // more coding to do + } + } + string animatedStr = "0" != durationStr ? "true" : "false"; + string textOutStr = textOut ? "true" : "false"; + size_t pos = 0; + while (pos < text.length() && ' ' > text[pos]) { + ++pos; + } + size_t end = text.length(); + size_t outIndent = 0; + size_t textIndent = count_indent(text, pos, end); + if ("" == def->fWrapper) { + this->setWrapper(def); + } + if (def->fWrapper.length() > 0) { + code += def->fWrapper; + code += "\\n"; + outIndent = 4; + } + add_code(text, pos, end, outIndent, textIndent, code); + if (def->fWrapper.length() > 0) { + code += "}"; + } + string example = "\"" + normalizedName + "\": {\n"; + size_t nameStart = def->fFileName.find(SkOSPath::SEPARATOR, 0); + SkASSERT(string::npos != nameStart); + string baseFile = def->fFileName.substr(nameStart + 1, def->fFileName.length() - nameStart - 5); + if (ExampleOptions::kText == exampleOptions) { + example += " \"code\": \"" + code + "\",\n"; + example += " \"hash\": \"" + def->fHash + "\",\n"; + example += " \"file\": \"" + baseFile + "\",\n"; + example += " \"name\": \"" + def->fName + "\","; + } else { + example += " \"code\": \"" + code + "\",\n"; + if (ExampleOptions::kPng == exampleOptions) { + example += " \"width\": " + widthStr + ",\n"; + example += " \"height\": " + heightStr + ",\n"; + example += " \"hash\": \"" + def->fHash + "\",\n"; + example += " \"file\": \"" + baseFile + "\",\n"; + example += " \"name\": \"" + def->fName + "\"\n"; + example += "}"; + } else { + example += " \"options\": {\n"; + example += " \"width\": " + widthStr + ",\n"; + example += " \"height\": " + heightStr + ",\n"; + example += " \"source\": " + imageStr + ",\n"; + example += " \"srgb\": " + srgbStr + ",\n"; + example += " \"f16\": false,\n"; + example += " \"textOnly\": " + textOutStr + ",\n"; + example += " \"animated\": " + animatedStr + ",\n"; + example += " \"duration\": " + durationStr + "\n"; + example += " },\n"; + example += " \"fast\": true"; + } + } + *result = example; + return true; +} + +string BmhParser::extractText(const Definition* def, TrimExtract trimExtract) const { + string result; + TextParser parser(def); + auto childIter = def->fChildren.begin(); + while (!parser.eof()) { + const char* end = def->fChildren.end() == childIter ? parser.fEnd : (*childIter)->fStart; + string fragment(parser.fChar, end - parser.fChar); + trim_end(fragment); + if (TrimExtract::kYes == trimExtract) { + trim_start(fragment); + if (result.length()) { + result += '\n'; + result += '\n'; + } + } + if (TrimExtract::kYes == trimExtract || has_nonwhitespace(fragment)) { + result += fragment; + } + parser.skipTo(end); + if (def->fChildren.end() != childIter) { + Definition* child = *childIter; + if (MarkType::kPhraseRef == child->fMarkType) { + auto phraseIter = fPhraseMap.find(child->fName); + if (fPhraseMap.end() == phraseIter) { + return def->reportError<string>("missing phrase definition"); + } + Definition* phrase = phraseIter->second; + // count indent of last line in result + size_t lastLF = result.rfind('\n'); + size_t startPos = string::npos == lastLF ? 0 : lastLF; + size_t lastLen = result.length() - startPos; + size_t indent = count_indent(result, startPos, result.length()) + 4; + string phraseStr = this->extractText(phrase, TrimExtract::kNo); + startPos = 0; + bool firstTime = true; + size_t endPos; + do { + endPos = phraseStr.find('\n', startPos); + size_t len = (string::npos != endPos ? endPos : phraseStr.length()) - startPos; + if (firstTime && lastLen + len + 1 < 100) { // FIXME: make 100 global const or something + result += ' '; + } else { + result += '\n'; + result += string(indent, ' '); + } + firstTime = false; + string tmp = phraseStr.substr(startPos, len); + result += tmp; + startPos = endPos + 1; + } while (string::npos != endPos); + result += '\n'; + } + parser.skipTo(child->fTerminator); + std::advance(childIter, 1); + } + } + return result; +} + +void BmhParser::setWrapper(Definition* def) const { + const char drawWrapper[] = "void draw(SkCanvas* canvas) {"; + const char drawNoCanvas[] = "void draw(SkCanvas* ) {"; + string text = this->extractText(def, TrimExtract::kNo); + size_t nonSpace = 0; + while (nonSpace < text.length() && ' ' >= text[nonSpace]) { + ++nonSpace; + } + bool hasFunc = !text.compare(nonSpace, sizeof(drawWrapper) - 1, drawWrapper); + bool noCanvas = !text.compare(nonSpace, sizeof(drawNoCanvas) - 1, drawNoCanvas); + bool hasCanvas = string::npos != text.find("SkCanvas canvas"); + SkASSERT(!hasFunc || !noCanvas); + bool preprocessor = text[0] == '#'; + bool wrapCode = !hasFunc && !noCanvas && !preprocessor; + if (wrapCode) { + def->fWrapper = hasCanvas ? string(drawNoCanvas) : string(drawWrapper); + } +} + // FIXME: some examples may produce different output on different platforms // if the text output can be different, think of how to author that @@ -812,7 +1087,7 @@ bool BmhParser::findDefinitions() { if (' ' >= fMC) { return this->reportError<bool>("illegal markup character"); } - fMarkup.emplace_front(MarkType::kMarkChar, fChar - 1, fLineCount, fParent); + fMarkup.emplace_front(MarkType::kMarkChar, fChar - 4, fLineCount, fParent, fMC); Definition* markChar = &fMarkup.front(); markChar->fContentStart = fChar - 1; this->skipToEndBracket('\n'); @@ -865,7 +1140,7 @@ bool BmhParser::findDefinitions() { } } else { // one line comment fMarkup.emplace_front(MarkType::kComment, fChar - 1, fLineCount, - fParent); + fParent, fMC); Definition* comment = &fMarkup.front(); comment->fContentStart = fChar - 1; this->skipToEndBracket('\n'); @@ -890,7 +1165,7 @@ bool BmhParser::findDefinitions() { } else if (TableState::kNone == fTableState) { // fixme? no nested tables for now fColStart = fChar - 1; - fMarkup.emplace_front(MarkType::kRow, fColStart, fLineCount, fParent); + fMarkup.emplace_front(MarkType::kRow, fColStart, fLineCount, fParent, fMC); fRow = &fMarkup.front(); fRow->fName = fParent->fName; this->skipWhiteSpace(); @@ -899,7 +1174,7 @@ bool BmhParser::findDefinitions() { fTableState = TableState::kColumnStart; } if (TableState::kColumnStart == fTableState) { - fMarkup.emplace_front(MarkType::kColumn, fColStart, fLineCount, fParent); + fMarkup.emplace_front(MarkType::kColumn, fColStart, fLineCount, fParent, fMC); fWorkingColumn = &fMarkup.front(); fWorkingColumn->fName = fParent->fName; fWorkingColumn->fContentStart = fChar; @@ -907,6 +1182,28 @@ bool BmhParser::findDefinitions() { fTableState = TableState::kColumnEnd; continue; } + } else if (this->peek() >= 'a' && this->peek() <= 'z') { + // expect zero or more letters and underscores (no spaces) then hash + const char* phraseNameStart = fChar; + this->skipPhraseName(); + string phraseKey = string(phraseNameStart, fChar - phraseNameStart); + if (fMC != this->next()) { + return this->reportError<bool>("expect # after phrase-name"); + } + const char* start = phraseNameStart; + SkASSERT('#' == start[-1]); + --start; + if (start > fStart && ' ' >= start[-1]) { + --start; // preserve whether to add whitespace before substitution + } + fMarkup.emplace_front(MarkType::kPhraseRef, start, fLineCount, fParent, fMC); + Definition* markChar = &fMarkup.front(); + markChar->fContentStart = fChar; + this->skipToEndBracket('\n'); + markChar->fContentEnd = fChar; + markChar->fTerminator = fChar; + markChar->fName = phraseKey; + fParent->fChildren.push_back(markChar); } } char nextChar = this->next(); @@ -1316,6 +1613,45 @@ const Definition* BmhParser::parentSpace() const { return parent; } +const char* BmhParser::checkForFullTerminal(const char* end, const Definition* definition) const { + const char* start = end; + while ('\n' != start[0] && start > fStart) { + --start; + } + SkASSERT (start < end); + // if end is preceeeded by \n#MarkType ## backup to there + TextParser parser(fFileName, start, fChar, fLineCount); + parser.skipWhiteSpace(); + if (parser.eof() || fMC != parser.next()) { + return end; + } + const char* markName = fMaps[(int) definition->fMarkType].fName; + if (!parser.skipExact(markName)) { + return end; + } + parser.skipWhiteSpace(); + const char* nameStart = parser.fChar; + if (isupper(nameStart[0])) { + parser.skipToWhiteSpace(); + if (parser.eof()) { + return end; + } + string defName = string(nameStart, parser.fChar - nameStart); + size_t defNamePos = definition->fName.rfind(defName); + if (definition->fName.length() != defNamePos + defName.length()) { + return end; + } + } + parser.skipWhiteSpace(); + if (fMC != parser.next()) { + return end; + } + if (!parser.eof() && fMC != parser.next()) { + return end; + } + return start; +} + bool BmhParser::popParentStack(Definition* definition) { if (!fParent) { return this->reportError<bool>("missing parent"); @@ -1329,7 +1665,19 @@ bool BmhParser::popParentStack(Definition* definition) { if (definition->fContentEnd) { return this->reportError<bool>("definition already ended"); } - definition->fContentEnd = fLine - 1; + // more to figure out to handle table columns, at minimum + const char* end = fChar; + if (fMC != end[0]) { + while (end > definition->fContentStart && ' ' >= end[-1]) { + --end; + } + SkASSERT(&end[-1] >= definition->fContentStart && fMC == end[-1] + && (MarkType::kColumn == definition->fMarkType + || (&end[-2] >= definition->fContentStart && fMC == end[-2]))); + end -= 2; + } + end = checkForFullTerminal(end, definition); + definition->fContentEnd = end; definition->fTerminator = fChar; fParent = definition->fParent; if (!fParent || (MarkType::kTopic == fParent->fMarkType && !fParent->fParent)) { @@ -1629,7 +1977,8 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) { builder = this->typedefName(); break; case MarkType::kParam: - // fixme: expect camelCase + case MarkType::kPhraseDef: + // fixme: expect camelCase for param builder = this->word("", ""); this->skipSpace(); *checkEnd = false; diff --git a/tools/bookmaker/bookmaker.h b/tools/bookmaker/bookmaker.h index 7bb743c9cb..db0d9926db 100644 --- a/tools/bookmaker/bookmaker.h +++ b/tools/bookmaker/bookmaker.h @@ -120,6 +120,8 @@ enum class MarkType { kNoExample, kOutdent, kParam, + kPhraseDef, + kPhraseRef, kPlatform, kPopulate, kPrivate, @@ -504,6 +506,12 @@ public: } } + void skipPhraseName() { + while (fChar < fEnd && (islower(fChar[0]) || '_' == fChar[0])) { + fChar++; + } + } + void skipToSpace() { while (fChar < fEnd && ' ' != fChar[0]) { fChar++; @@ -637,6 +645,17 @@ public: return fChar + index; } + const char* trimmedBracketEnd(string bracket) const { + size_t max = (size_t) (this->lineLength()); + string line(fChar, max); + size_t index = line.find(bracket); + SkASSERT(index < max); + while (index > 0 && ' ' >= fChar[index - 1]) { + --index; + } + return fChar + index; + } + const char* trimmedLineEnd() const { const char* result = this->lineEnd(); while (result > fChar && ' ' >= result[-1]) { @@ -730,17 +749,6 @@ public: kFileType, }; - enum class TrimExtract { - kNo, - kYes - }; - - enum class ExampleOptions { - kText, - kPng, - kAll - }; - enum class MethodType { kNone, kConstructor, @@ -775,13 +783,14 @@ public: Definition() {} - Definition(const char* start, const char* end, int line, Definition* parent) + Definition(const char* start, const char* end, int line, Definition* parent, char mc) : fStart(start) , fContentStart(start) , fContentEnd(end) , fParent(parent) , fLineCount(line) - , fType(Type::kWord) { + , fType(Type::kWord) + , fMC(mc) { if (parent) { SkASSERT(parent->fFileName.length() > 0); fFileName = parent->fFileName; @@ -789,31 +798,31 @@ public: this->setParentIndex(); } - Definition(MarkType markType, const char* start, int line, Definition* parent) - : Definition(markType, start, nullptr, line, parent) { + Definition(MarkType markType, const char* start, int line, Definition* parent, char mc) + : Definition(markType, start, nullptr, line, parent, mc) { } - Definition(MarkType markType, const char* start, const char* end, int line, Definition* parent) - : Definition(start, end, line, parent) { + Definition(MarkType markType, const char* start, const char* end, int line, Definition* parent, char mc) + : Definition(start, end, line, parent, mc) { fMarkType = markType; fType = Type::kMark; } - Definition(Bracket bracket, const char* start, int lineCount, Definition* parent) - : Definition(start, nullptr, lineCount, parent) { + Definition(Bracket bracket, const char* start, int lineCount, Definition* parent, char mc) + : Definition(start, nullptr, lineCount, parent, mc) { fBracket = bracket; fType = Type::kBracket; } Definition(KeyWord keyWord, const char* start, const char* end, int lineCount, - Definition* parent) - : Definition(start, end, lineCount, parent) { + Definition* parent, char mc) + : Definition(start, end, lineCount, parent, mc) { fKeyWord = keyWord; fType = Type::kKeyWord; } - Definition(Punctuation punctuation, const char* start, int lineCount, Definition* parent) - : Definition(start, nullptr, lineCount, parent) { + Definition(Punctuation punctuation, const char* start, int lineCount, Definition* parent, char mc) + : Definition(start, nullptr, lineCount, parent, mc) { fPunctuation = punctuation; fType = Type::kPunctuation; } @@ -845,8 +854,6 @@ public: return nullptr; } - bool exampleToScript(string* result, ExampleOptions ) const; - string extractText(TrimExtract trimExtract) const; string fiddleName() const; const Definition* findClone(string match) const; string formatFunction(Format format) const; @@ -901,8 +908,6 @@ public: fParentIndex = fParent ? (int) fParent->fTokens.size() : -1; } - void setWrapper(); - const Definition* topicParent() const { Definition* test = fParent; while (test) { @@ -936,6 +941,7 @@ public: MethodType fMethodType = MethodType::kNone; Operator fOperator = Operator::kUnknown; Type fType = Type::kNone; + char fMC = '#'; bool fClone = false; bool fCloned = false; bool fDeprecated = false; @@ -958,12 +964,12 @@ public: RootDefinition() { } - RootDefinition(MarkType markType, const char* start, int line, Definition* parent) - : Definition(markType, start, line, parent) { + RootDefinition(MarkType markType, const char* start, int line, Definition* parent, char mc) + : Definition(markType, start, line, parent, mc) { } RootDefinition(MarkType markType, const char* start, const char* end, int line, - Definition* parent) : Definition(markType, start, end, line, parent) { + Definition* parent, char mc) : Definition(markType, start, end, line, parent, mc) { } ~RootDefinition() override { @@ -1205,6 +1211,12 @@ public: kClone, // resolved, output, with references to clones as well }; + enum class ExampleOptions { + kText, + kPng, + kAll + }; + enum class Exemplary { kNo, kYes, @@ -1222,6 +1234,11 @@ public: kYes, }; + enum class TrimExtract { + kNo, + kYes + }; + #define M(mt) (1LL << (int) MarkType::k##mt) #define M_D M(Description) #define M_CS M(Class) | M(Struct) @@ -1287,6 +1304,8 @@ public: , { "NoExample", nullptr, MarkType::kNoExample, R_O, 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) } +, { "", nullptr, MarkType::kPhraseRef, R_Y, E_N, 0 } , { "Platform", nullptr, MarkType::kPlatform, R_N, E_N, M(Example) | M(NoExample) } , { "Populate", nullptr, MarkType::kPopulate, R_N, E_N, M(Subtopic) } , { "Private", nullptr, MarkType::kPrivate, R_N, E_N, 0 } @@ -1333,13 +1352,17 @@ public: const vector<string>& typeNameBuilder, HasTag hasTag); bool checkEndMarker(MarkType markType, string name) const; bool checkExamples() const; + const char* checkForFullTerminal(const char* end, const Definition* ) const; bool checkParamReturn(const Definition* definition) const; + bool dumpExamples(FILE* fiddleOut, Definition& def, bool* continuation) const; bool dumpExamples(const char* fiddleJsonFileName) const; bool childOf(MarkType markType) const; string className(MarkType markType); bool collectExternals(); int endHashCount() const; bool endTableColumn(const char* end, const char* terminator); + bool exampleToScript(Definition*, ExampleOptions, string* result ) const; + string extractText(const Definition* , TrimExtract ) const; RootDefinition* findBmhObject(MarkType markType, const string& typeName) const { auto map = fMaps[(int) markType].fBmh; @@ -1383,6 +1406,7 @@ public: fCheckMethods = false; } + void setWrapper(Definition* def) const; bool skipNoName(); bool skipToDefinitionEnd(MarkType markType); bool skipToString(); @@ -1418,6 +1442,7 @@ public: unordered_map<string, RootDefinition> fTypedefMap; unordered_map<string, Definition*> fTopicMap; unordered_map<string, Definition*> fAliasMap; + unordered_map<string, Definition*> fPhraseMap; RootDefinition* fRoot; Definition* fWorkingColumn; Definition* fRow; @@ -1485,6 +1510,8 @@ public: , { nullptr, MarkType::kNoExample } , { nullptr, MarkType::kOutdent } , { nullptr, MarkType::kParam } + , { nullptr, MarkType::kPhraseDef } + , { nullptr, MarkType::kPhraseRef } , { nullptr, MarkType::kPlatform } , { nullptr, MarkType::kPopulate } , { nullptr, MarkType::kPrivate } @@ -1517,11 +1544,11 @@ public: void addKeyword(KeyWord keyWord); void addPunctuation(Punctuation punctuation) { - fParent->fTokens.emplace_back(punctuation, fChar, fLineCount, fParent); + fParent->fTokens.emplace_back(punctuation, fChar, fLineCount, fParent, '\0'); } void addWord() { - fParent->fTokens.emplace_back(fIncludeWord, fChar, fLineCount, fParent); + fParent->fTokens.emplace_back(fIncludeWord, fChar, fLineCount, fParent, '\0'); fIncludeWord = nullptr; } @@ -1602,7 +1629,7 @@ public: void pushBracket(Bracket bracket) { this->setBracketShortCuts(bracket); - fParent->fTokens.emplace_back(bracket, fChar, fLineCount, fParent); + fParent->fTokens.emplace_back(bracket, fChar, fLineCount, fParent, '\0'); Definition* container = &fParent->fTokens.back(); this->addDefinition(container); } @@ -1889,7 +1916,7 @@ public: void constOut(const Definition* memberStart, const Definition& child, const Definition* bmhConst); - void descriptionOut(const Definition* def, SkipFirstLine ); + void descriptionOut(const Definition* def, SkipFirstLine , Phrase ); void enumHeaderOut(const RootDefinition* root, const Definition& child); void enumMembersOut(const RootDefinition* root, Definition& child); void enumSizeItems(const Definition& child); diff --git a/tools/bookmaker/cataloger.cpp b/tools/bookmaker/cataloger.cpp index b3f578dd71..a564d3ee98 100644 --- a/tools/bookmaker/cataloger.cpp +++ b/tools/bookmaker/cataloger.cpp @@ -103,7 +103,7 @@ bool Catalog::parseFromFile(const char* path) { bool Catalog::pngOut(Definition* example) { string result; - if (!example->exampleToScript(&result, Definition::ExampleOptions::kPng)) { + if (!fBmhParser->exampleToScript(example, BmhParser::ExampleOptions::kPng, &result)) { return false; } if (result.length() > 0) { @@ -121,7 +121,7 @@ bool Catalog::pngOut(Definition* example) { bool Catalog::textOut(Definition* def, const char* stdOutStart, const char* stdOutEnd) { string result; - if (!def->exampleToScript(&result, Definition::ExampleOptions::kText)) { + if (!fBmhParser->exampleToScript(def, BmhParser::ExampleOptions::kText, &result)) { return false; } if (result.length() > 0) { diff --git a/tools/bookmaker/definition.cpp b/tools/bookmaker/definition.cpp index 68e001aebb..14f6daab81 100644 --- a/tools/bookmaker/definition.cpp +++ b/tools/bookmaker/definition.cpp @@ -6,51 +6,6 @@ */ #include "bookmaker.h" -#include "SkOSPath.h" - -static size_t count_indent(const string& text, size_t test, size_t end) { - size_t result = test; - while (test < end) { - if (' ' != text[test]) { - break; - } - ++test; - } - return test - result; -} - -static void add_code(const string& text, int pos, int end, - size_t outIndent, size_t textIndent, string& example) { - do { - // fix this to move whole paragraph in, out, but preserve doc indent - int nextIndent = count_indent(text, pos, end); - size_t len = text.find('\n', pos); - if (string::npos == len) { - len = end; - } - if ((size_t) (pos + nextIndent) < len) { - size_t indent = outIndent + nextIndent; - SkASSERT(indent >= textIndent); - indent -= textIndent; - for (size_t index = 0; index < indent; ++index) { - example += ' '; - } - pos += nextIndent; - while ((size_t) pos < len) { - example += '"' == text[pos] ? "\\\"" : - '\\' == text[pos] ? "\\\\" : - text.substr(pos, 1); - ++pos; - } - example += "\\n"; - } else { - pos += nextIndent; - } - if ('\n' == text[pos]) { - ++pos; - } - } while (pos < end); -} #ifdef CONST #undef CONST @@ -487,215 +442,6 @@ void Definition::setCanonicalFiddle() { fFiddle = Definition::NormalizedName(result); } -void Definition::setWrapper() { - const char drawWrapper[] = "void draw(SkCanvas* canvas) {"; - const char drawNoCanvas[] = "void draw(SkCanvas* ) {"; - string text = this->extractText(Definition::TrimExtract::kNo); - size_t nonSpace = 0; - while (nonSpace < text.length() && ' ' >= text[nonSpace]) { - ++nonSpace; - } - bool hasFunc = !text.compare(nonSpace, sizeof(drawWrapper) - 1, drawWrapper); - bool noCanvas = !text.compare(nonSpace, sizeof(drawNoCanvas) - 1, drawNoCanvas); - bool hasCanvas = string::npos != text.find("SkCanvas canvas"); - SkASSERT(!hasFunc || !noCanvas); - bool preprocessor = text[0] == '#'; - bool wrapCode = !hasFunc && !noCanvas && !preprocessor; - if (wrapCode) { - fWrapper = hasCanvas ? string(drawNoCanvas) : string(drawWrapper); - } -} - -bool Definition::exampleToScript(string* result, ExampleOptions exampleOptions) const { - bool hasFiddle = true; - const Definition* platform = this->hasChild(MarkType::kPlatform); - if (platform) { - TextParser platParse(platform); - hasFiddle = !platParse.strnstr("!fiddle", platParse.fEnd); - } - if (!hasFiddle) { - *result = ""; - return true; - } - string text = this->extractText(Definition::TrimExtract::kNo); - bool textOut = string::npos != text.find("SkDebugf(") - || string::npos != text.find("dump(") - || string::npos != text.find("dumpHex("); - string heightStr = "256"; - string widthStr = "256"; - string normalizedName(fFiddle); - string code; - string imageStr = "0"; - string srgbStr = "false"; - string durationStr = "0"; - for (auto const& iter : fChildren) { - switch (iter->fMarkType) { - case MarkType::kDuration: - durationStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart); - break; - case MarkType::kHeight: - heightStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart); - break; - case MarkType::kWidth: - widthStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart); - break; - case MarkType::kDescription: - // ignore for now - break; - case MarkType::kFunction: { - // emit this, but don't wrap this in draw() - string funcText(iter->fContentStart, iter->fContentEnd - iter->fContentStart); - size_t pos = 0; - while (pos < funcText.length() && ' ' > funcText[pos]) { - ++pos; - } - size_t indent = count_indent(funcText, pos, funcText.length()); - add_code(funcText, pos, funcText.length(), 0, indent, code); - code += "\\n"; - } break; - case MarkType::kComment: - break; - case MarkType::kImage: - imageStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart); - break; - case MarkType::kToDo: - break; - case MarkType::kBug: - case MarkType::kMarkChar: - case MarkType::kPlatform: - // ignore for now - break; - case MarkType::kSet: - if ("sRGB" == string(iter->fContentStart, - iter->fContentEnd - iter->fContentStart)) { - srgbStr = "true"; - } else { - SkASSERT(0); // more work to do - return false; - } - break; - case MarkType::kStdOut: - textOut = true; - break; - default: - SkASSERT(0); // more coding to do - } - } - string animatedStr = "0" != durationStr ? "true" : "false"; - string textOutStr = textOut ? "true" : "false"; - size_t pos = 0; - while (pos < text.length() && ' ' > text[pos]) { - ++pos; - } - size_t end = text.length(); - size_t outIndent = 0; - size_t textIndent = count_indent(text, pos, end); - if (fWrapper.length() > 0) { - code += fWrapper; - code += "\\n"; - outIndent = 4; - } - add_code(text, pos, end, outIndent, textIndent, code); - if (fWrapper.length() > 0) { - code += "}"; - } - string example = "\"" + normalizedName + "\": {\n"; - size_t nameStart = fFileName.find(SkOSPath::SEPARATOR, 0); - SkASSERT(string::npos != nameStart); - string baseFile = fFileName.substr(nameStart + 1, fFileName.length() - nameStart - 5); - if (ExampleOptions::kText == exampleOptions) { - example += " \"code\": \"" + code + "\",\n"; - example += " \"hash\": \"" + fHash + "\",\n"; - example += " \"file\": \"" + baseFile + "\",\n"; - example += " \"name\": \"" + fName + "\","; - } else { - example += " \"code\": \"" + code + "\",\n"; - if (ExampleOptions::kPng == exampleOptions) { - example += " \"width\": " + widthStr + ",\n"; - example += " \"height\": " + heightStr + ",\n"; - example += " \"hash\": \"" + fHash + "\",\n"; - example += " \"file\": \"" + baseFile + "\",\n"; - example += " \"name\": \"" + fName + "\"\n"; - example += "}"; - } else { - example += " \"options\": {\n"; - example += " \"width\": " + widthStr + ",\n"; - example += " \"height\": " + heightStr + ",\n"; - example += " \"source\": " + imageStr + ",\n"; - example += " \"srgb\": " + srgbStr + ",\n"; - example += " \"f16\": false,\n"; - example += " \"textOnly\": " + textOutStr + ",\n"; - example += " \"animated\": " + animatedStr + ",\n"; - example += " \"duration\": " + durationStr + "\n"; - example += " },\n"; - example += " \"fast\": true"; - } - } - *result = example; - return true; -} - -string Definition::extractText(TrimExtract trimExtract) const { - string result; - TextParser parser(fFileName, fContentStart, fContentEnd, fLineCount); - int childIndex = 0; - char mc = '#'; - while (parser.fChar < parser.fEnd) { - if (TrimExtract::kYes == trimExtract && !parser.skipWhiteSpace()) { - break; - } - if (parser.next() == mc) { - if (parser.next() == mc) { - if (parser.next() == mc) { - mc = parser.next(); - } - } else { - // fixme : more work to do if # style comment is in text - // if in method definition, could be alternate method name - --parser.fChar; - if (' ' < parser.fChar[0]) { - if (islower(parser.fChar[0])) { - result += '\n'; - parser.skipLine(); - } else { - SkASSERT(isupper(parser.fChar[0])); - parser.skipTo(fChildren[childIndex]->fTerminator); - if (mc == parser.fChar[0] && mc == parser.fChar[1]) { - parser.next(); - parser.next(); - } - childIndex++; - } - } else { - parser.skipLine(); - } - continue; - } - } else { - --parser.fChar; - } - const char* end = parser.fEnd; - const char* mark = parser.strnchr(mc, end); - if (mark) { - end = mark; - } - string fragment(parser.fChar, end - parser.fChar); - trim_end(fragment); - if (TrimExtract::kYes == trimExtract) { - trim_start(fragment); - if (result.length()) { - result += '\n'; - result += '\n'; - } - } - if (TrimExtract::kYes == trimExtract || has_nonwhitespace(fragment)) { - result += fragment; - } - parser.skipTo(end); - } - return result; -} - static void space_pad(string* str) { size_t len = str->length(); if (len == 0) { diff --git a/tools/bookmaker/includeParser.cpp b/tools/bookmaker/includeParser.cpp index 385b9c92da..07189dcc3f 100644 --- a/tools/bookmaker/includeParser.cpp +++ b/tools/bookmaker/includeParser.cpp @@ -87,7 +87,7 @@ void IncludeParser::ValidateKeyWords() { } void IncludeParser::addKeyword(KeyWord keyWord) { - fParent->fTokens.emplace_back(keyWord, fIncludeWord, fChar, fLineCount, fParent); + fParent->fTokens.emplace_back(keyWord, fIncludeWord, fChar, fLineCount, fParent, '\0'); fIncludeWord = nullptr; if (KeyProperty::kObject == kKeyWords[(int) keyWord].fProperty) { Definition* def = &fParent->fTokens.back(); @@ -1295,7 +1295,7 @@ bool IncludeParser::parseComment(const string& filename, const char* start, cons } const char* lineEnd = parser.trimmedLineEnd(); markupDef->fTokens.emplace_back(MarkType::kComment, parser.fChar, lineEnd, - parser.fLineCount, parent); + parser.fLineCount, parent, '\0'); parser.skipToEndBracket('\n'); } return true; @@ -1338,7 +1338,7 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) { markupChild->fLineCount = child->fLineCount; } else { markupDef->fTokens.emplace_back(MarkType::kEnum, child->fContentStart, child->fContentEnd, - child->fLineCount, markupDef); + child->fLineCount, markupDef, '\0'); markupChild = &markupDef->fTokens.back(); } SkASSERT(KeyWord::kNone == markupChild->fKeyWord); @@ -1385,7 +1385,7 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) { parser.skipToLineStart(); } markupChild->fTokens.emplace_back(MarkType::kComment, start, end, parser.fLineCount, - markupChild); + markupChild, '\0'); comment = &markupChild->fTokens.back(); comment->fTerminator = end; if (!this->parseComment(parser.fFileName, start, end, parser.fLineCount, comment)) { @@ -1439,12 +1439,12 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) { SkASSERT(!parser.eof()); const char* commentEnd = parser.fChar; markupChild->fTokens.emplace_back(MarkType::kComment, commentStart, commentEnd, - parser.fLineCount, markupChild); + parser.fLineCount, markupChild, '\0'); comment = &markupChild->fTokens.back(); comment->fTerminator = commentEnd; } markupChild->fTokens.emplace_back(MarkType::kMember, dataStart, dataEnd, parser.fLineCount, - markupChild); + markupChild, '\0'); Definition* member = &markupChild->fTokens.back(); member->fName = memberName; if (comment) { @@ -1463,7 +1463,7 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) { } SkASSERT(KeyWord::kStatic == outsideMember->fKeyWord); markupChild->fTokens.emplace_back(MarkType::kMember, outsideMember->fContentStart, - outsideMember->fContentEnd, outsideMember->fLineCount, markupChild); + outsideMember->fContentEnd, outsideMember->fLineCount, markupChild, '\0'); Definition* member = &markupChild->fTokens.back(); member->fName = outsideMember->fName; // FIXME: ? add comment as well ? @@ -1503,7 +1503,7 @@ bool IncludeParser::parseInclude(const string& name) { bool IncludeParser::parseMember(Definition* child, Definition* markupDef) { const char* typeStart = child->fChildren[0]->fContentStart; markupDef->fTokens.emplace_back(MarkType::kMember, typeStart, child->fContentStart, - child->fLineCount, markupDef); + child->fLineCount, markupDef, '\0'); Definition* markupChild = &markupDef->fTokens.back(); TextParser nameParser(child); nameParser.skipToNonAlphaNum(); @@ -1534,7 +1534,7 @@ bool IncludeParser::parseMember(Definition* child, Definition* markupDef) { } } markupDef->fTokens.emplace_back(MarkType::kComment, start, end, child->fLineCount, - markupDef); + markupDef, '\0'); Definition* commentChild = &markupDef->fTokens.back(); markupChild->fChildren.emplace_back(commentChild); parser.skipTo(end); @@ -1676,7 +1676,7 @@ bool IncludeParser::parseMethod(Definition* child, Definition* markupDef) { return true; } markupDef->fTokens.emplace_back(MarkType::kMethod, start, end, tokenIter->fLineCount, - markupDef); + markupDef, '\0'); Definition* markupChild = &markupDef->fTokens.back(); // do find instead -- I wonder if there is a way to prevent this in c++ IClassDefinition& classDef = fIClassMap[markupDef->fName]; @@ -1873,7 +1873,7 @@ bool IncludeParser::parseTypedef(Definition* child, Definition* markupDef) { return true; } markupDef->fTokens.emplace_back(MarkType::kTypedef, child->fContentStart, child->fContentEnd, - child->fLineCount, markupDef); + child->fLineCount, markupDef, '\0'); Definition* markupChild = &markupDef->fTokens.back(); markupChild->fName = nameStr; markupChild->fTerminator = markupChild->fContentEnd; diff --git a/tools/bookmaker/includeWriter.cpp b/tools/bookmaker/includeWriter.cpp index 328e9412cb..83895ea78a 100644 --- a/tools/bookmaker/includeWriter.cpp +++ b/tools/bookmaker/includeWriter.cpp @@ -15,13 +15,14 @@ void IncludeWriter::constOut(const Definition* memberStart, const Definition& ch this->lf(2); this->writeCommentHeader(); fIndent += 4; - this->descriptionOut(bmhConst, SkipFirstLine::kYes); + this->descriptionOut(bmhConst, SkipFirstLine::kYes, Phrase::kNo); fIndent -= 4; this->writeCommentTrailer(); fStart = memberStart->fContentStart; } -void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirstLine) { +void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirstLine, + Phrase phrase) { const char* commentStart = def->fContentStart; if (SkipFirstLine::kYes == skipFirstLine) { TextParser parser(def); @@ -99,7 +100,11 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs commentLen = (int) (prop->fContentEnd - commentStart); if (commentLen > 0) { this->writeBlockIndent(commentLen, commentStart); - if ('\n' != commentStart[commentLen - 1] && '\n' == commentStart[commentLen]) { + const char* end = commentStart + commentLen; + while (end > commentStart && ' ' == end[-1]) { + --end; + } + if (end > commentStart && '\n' == end[-1]) { this->lfcr(); } } @@ -175,7 +180,7 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs SkASSERT(MarkType::kColumn == column->fMarkType); this->writeString("-"); this->writeSpace(); - this->descriptionOut(column, SkipFirstLine::kNo); + this->descriptionOut(column, SkipFirstLine::kNo, Phrase::kNo); this->lf(1); } } @@ -185,6 +190,22 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs this->lf(2); } break; + case MarkType::kPhraseRef: { + commentLen = prop->fStart - commentStart; + if (commentLen > 0) { + this->rewriteBlock(commentLen, commentStart, Phrase::kNo); + // ince we don't do line wrapping, always insert LF before phrase + this->lfcr(); // TODO: remove this once rewriteBlock rewraps paragraphs + } + auto iter = fBmhParser->fPhraseMap.find(prop->fName); + if (fBmhParser->fPhraseMap.end() == iter) { + return this->reportError<void>("missing phrase definition"); + } + Definition* phraseDef = iter->second; + this->rewriteBlock(phraseDef->length(), phraseDef->fContentStart, Phrase::kYes); + commentStart = prop->fContentStart; + commentLen = (int) (def->fContentEnd - commentStart); + } break; default: commentLen = (int) (prop->fStart - commentStart); breakOut = true; @@ -195,7 +216,7 @@ void IncludeWriter::descriptionOut(const Definition* def, SkipFirstLine skipFirs } SkASSERT(wroteCode || (commentLen > 0 && commentLen < 1500) || def->fDeprecated); if (commentLen > 0) { - this->rewriteBlock(commentLen, commentStart, Phrase::kNo); + this->rewriteBlock(commentLen, commentStart, phrase); } } @@ -654,7 +675,7 @@ void IncludeWriter::methodOut(const Definition* method, const Definition& child) } this->writeCommentHeader(); fIndent += 4; - this->descriptionOut(method, SkipFirstLine::kNo); + this->descriptionOut(method, SkipFirstLine::kNo, Phrase::kNo); // compute indention column size_t column = 0; bool hasParmReturn = false; @@ -671,8 +692,6 @@ void IncludeWriter::methodOut(const Definition* method, const Definition& child) column += fIndent + sizeof("@return "); int saveIndent = fIndent; for (auto methodPart : method->fChildren) { - const char* partStart = methodPart->fContentStart; - const char* partEnd = methodPart->fContentEnd; if (MarkType::kParam == methodPart->fMarkType) { this->writeString("@param"); this->writeSpace(); @@ -682,18 +701,24 @@ void IncludeWriter::methodOut(const Definition* method, const Definition& child) } else { continue; } + this->indentToColumn(column); + fIndent = column; +#if 0 + const char* partStart = methodPart->fContentStart; + const char* partEnd = methodPart->fContentEnd; while ('\n' == partEnd[-1]) { --partEnd; } while ('#' == partEnd[-1]) { // FIXME: so wrong; should not be before fContentEnd --partEnd; } - this->indentToColumn(column); int partLen = (int) (partEnd - partStart); // FIXME : detect this earlier; assert if #Return is empty SkASSERT(partLen > 0 && partLen < 300); // may assert if param desc is especially long - fIndent = column; this->rewriteBlock(partLen, partStart, Phrase::kYes); +#else + this->descriptionOut(methodPart, SkipFirstLine::kNo, Phrase::kYes); +#endif fIndent = saveIndent; this->lfcr(); } @@ -820,7 +845,7 @@ Definition* IncludeWriter::structMemberOut(const Definition* memberStart, const this->indentToColumn(fStructCommentTab); this->writeString("//!<"); this->writeSpace(); - string extract = commentBlock->extractText(Definition::TrimExtract::kYes); + string extract = fBmhParser->extractText(commentBlock, BmhParser::TrimExtract::kYes); this->rewriteBlock(extract.length(), &extract.front(), Phrase::kNo); } this->lf(2); @@ -833,7 +858,7 @@ void IncludeWriter::structSetMembersShort(const vector<Definition*>& bmhChildren if (MarkType::kMember != memberDef->fMarkType) { continue; } - string extract = memberDef->extractText(Definition::TrimExtract::kYes); + string extract = fBmhParser->extractText(memberDef, BmhParser::TrimExtract::kYes); bool multiline = string::npos != extract.find('\n'); if (multiline) { memberDef->fShort = false; diff --git a/tools/bookmaker/mdOut.cpp b/tools/bookmaker/mdOut.cpp index f74853b470..ff1bff2634 100644 --- a/tools/bookmaker/mdOut.cpp +++ b/tools/bookmaker/mdOut.cpp @@ -166,7 +166,9 @@ string MdOut::addReferences(const char* refStart, const char* refEnd, // look for Sk / sk / SK .. if (!ref.compare(0, 2, "Sk") && ref != "Skew" && ref != "Skews" && ref != "Skip" && ref != "Skips") { - t.reportError("missed Sk prefixed"); + if (BmhParser::Resolvable::kOut != resolvable) { + t.reportError("missed Sk prefixed"); + } return result; } if (!ref.compare(0, 2, "SK")) { @@ -744,7 +746,9 @@ void MdOut::markTypeOut(Definition* def) { const char* textStart = def->fContentStart; if (MarkType::kParam != def->fMarkType && MarkType::kConst != def->fMarkType && (!def->fParent || MarkType::kConst != def->fParent->fMarkType) && - TableState::kNone != fTableState) { + TableState::kNone != fTableState && + (MarkType::kPhraseRef != def->fMarkType || !def->fParent || + MarkType::kParam != def->fParent->fMarkType)) { this->writePending(); FPRINTF("</table>"); this->lf(2); @@ -1088,6 +1092,22 @@ void MdOut::markTypeOut(Definition* def) { break; case MarkType::kWidth: break; + case MarkType::kPhraseDef: + break; + case MarkType::kPhraseRef: + if (fBmhParser.fPhraseMap.end() == fBmhParser.fPhraseMap.find(def->fName)) { + def->reportError<void>("missing phrase definition"); + } else { + if (fColumn && ' ' >= def->fStart[0]) { + this->writeSpace(); + } + Definition* phraseRef = fBmhParser.fPhraseMap.find(def->fName)->second; + this->childrenOut(phraseRef, phraseRef->fContentStart); + if (' ' >= def->fContentStart[0]) { + this->writeSpace(); + } + } + break; default: SkDebugf("fatal error: MarkType::k%s unhandled in %s()\n", fBmhParser.fMaps[(int) def->fMarkType].fName, __func__); @@ -1195,6 +1215,8 @@ void MdOut::markTypeOut(Definition* def) { case MarkType::kTable: this->lf(2); break; + case MarkType::kPhraseDef: + break; case MarkType::kPrivate: break; default: |