aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/bookmaker/bookmaker.cpp
diff options
context:
space:
mode:
authorGravatar Cary Clark <caryclark@skia.org>2018-05-16 07:07:07 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-05-16 11:35:24 +0000
commit682c58da482155213e8cd2834b57bc6541e510a0 (patch)
tree63d666ea9ec0c2e765557e61e9ec5fc78ad9747f /tools/bookmaker/bookmaker.cpp
parent4c2a34e4804e5affa8447b590578a359bad2caf8 (diff)
Documentation refresh
- add links to types within methods - add check to see that all references and definitions match - add style to tables to make them easier to read - use https everywhere - remove trailing spaces - move overview inside class - split class and struct in summary tables - add missing #Line - clean up SkImageInfo constant documentation - work on SkColor documentation - allow common phrases to take different parameters - add more flexibility to generated tables - tighten token parent requirements - generalize deprecated and example interfaces - detect inner constructors R=caryclark@google.com Docs-Preview: https://skia.org/?cl=121799 Bug: skia:6898 Change-Id: Ia75a23740b80259460916890b310e2a9f024962a Reviewed-on: https://skia-review.googlesource.com/121799 Commit-Queue: Cary Clark <caryclark@skia.org> Auto-Submit: Cary Clark <caryclark@skia.org> Reviewed-by: Cary Clark <caryclark@skia.org>
Diffstat (limited to 'tools/bookmaker/bookmaker.cpp')
-rw-r--r--tools/bookmaker/bookmaker.cpp270
1 files changed, 206 insertions, 64 deletions
diff --git a/tools/bookmaker/bookmaker.cpp b/tools/bookmaker/bookmaker.cpp
index 49e347e6ea..aaf3781974 100644
--- a/tools/bookmaker/bookmaker.cpp
+++ b/tools/bookmaker/bookmaker.cpp
@@ -29,18 +29,14 @@ DEFINE_string2(spellcheck, s, "", "Spell-check [once, all, mispelling]. (Require
DEFINE_bool2(tokens, t, false, "Write bmh from include. (Requires -b -i)");
DEFINE_bool2(crosscheck, x, false, "Check bmh against includes. (Requires -b -i)");
// v is reserved for verbose
+DEFINE_bool2(validate, V, false, "Validate that all anchor references have definitions. (Requires -r)");
DEFINE_bool2(skip, z, false, "Skip degenerate missed in legacy preprocessor.");
-/* recipe for generating timestamps for existing doxygen comments
-find include/core -type f -name '*.h' -print -exec git blame {} \; > ~/all.blame.txt
+/* todos:
+
+add new markup to associate enum SaveLayerFlagsSet with typedef SaveLayerFlags, if needed.
-todos:
-add new markup to associate typedef SaveLayerFlags with Enum so that, for
- documentation purposes, this enum is named rather than anonymous
-check column 1 of subtopic tables to see that they start lowercase and don't have a trailing period
-space table better for Constants
should Return be on same line as 'Return Value'?
-remove anonymous header, e.g. Enum SkPaint::::anonymous_2
#Member lost all formatting
#List needs '# content ##', formatting
consts like enum members need fully qualfied refs to make a valid link
@@ -53,6 +49,45 @@ deprecated methods should be sorted down in md out, and show include "Deprecated
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
+add check to require #Const to contain #Code block if defining const or constexpr (enum consts have
+ #Code blocks inside the #Enum def
+add spelling rule to look for x-bit but allow x bits
+
+There are a number of formatting bugs with ad hoc patches where a substitution doesn't keep
+the space before or after, or the linefeeds before or after. The rules are not very good either.
+Linefeeds in the bmh file are intended to be respected, but #Formula tends to start on a new line
+even if the contents is intended to be inlined. Probably need to require it to be, e.g.:
+
+ array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
+
+where there is always a space between prior words and formula (i.e., between "be" and "(fXCount";
+and, an absense of a space after ## denotes no space between "+ 1)" and ".". These rules preserve
+that # commands are always preceded by a whitespace character. Similarly, #PhraseDef/Ref
+need to be inline or create new paragraphs. #phrase_ref# is sufficiently flexible that it can be
+treated as a word without trailing whitespace, adapting the whitespace of its context. It also must
+always have leading whitespace.
+
+It's awkward that phrase param is a child of the phrase def. Since phrase refs may also be children,
+there is special case code to skip phrase def when looking for additional substitutions in the
+phrase def. Could put it in the token list instead I guess, or make a definition subclass used
+by phrase def with an additional slot...
+
+
+
+#Deprecated soon
+##
+should emit the text "To be deprecated soon." (right now you get just "soon")
+
+SkCanvas_ColorBehavior_kLegacy missing </table> in md out
+
+rearrange const out for md so that const / value / short description comes first in a table,
+followed by more elaborate descriptions, examples, seealso. In md.cpp, look to see if #Subtopic
+has #Const children. If so, generate a summary table first.
+Or, only allow #Line and moderate text description in #Const. Put more verbose text, example,
+seealso, in subsequent #SubTopic. Alpha_Type does this and it looks good.
+
+more spelling: x-value y-value
+
see head of selfCheck.cpp for additional todos
*/
@@ -67,6 +102,8 @@ see head of selfCheck.cpp for additional todos
#define M(mt) (1LL << (int) MarkType::k##mt)
#define M_D M(Description)
#define M_CS M(Class) | M(Struct)
+#define M_MD M(Method) | M(Define)
+#define M_MDCM M_MD | M(Const) | M(Member)
#define M_ST M(Subtopic) | M(Topic)
#define M_CSST M_CS | M_ST
#ifdef M_E
@@ -84,35 +121,35 @@ see head of selfCheck.cpp for additional todos
#define E_N Exemplary::kNo
#define E_O Exemplary::kOptional
+// ToDo: add column to denote which marks are one-liners
BmhParser::MarkProps BmhParser::kMarkProps[] = {
// names without formal definitions (e.g. Column) aren't included
-// fill in other names once they're actually used
{ "", MarkType::kNone, R_Y, E_N, 0 }
, { "A", MarkType::kAnchor, R_N, E_N, 0 }
-, { "Alias", MarkType::kAlias, R_N, E_N, 0 }
-, { "Bug", MarkType::kBug, R_N, E_N, 0 }
-, { "Class", MarkType::kClass, R_Y, E_O, M_CSST | M(Root) }
-, { "Code", MarkType::kCode, R_F, E_N, M_CSST | M_E | M(Method) | M(Define) | M(Typedef) }
+, { "Alias", MarkType::kAlias, R_N, E_N, M_ST | M(Const) }
+, { "Bug", MarkType::kBug, R_N, E_N, M_CSST | M_MDCM | M_E
+ | M(Example) | M(NoExample) }
+, { "Class", MarkType::kClass, R_Y, E_O, M_CSST }
+, { "Code", MarkType::kCode, R_F, E_N, M_CSST | M_E | M_MD | M(Typedef) }
, { "", MarkType::kColumn, R_Y, E_N, M(Row) }
, { "", MarkType::kComment, R_N, E_N, 0 }
, { "Const", MarkType::kConst, R_Y, E_O, M_E | M_ST }
, { "Define", MarkType::kDefine, R_O, E_Y, M_ST }
, { "DefinedBy", MarkType::kDefinedBy, R_N, E_N, M(Method) }
-, { "Deprecated", MarkType::kDeprecated, R_Y, E_N, 0 }
+, { "Deprecated", MarkType::kDeprecated, R_Y, E_N, M_CS | M_MDCM | M_E }
, { "Description", MarkType::kDescription, R_Y, E_N, M(Example) | M(NoExample) }
-, { "Doxygen", MarkType::kDoxygen, R_Y, E_N, 0 }
+, { "Details", MarkType::kDetails, R_N, E_N, M(Const) }
, { "Duration", MarkType::kDuration, R_N, E_N, M(Example) | M(NoExample) }
-, { "Enum", MarkType::kEnum, R_Y, E_O, M_CSST | M(Root) }
-, { "EnumClass", MarkType::kEnumClass, R_Y, E_O, M_CSST | M(Root) }
-, { "Example", MarkType::kExample, R_O, E_N, M_CSST | M_E | M(Method) | M(Const) | M(Define) }
-, { "Experimental", MarkType::kExperimental, R_Y, E_N, 0 }
-, { "External", MarkType::kExternal, R_Y, E_N, M(Root) }
-, { "File", MarkType::kFile, R_N, E_N, M(Track) }
-, { "Formula", MarkType::kFormula, R_F, E_N,
- M(Column) | M_E | M_ST | M(Member) | M(Method) | M_D }
+, { "Enum", MarkType::kEnum, R_Y, E_O, M_CSST }
+, { "EnumClass", MarkType::kEnumClass, R_Y, E_O, M_CSST }
+, { "Example", MarkType::kExample, R_O, E_N, M_CSST | M_E | M_MD }
+, { "Experimental", MarkType::kExperimental, R_Y, E_N, M_CS | M_MDCM | M_E }
+, { "External", MarkType::kExternal, R_Y, E_N, 0 }
+, { "Formula", MarkType::kFormula, R_F, E_N, M(Column) | M(Description)
+ | M_E | M_ST | M_MDCM }
, { "Function", MarkType::kFunction, R_O, E_N, M(Example) | M(NoExample) }
, { "Height", MarkType::kHeight, R_N, E_N, M(Example) | M(NoExample) }
-, { "Illustration", MarkType::kIllustration, R_N, E_N, M(Subtopic) }
+, { "Illustration", MarkType::kIllustration, R_N, E_N, M_CSST | M_MD }
, { "Image", MarkType::kImage, R_N, E_N, M(Example) | M(NoExample) }
, { "In", MarkType::kIn, R_N, E_N, M_CSST | M_E | M(Method) | M(Typedef) }
, { "Legend", MarkType::kLegend, R_Y, E_N, M(Table) }
@@ -123,32 +160,31 @@ BmhParser::MarkProps BmhParser::kMarkProps[] = {
, { "", MarkType::kMarkChar, R_N, E_N, 0 }
, { "Member", MarkType::kMember, R_Y, E_N, M_CSST }
, { "Method", MarkType::kMethod, R_Y, E_Y, M_CSST }
-, { "NoExample", MarkType::kNoExample, R_N, E_N, M_CSST | M_E | M(Method) | M(Const) | M(Define) }
+, { "NoExample", MarkType::kNoExample, R_N, E_N, M_CSST | M_E | M_MD }
+, { "NoJustify", MarkType::kNoJustify, R_N, E_N, M(Const) | M(Member) }
, { "Outdent", MarkType::kOutdent, R_N, E_N, M(Code) }
, { "Param", MarkType::kParam, R_Y, E_N, M(Method) | M(Define) }
, { "PhraseDef", MarkType::kPhraseDef, R_Y, E_N, M(Subtopic) }
-, { "", MarkType::kPhraseRef, R_Y, E_N, 0 }
+, { "", MarkType::kPhraseParam, R_Y, E_N, 0 }
+, { "", MarkType::kPhraseRef, R_N, E_N, 0 }
, { "Platform", MarkType::kPlatform, R_N, E_N, M(Example) | M(NoExample) }
, { "Populate", MarkType::kPopulate, R_N, E_N, M(Subtopic) }
-, { "Private", MarkType::kPrivate, R_N, E_N, 0 }
+, { "Private", MarkType::kPrivate, R_Y, E_N, M_CSST | M_MDCM | M_E }
, { "Return", MarkType::kReturn, R_Y, E_N, M(Method) }
-, { "", MarkType::kRoot, R_Y, E_N, 0 }
, { "", MarkType::kRow, R_Y, E_N, M(Table) | M(List) }
-, { "SeeAlso", MarkType::kSeeAlso, R_C, E_N, M_CSST | M_E | M(Method) | M(Define) | M(Typedef) }
+, { "SeeAlso", MarkType::kSeeAlso, R_C, E_N, M_CSST | M_E | M_MD | M(Typedef) }
, { "Set", MarkType::kSet, R_N, E_N, M(Example) | M(NoExample) }
, { "StdOut", MarkType::kStdOut, R_N, E_N, M(Example) | M(NoExample) }
-, { "Struct", MarkType::kStruct, R_Y, E_O, M(Class) | M(Root) | M_ST }
+, { "Struct", MarkType::kStruct, R_Y, E_O, M(Class) | M_ST }
, { "Substitute", MarkType::kSubstitute, R_N, E_N, M_ST }
, { "Subtopic", MarkType::kSubtopic, R_Y, E_Y, M_CSST }
, { "Table", MarkType::kTable, R_Y, E_N, M(Method) | M_CSST | M_E }
-, { "Template", MarkType::kTemplate, R_Y, E_N, 0 }
+, { "Template", MarkType::kTemplate, R_Y, E_N, M_CSST }
, { "", MarkType::kText, R_N, E_N, 0 }
-, { "Time", MarkType::kTime, R_Y, E_N, M(Track) }
, { "ToDo", MarkType::kToDo, R_N, E_N, 0 }
-, { "Topic", MarkType::kTopic, R_Y, E_Y, M_CS | M(Root) | M(Topic) }
-, { "Track", MarkType::kTrack, R_Y, E_N, M_E | M_ST }
-, { "Typedef", MarkType::kTypedef, R_Y, E_N, M(Class) | M_ST }
-, { "", MarkType::kUnion, R_Y, E_N, 0 }
+, { "Topic", MarkType::kTopic, R_Y, E_Y, 0 }
+, { "Typedef", MarkType::kTypedef, R_Y, E_N, M_CSST | M_E }
+, { "Union", MarkType::kUnion, R_Y, E_N, M_CSST }
, { "Volatile", MarkType::kVolatile, R_N, E_N, M(StdOut) }
, { "Width", MarkType::kWidth, R_N, E_N, M(Example) | M(NoExample) }
};
@@ -163,6 +199,7 @@ BmhParser::MarkProps BmhParser::kMarkProps[] = {
#undef M_CSST
#undef M_ST
#undef M_CS
+#undef M_MCD
#undef M_D
#undef M
@@ -438,18 +475,46 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
fParent->fChildren.push_back(definition);
}
break;
+ } else if (MarkType::kPhraseDef == markType) {
+ bool hasParams = '(' == this->next();
+ fMarkup.emplace_front(markType, defStart, fLineCount, fParent, fMC);
+ definition = &fMarkup.front();
+ definition->fName = typeNameBuilder[0];
+ definition->fFiddle = fParent->fFiddle;
+ definition->fContentStart = fChar;
+ if (hasParams) {
+ char lastChar;
+ do {
+ const char* subEnd = this->anyOf(",)\n");
+ if (!subEnd || '\n' == *subEnd) {
+ return this->reportError<bool>("unexpected phrase list end");
+ }
+ fMarkup.emplace_front(MarkType::kPhraseParam, fChar, fLineCount, fParent,
+ fMC);
+ Definition* phraseParam = &fMarkup.front();
+ phraseParam->fContentStart = fChar;
+ phraseParam->fContentEnd = subEnd;
+ phraseParam->fName = string(fChar, subEnd - fChar);
+ definition->fChildren.push_back(phraseParam);
+ this->skipTo(subEnd);
+ lastChar = this->next();
+ phraseParam->fTerminator = fChar;
+ } while (')' != lastChar);
+ this->skipWhiteSpace();
+ definition->fContentStart = fChar;
+ }
+ this->setAsParent(definition);
+ break;
}
// not one-liners
case MarkType::kCode:
case MarkType::kExample:
- case MarkType::kExperimental:
case MarkType::kFormula:
case MarkType::kFunction:
case MarkType::kLegend:
case MarkType::kList:
case MarkType::kPrivate:
case MarkType::kTable:
- case MarkType::kTrack:
if (hasEnd) {
definition = fParent;
if (markType != fParent->fMarkType) {
@@ -502,21 +567,22 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
case MarkType::kAnchor:
case MarkType::kBug:
case MarkType::kDeprecated:
+ case MarkType::kDetails:
case MarkType::kDuration:
- case MarkType::kFile:
+ case MarkType::kExperimental:
case MarkType::kHeight:
case MarkType::kIllustration:
case MarkType::kImage:
case MarkType::kIn:
case MarkType::kLine:
case MarkType::kLiteral:
+ case MarkType::kNoJustify:
case MarkType::kOutdent:
case MarkType::kPlatform:
case MarkType::kPopulate:
case MarkType::kSeeAlso:
case MarkType::kSet:
case MarkType::kSubstitute:
- case MarkType::kTime:
case MarkType::kVolatile:
case MarkType::kWidth:
// todo : add check disallowing children?
@@ -569,16 +635,37 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
}
fMarkup.emplace_front(MarkType::kText, start, fLineCount, definition, fMC);
Definition* text = &fMarkup.front();
+ if (!islower(start[0]) && (!isdigit(start[0])
+ || MarkType::kConst != definition->fParent->fMarkType)) {
+ return this->reportError<bool>("expect lower case start");
+ }
+ string contents = string(start, end - start);
+ if (string::npos != contents.find('.')) {
+ return this->reportError<bool>("expect phrase, not sentence");
+ }
+ size_t firstSpace = contents.find(' ');
+ if (string::npos == firstSpace || 0 == firstSpace || 's' != start[firstSpace - 1]) {
+ if (MarkType::kMethod == fParent->fMarkType && "experimental" != contents
+ && "incomplete" != contents) {
+ return this->reportError<bool>( "expect phrase in third person present"
+ " tense (1st word should end in 's'");
+ }
+ }
text->fContentStart = start;
text->fContentEnd = end;
text->fTerminator = fChar;
definition->fContentEnd = text->fContentEnd;
definition->fTerminator = fChar;
definition->fChildren.emplace_back(text);
- } else if (MarkType::kDeprecated == markType) {
+ } else if (IncompleteAllowed(markType)) {
this->skipSpace();
fParent->fDeprecated = true;
- fParent->fToBeDeprecated = this->skipExact("soon");
+ fParent->fDetails =
+ this->skipExact("soon") ? Definition::Details::kSoonToBe_Deprecated :
+ this->skipExact("testing") ? Definition::Details::kTestingOnly_Experiment :
+ this->skipExact("do not use") ? Definition::Details::kDoNotUse_Experiement :
+ this->skipExact("not ready") ? Definition::Details::kNotReady_Experiment :
+ Definition::Details::kNone;
this->skipSpace();
if ('\n' != this->peek()) {
return this->reportError<bool>("unexpected text after #Deprecated");
@@ -1210,8 +1297,8 @@ bool BmhParser::findDefinitions() {
const char* defStart = fChar - 1;
MarkType markType = this->getMarkType(MarkLookup::kRequire);
bool hasEnd = this->hasEndToken();
- if (!hasEnd) {
- MarkType parentType = fParent ? fParent->fMarkType : MarkType::kRoot;
+ if (!hasEnd && fParent) {
+ MarkType parentType = fParent->fMarkType;
uint64_t parentMask = kMarkProps[(int) markType].fParentMask;
if (parentMask && !(parentMask & (1LL << (int) parentType))) {
return this->reportError<bool>("invalid parent");
@@ -1298,8 +1385,24 @@ bool BmhParser::findDefinitions() {
const char* phraseNameStart = fChar;
this->skipPhraseName();
string phraseKey = string(phraseNameStart, fChar - phraseNameStart);
- if (fMC != this->next()) {
- return this->reportError<bool>("expect # after phrase-name");
+ char delimiter = this->next();
+ vector<string> params;
+ vector<const char*> paramsLoc;
+ if (fMC != delimiter) {
+ if ('(' != delimiter) {
+ return this->reportError<bool>("expect # after phrase name");
+ }
+ // phrase may take comma delimited parameter list
+ do {
+ const char* subEnd = this->anyOf(",)\n");
+ if (!subEnd || '\n' == *subEnd) {
+ return this->reportError<bool>("unexpected phrase list end");
+ }
+ params.push_back(string(fChar, subEnd - fChar));
+ paramsLoc.push_back(fChar);
+ this->skipTo(subEnd);
+
+ } while (')' != this->next());
}
const char* start = phraseNameStart;
SkASSERT('#' == start[-1]);
@@ -1309,12 +1412,24 @@ bool BmhParser::findDefinitions() {
}
fMarkup.emplace_front(MarkType::kPhraseRef, start, fLineCount, fParent, fMC);
Definition* markChar = &fMarkup.front();
+ this->skipExact("#");
markChar->fContentStart = fChar;
- this->skipToEndBracket('\n');
markChar->fContentEnd = fChar;
markChar->fTerminator = fChar;
markChar->fName = phraseKey;
fParent->fChildren.push_back(markChar);
+ int paramLocIndex = 0;
+ for (auto param : params) {
+ const char* paramLoc = paramsLoc[paramLocIndex++];
+ fMarkup.emplace_front(MarkType::kPhraseParam, paramLoc, fLineCount, fParent,
+ fMC);
+ Definition* phraseParam = &fMarkup.front();
+ phraseParam->fContentStart = paramLoc;
+ phraseParam->fContentEnd = paramLoc + param.length();
+ phraseParam->fTerminator = paramLoc + param.length();
+ phraseParam->fName = param;
+ markChar->fChildren.push_back(phraseParam);
+ }
}
}
char nextChar = this->next();
@@ -1384,13 +1499,14 @@ bool HackParser::hackFiles() {
SkASSERT(!root->fParent);
fStart = root->fStart;
fChar = fStart;
- fClassesAndStructs = nullptr;
+ fClasses = nullptr;
fConstants = nullptr;
fConstructors = nullptr;
fMemberFunctions = nullptr;
fMembers = nullptr;
fOperators = nullptr;
fRelatedFunctions = nullptr;
+ fStructs = nullptr;
this->topicIter(root);
fprintf(fOut, "%.*s", (int) (fEnd - fChar), fChar);
fclose(fOut);
@@ -1442,31 +1558,35 @@ string HackParser::searchTable(const Definition* tableHolder, const Definition*
// returns true if topic has method
void HackParser::topicIter(const Definition* topic) {
- if (string::npos != topic->fName.find(MdOut::kClassesAndStructs)) {
- SkASSERT(!fClassesAndStructs);
- fClassesAndStructs = topic;
+ if (string::npos != topic->fName.find(SubtopicKeys::kClasses)) {
+ SkASSERT(!fClasses);
+ fClasses = topic;
+ }
+ if (string::npos != topic->fName.find(SubtopicKeys::kStructs)) {
+ SkASSERT(!fStructs);
+ fStructs = topic;
}
- if (string::npos != topic->fName.find(MdOut::kConstants)) {
+ if (string::npos != topic->fName.find(SubtopicKeys::kConstants)) {
SkASSERT(!fConstants);
fConstants = topic;
}
- if (string::npos != topic->fName.find(MdOut::kConstructors)) {
+ if (string::npos != topic->fName.find(SubtopicKeys::kConstructors)) {
SkASSERT(!fConstructors);
fConstructors = topic;
}
- if (string::npos != topic->fName.find(MdOut::kMemberFunctions)) {
+ if (string::npos != topic->fName.find(SubtopicKeys::kMemberFunctions)) {
SkASSERT(!fMemberFunctions);
fMemberFunctions = topic;
}
- if (string::npos != topic->fName.find(MdOut::kMembers)) {
+ if (string::npos != topic->fName.find(SubtopicKeys::kMembers)) {
SkASSERT(!fMembers);
fMembers = topic;
}
- if (string::npos != topic->fName.find(MdOut::kOperators)) {
+ if (string::npos != topic->fName.find(SubtopicKeys::kOperators)) {
SkASSERT(!fOperators);
fOperators = topic;
}
- if (string::npos != topic->fName.find(MdOut::kRelatedFunctions)) {
+ if (string::npos != topic->fName.find(SubtopicKeys::kRelatedFunctions)) {
SkASSERT(!fRelatedFunctions);
fRelatedFunctions = topic;
}
@@ -1539,8 +1659,11 @@ void HackParser::topicIter(const Definition* topic) {
this->topicIter(child);
break;
case MarkType::kStruct:
+ this->addOneLiner(fStructs, child, hasLine, false);
+ this->topicIter(child);
+ break;
case MarkType::kClass:
- this->addOneLiner(fClassesAndStructs, child, hasLine, false);
+ this->addOneLiner(fClasses, child, hasLine, false);
this->topicIter(child);
break;
case MarkType::kEnum:
@@ -1822,6 +1945,7 @@ void TextParser::reportError(const char* errorStr) const {
}
void TextParser::reportWarning(const char* errorStr) const {
+ SkASSERT(fLine < fEnd);
TextParser err(fFileName, fLine, fEnd, fLineCount);
size_t lineLen = this->lineLength();
ptrdiff_t spaces = fChar - fLine;
@@ -1892,7 +2016,13 @@ string TextParser::typedefName() {
do {
this->skipToWhiteSpace();
if (fChar < end && isspace(fChar[0])) {
+ const char* whiteStart = fChar;
this->skipWhiteSpace();
+ // FIXME: test should be for fMC
+ if ('#' == fChar[0]) {
+ end = whiteStart;
+ break;
+ }
lastWord = fChar;
} else {
break;
@@ -2051,8 +2181,6 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) {
break;
case MarkType::kCode:
case MarkType::kDescription:
- case MarkType::kDoxygen:
- case MarkType::kExperimental:
case MarkType::kExternal:
case MarkType::kFormula:
case MarkType::kFunction:
@@ -2060,7 +2188,6 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) {
case MarkType::kList:
case MarkType::kNoExample:
case MarkType::kPrivate:
- case MarkType::kTrack:
this->skipNoName();
break;
case MarkType::kLine:
@@ -2071,13 +2198,15 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) {
case MarkType::kBug: // fixme: expect number
case MarkType::kDefinedBy:
case MarkType::kDeprecated:
+ case MarkType::kDetails:
case MarkType::kDuration:
- case MarkType::kFile:
+ case MarkType::kExperimental:
case MarkType::kHeight:
case MarkType::kIllustration:
case MarkType::kImage:
case MarkType::kIn:
case MarkType::kLiteral:
+ case MarkType::kNoJustify:
case MarkType::kOutdent:
case MarkType::kPlatform:
case MarkType::kPopulate:
@@ -2085,7 +2214,6 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) {
case MarkType::kSeeAlso:
case MarkType::kSet:
case MarkType::kSubstitute:
- case MarkType::kTime:
case MarkType::kToDo:
case MarkType::kVolatile:
case MarkType::kWidth:
@@ -2104,12 +2232,22 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) {
builder = this->typedefName();
break;
case MarkType::kParam:
- case MarkType::kPhraseDef:
// fixme: expect camelCase for param
builder = this->word("", "");
this->skipSpace();
*checkEnd = false;
break;
+ case MarkType::kPhraseDef: {
+ const char* nameEnd = this->anyOf("(\n");
+ builder = string(fChar, nameEnd - fChar);
+ this->skipLower();
+ if (fChar != nameEnd) {
+ this->reportError("expect lower case only");
+ break;
+ }
+ this->skipTo(nameEnd);
+ *checkEnd = false;
+ } break;
case MarkType::kTable:
this->skipNoName();
break; // unnamed
@@ -2516,6 +2654,7 @@ int main(int argc, char** const argv) {
}
MdOut mdOut(bmhParser);
mdOut.fDebugOut = FLAGS_stdout;
+ mdOut.fValidate = FLAGS_validate;
if (!FLAGS_bmh.isEmpty() && mdOut.buildReferences(includeParser,
FLAGS_bmh[0], FLAGS_ref[0])) {
bmhParser.fWroteOut = true;
@@ -2523,6 +2662,9 @@ int main(int argc, char** const argv) {
if (!FLAGS_status.isEmpty() && mdOut.buildStatus(FLAGS_status[0], FLAGS_ref[0])) {
bmhParser.fWroteOut = true;
}
+ if (FLAGS_validate) {
+ mdOut.checkAnchors();
+ }
}
if (!done && !FLAGS_spellcheck.isEmpty() && FLAGS_examples.isEmpty()) {
if (!FLAGS_bmh.isEmpty()) {