aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/bookmaker/bookmaker.cpp2
-rw-r--r--tools/bookmaker/bookmaker.h13
-rw-r--r--tools/bookmaker/includeParser.cpp97
-rw-r--r--tools/bookmaker/includeWriter.cpp32
-rw-r--r--tools/bookmaker/mdOut.cpp191
-rw-r--r--tools/bookmaker/parserCommon.cpp46
6 files changed, 281 insertions, 100 deletions
diff --git a/tools/bookmaker/bookmaker.cpp b/tools/bookmaker/bookmaker.cpp
index b7aa044885..eb1ce1e366 100644
--- a/tools/bookmaker/bookmaker.cpp
+++ b/tools/bookmaker/bookmaker.cpp
@@ -16,7 +16,7 @@ DEFINE_string2(include, i, "", "Path to a *.h file or a directory.");
DEFINE_bool2(hack, k, false, "Do a find/replace hack to update all *.bmh files. (Requires -b)");
DEFINE_bool2(stdout, o, false, "Write file out to standard out.");
DEFINE_bool2(populate, p, false, "Populate include from bmh. (Requires -b -i)");
-DEFINE_string2(ref, r, "", "Resolve refs and write bmh_*.md files to path. (Requires -b -f)");
+DEFINE_string2(ref, r, "", "Resolve refs and write *.md files to path. (Requires -b -f)");
DEFINE_string2(spellcheck, s, "", "Spell-check [once, all, mispelling]. (Requires -b)");
DEFINE_bool2(tokens, t, false, "Write bmh from include. (Requires -b -i)");
DEFINE_bool2(crosscheck, x, false, "Check bmh against includes. (Requires -b -i)");
diff --git a/tools/bookmaker/bookmaker.h b/tools/bookmaker/bookmaker.h
index f309d795c9..792f7d9249 100644
--- a/tools/bookmaker/bookmaker.h
+++ b/tools/bookmaker/bookmaker.h
@@ -1041,6 +1041,8 @@ public:
fParent = fParent->fParent;
}
+ const char* ReadToBuffer(string filename, int* size);
+
virtual void reset() = 0;
void resetCommon() {
@@ -1104,6 +1106,7 @@ public:
this->writeString(str.c_str());
}
+ bool writtenFileDiffers(string filename, string readname);
unordered_map<string, sk_sp<SkData>> fRawData;
unordered_map<string, vector<char>> fLFOnly;
@@ -1195,7 +1198,7 @@ public:
// names without formal definitions (e.g. Column) aren't included
// fill in other names once they're actually used
{ "", nullptr, MarkType::kNone, R_Y, E_N, 0 }
-, { "A", nullptr, MarkType::kAnchor, R_Y, E_N, 0 }
+, { "A", nullptr, MarkType::kAnchor, R_N, E_N, 0 }
, { "Alias", nullptr, MarkType::kAlias, R_N, E_N, 0 }
, { "Bug", nullptr, MarkType::kBug, R_N, E_N, 0 }
, { "Class", &fClassMap, MarkType::kClass, R_Y, E_O, M_CSST | M(Root) }
@@ -1556,6 +1559,7 @@ public:
fInFunction = false;
fInString = false;
fFailed = false;
+ fPriorEnum = nullptr;
}
void setBracketShortCuts(Bracket bracket) {
@@ -1724,6 +1728,8 @@ protected:
Definition* fRootTopic;
Definition* fInBrace;
Definition* fLastObject;
+ Definition* fPriorEnum;
+ int fPriorIndex;
const char* fIncludeWord;
char fPrev;
bool fInChar;
@@ -1837,7 +1843,6 @@ public:
void structOut(const Definition* root, const Definition& child,
const char* commentStart, const char* commentEnd);
void structSizeMembers(const Definition& child);
-
private:
BmhParser* fBmhParser;
Definition* fDeferComment;
@@ -1966,8 +1971,8 @@ public:
this->reset();
}
- bool buildReferences(const char* path, const char* outDir);
- bool buildStatus(const char* path, const char* outDir);
+ bool buildReferences(const char* docDir, const char* mdOutDirOrFile);
+ bool buildStatus(const char* docDir, const char* mdOutDir);
private:
enum class TableState {
kNone,
diff --git a/tools/bookmaker/includeParser.cpp b/tools/bookmaker/includeParser.cpp
index 363aacc650..fa5ad325fd 100644
--- a/tools/bookmaker/includeParser.cpp
+++ b/tools/bookmaker/includeParser.cpp
@@ -449,6 +449,8 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
}
}
}
+ int crossChecks = 0;
+ string firstCheck;
for (auto& classMapper : fIClassMap) {
string className = classMapper.first;
auto finder = bmhParser.fClassMap.find(className);
@@ -460,7 +462,19 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
SkDebugf("some struct elements not found; struct finding in includeParser is missing\n");
fFailed = true;
}
- SkDebugf("cross-checked %s\n", className.c_str());
+ if (crossChecks) {
+ SkDebugf(".");
+ } else {
+ SkDebugf("cross-check");
+ firstCheck = className;
+ }
+ ++crossChecks;
+ }
+ if (crossChecks) {
+ if (1 == crossChecks) {
+ SkDebugf("%s", firstCheck.c_str());
+ }
+ SkDebugf("\n");
}
bmhParser.fWroteOut = true;
return !fFailed;
@@ -1338,22 +1352,21 @@ bool IncludeParser::parseEnum(Definition* child, Definition* markupDef) {
}
markupChild->fChildren.push_back(member);
} while (true);
- for (auto count : child->fChildren) {
- if (Definition::Type::kBracket == count->fType) {
+ for (auto outsideMember : child->fChildren) {
+ if (Definition::Type::kBracket == outsideMember->fType) {
continue;
}
- SkASSERT(Definition::Type::kKeyWord == count->fType);
- if (KeyWord::kClass == count->fKeyWord) {
+ SkASSERT(Definition::Type::kKeyWord == outsideMember->fType);
+ if (KeyWord::kClass == outsideMember->fKeyWord) {
continue;
}
- SkASSERT(KeyWord::kStatic == count->fKeyWord);
- markupChild->fTokens.emplace_back(MarkType::kMember, count->fContentStart,
- count->fContentEnd, count->fLineCount, markupChild);
+ SkASSERT(KeyWord::kStatic == outsideMember->fKeyWord);
+ markupChild->fTokens.emplace_back(MarkType::kMember, outsideMember->fContentStart,
+ outsideMember->fContentEnd, outsideMember->fLineCount, markupChild);
Definition* member = &markupChild->fTokens.back();
- member->fName = count->fName;
+ member->fName = outsideMember->fName;
// FIXME: ? add comment as well ?
markupChild->fChildren.push_back(member);
- break;
}
IClassDefinition& classDef = fIClassMap[markupDef->fName];
SkASSERT(classDef.fStart);
@@ -1493,9 +1506,6 @@ bool IncludeParser::parseMethod(Definition* child, Definition* markupDef) {
}
tokenIter->fName = nameStr;
tokenIter->fMarkType = MarkType::kMethod;
- if (string::npos != nameStr.find("defined")) {
- SkDebugf("");
- }
tokenIter->fPrivate = string::npos != nameStr.find("::");
auto testIter = child->fParent->fTokens.begin();
SkASSERT(child->fParentIndex > 0);
@@ -2036,6 +2046,7 @@ bool IncludeParser::parseChar() {
fInEnum = false;
}
this->popObject();
+ fPriorEnum = nullptr;
} else if (Definition::Type::kBracket == fParent->fType
&& fParent->fParent && Definition::Type::kKeyWord == fParent->fParent->fType
&& KeyWord::kStruct == fParent->fParent->fKeyWord) {
@@ -2069,27 +2080,31 @@ bool IncludeParser::parseChar() {
for (auto nameType = baseIter; nameType != namedIter; ++nameType) {
member->fChildren.push_back(&*nameType);
}
-
}
+ fPriorEnum = nullptr;
} else if (fParent->fChildren.size() > 0) {
auto lastIter = fParent->fChildren.end();
- Definition* priorEnum;
- while (fParent->fChildren.begin() != lastIter) {
- std::advance(lastIter, -1);
- priorEnum = *lastIter;
- if (Definition::Type::kBracket != priorEnum->fType ||
- (Bracket::kSlashSlash != priorEnum->fBracket
- && Bracket::kSlashStar != priorEnum->fBracket)) {
- break;
+ Definition* priorEnum = fPriorEnum;
+ fPriorEnum = nullptr;
+ if (!priorEnum) {
+ while (fParent->fChildren.begin() != lastIter) {
+ std::advance(lastIter, -1);
+ priorEnum = *lastIter;
+ if (Definition::Type::kBracket != priorEnum->fType ||
+ (Bracket::kSlashSlash != priorEnum->fBracket
+ && Bracket::kSlashStar != priorEnum->fBracket)) {
+ break;
+ }
}
+ fPriorIndex = priorEnum->fParentIndex;
}
if (Definition::Type::kKeyWord == priorEnum->fType
&& KeyWord::kEnum == priorEnum->fKeyWord) {
auto tokenWalker = fParent->fTokens.begin();
- std::advance(tokenWalker, priorEnum->fParentIndex);
- SkASSERT(KeyWord::kEnum == tokenWalker->fKeyWord);
+ std::advance(tokenWalker, fPriorIndex);
while (tokenWalker != fParent->fTokens.end()) {
std::advance(tokenWalker, 1);
+ ++fPriorIndex;
if (Punctuation::kSemicolon == tokenWalker->fPunctuation) {
break;
}
@@ -2103,6 +2118,7 @@ bool IncludeParser::parseChar() {
break;
}
}
+ auto saveTokenWalker = tokenWalker;
Definition* start = &*tokenWalker;
bool foundExpected = true;
for (KeyWord expected : {KeyWord::kStatic, KeyWord::kConstExpr, KeyWord::kInt}){
@@ -2116,6 +2132,36 @@ bool IncludeParser::parseChar() {
}
std::advance(tokenWalker, 1);
}
+ if (!foundExpected) {
+ foundExpected = true;
+ tokenWalker = saveTokenWalker;
+ for (KeyWord expected : {KeyWord::kStatic, KeyWord::kConst, KeyWord::kNone}){
+ const Definition* test = &*tokenWalker;
+ if (expected != test->fKeyWord) {
+ foundExpected = false;
+ break;
+ }
+ if (tokenWalker == fParent->fTokens.end()) {
+ break;
+ }
+ if (KeyWord::kNone != expected) {
+ std::advance(tokenWalker, 1);
+ }
+ }
+ if (foundExpected) {
+ auto nameToken = priorEnum->fTokens.begin();
+ string enumName = string(nameToken->fContentStart,
+ nameToken->fContentEnd - nameToken->fContentStart);
+ const Definition* test = &*tokenWalker;
+ string constType = string(test->fContentStart,
+ test->fContentEnd - test->fContentStart);
+ if (enumName != constType) {
+ foundExpected = false;
+ } else {
+ std::advance(tokenWalker, 1);
+ }
+ }
+ }
if (foundExpected && tokenWalker != fParent->fTokens.end()) {
const char* nameStart = tokenWalker->fStart;
std::advance(tokenWalker, 1);
@@ -2125,7 +2171,8 @@ bool IncludeParser::parseChar() {
start->fName = string(nameStart, tp.fChar - nameStart);
start->fContentEnd = fChar;
priorEnum->fChildren.emplace_back(start);
- }
+ fPriorEnum = priorEnum;
+ }
}
}
}
diff --git a/tools/bookmaker/includeWriter.cpp b/tools/bookmaker/includeWriter.cpp
index c34fc9391f..463ac92c91 100644
--- a/tools/bookmaker/includeWriter.cpp
+++ b/tools/bookmaker/includeWriter.cpp
@@ -486,7 +486,7 @@ void IncludeWriter::enumSizeItems(const Definition& child) {
int longestValue = 0;
int valueLen = 0;
const char* lastEnd = nullptr;
- SkASSERT(child.fChildren.size() == 1 || child.fChildren.size() == 2);
+// SkASSERT(child.fChildren.size() == 1 || child.fChildren.size() == 2);
auto brace = child.fChildren[0];
if (KeyWord::kClass == brace->fKeyWord) {
brace = brace->fChildren[0];
@@ -585,6 +585,9 @@ void IncludeWriter::enumSizeItems(const Definition& child) {
// walk children and output complete method doxygen description
void IncludeWriter::methodOut(const Definition* method, const Definition& child) {
+ if (string::npos != method->fName.find("validate")) {
+ SkDebugf("");
+ }
if (fPendingMethod) {
fIndent -= 4;
fPendingMethod = false;
@@ -1076,12 +1079,22 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
const char* bodyEnd = fDeferComment ? fDeferComment->fContentStart - 1 :
fAttrDeprecated ? fAttrDeprecated->fContentStart - 1 :
child.fContentStart;
+ if (Definition::Type::kBracket == def->fType && Bracket::kDebugCode == def->fBracket) {
+ auto tokenIter = def->fParent->fTokens.begin();
+ std::advance(tokenIter, def->fParentIndex - 1);
+ Definition* prior = &*tokenIter;
+ if (Definition::Type::kBracket == def->fType &&
+ Bracket::kSlashStar == prior->fBracket) {
+ bodyEnd = prior->fContentStart - 1;
+ }
+ }
// FIXME: roll end-trimming into writeBlockTrim call
while (fStart < bodyEnd && ' ' >= bodyEnd[-1]) {
--bodyEnd;
}
int blockSize = (int) (bodyEnd - fStart);
if (blockSize) {
+ string debugstr(fStart, blockSize);
this->writeBlock(blockSize, fStart);
}
startDef = &child;
@@ -1445,7 +1458,22 @@ bool IncludeWriter::populate(BmhParser& bmhParser) {
this->lfcr();
this->writePending();
fclose(fOut);
- SkDebugf("wrote %s\n", fileName.c_str());
+ fflush(fOut);
+ size_t slash = fFileName.find_last_of('/');
+ if (string::npos == slash) {
+ slash = 0;
+ }
+ size_t back = fFileName.find_last_of('\\');
+ if (string::npos == back) {
+ back = 0;
+ }
+ string dir = fFileName.substr(0, SkTMax(slash, back) + 1);
+ string readname = dir + fileName;
+ if (this->writtenFileDiffers(fileName, readname)) {
+ SkDebugf("wrote updated %s\n", fileName.c_str());
+ } else {
+ remove(fileName.c_str());
+ }
}
return allPassed;
}
diff --git a/tools/bookmaker/mdOut.cpp b/tools/bookmaker/mdOut.cpp
index d6069e4b3a..0443199155 100644
--- a/tools/bookmaker/mdOut.cpp
+++ b/tools/bookmaker/mdOut.cpp
@@ -10,6 +10,12 @@
#include "SkOSFile.h"
#include "SkOSPath.h"
+#define FPRINTF(...) \
+ if (fDebugOut) { \
+ SkDebugf(__VA_ARGS__); \
+ } \
+ fprintf(fOut, __VA_ARGS__)
+
static void add_ref(const string& leadingSpaces, const string& ref, string* result) {
*result += leadingSpaces + ref;
}
@@ -65,7 +71,11 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
}
t.skipToMethodEnd();
if (base == t.fChar) {
- break;
+ if (!t.eof() && '~' == base[0] && !isalnum(base[1])) {
+ t.next();
+ } else {
+ break;
+ }
}
if (start >= t.fChar) {
continue;
@@ -76,6 +86,10 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
ref = string(start, t.fChar - start);
if (const Definition* def = this->isDefined(t, ref,
BmhParser::Resolvable::kOut != resolvable)) {
+ if (MarkType::kExternal == def->fMarkType) {
+ add_ref(leadingSpaces, ref, &result);
+ continue;
+ }
SkASSERT(def->fFiddle.length());
if (!t.eof() && '(' == t.peek() && t.strnchr(')', t.fEnd)) {
if (!t.skipToEndBracket(')')) {
@@ -237,16 +251,21 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
return result;
}
-bool MdOut::buildReferences(const char* fileOrPath, const char* outDir) {
- if (!sk_isdir(fileOrPath)) {
- if (!this->buildRefFromFile(fileOrPath, outDir)) {
- SkDebugf("failed to parse %s\n", fileOrPath);
+bool MdOut::buildReferences(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;
}
} else {
- SkOSFile::Iter it(fileOrPath, ".bmh");
+ SkOSFile::Iter it(docDir, ".bmh");
for (SkString file; it.next(&file); ) {
- SkString p = SkOSPath::Join(fileOrPath, file.c_str());
+ SkString p = SkOSPath::Join(docDir, file.c_str());
const char* hunk = p.c_str();
if (!SkStrEndsWith(hunk, ".bmh")) {
continue;
@@ -254,7 +273,7 @@ bool MdOut::buildReferences(const char* fileOrPath, const char* outDir) {
if (SkStrEndsWith(hunk, "markup.bmh")) { // don't look inside this for now
continue;
}
- if (!this->buildRefFromFile(hunk, outDir)) {
+ if (!this->buildRefFromFile(hunk, mdFileOrPath)) {
SkDebugf("failed to parse %s\n", hunk);
return false;
}
@@ -318,7 +337,7 @@ bool MdOut::buildRefFromFile(const char* name, const char* outDir) {
fullName += '/';
}
fullName += filename;
- fOut = fopen(fullName.c_str(), "wb");
+ fOut = fopen(filename.c_str(), "wb");
if (!fOut) {
SkDebugf("could not open output file %s\n", fullName.c_str());
return false;
@@ -328,16 +347,26 @@ bool MdOut::buildRefFromFile(const char* name, const char* outDir) {
header.replace(underscorePos, 1, " ");
}
SkASSERT(string::npos == header.find('_'));
- fprintf(fOut, "%s", header.c_str());
+ FPRINTF("%s", header.c_str());
this->lfAlways(1);
- fprintf(fOut, "===");
+ FPRINTF("===");
}
this->markTypeOut(topicDef);
}
if (fOut) {
this->writePending();
fclose(fOut);
- SkDebugf("wrote %s\n", fullName.c_str());
+ fflush(fOut);
+ if (this->writtenFileDiffers(filename, fullName)) {
+ fOut = fopen(fullName.c_str(), "wb");
+ int writtenSize;
+ const char* written = ReadToBuffer(filename, &writtenSize);
+ fwrite(written, 1, writtenSize, fOut);
+ fclose(fOut);
+ fflush(fOut);
+ SkDebugf("wrote updated %s\n", fullName.c_str());
+ }
+ remove(filename.c_str());
fOut = nullptr;
}
return true;
@@ -642,35 +671,46 @@ void MdOut::markTypeOut(Definition* def) {
(!def->fParent || MarkType::kConst != def->fParent->fMarkType) &&
TableState::kNone != fTableState) {
this->writePending();
- fprintf(fOut, "</table>");
+ FPRINTF("</table>");
this->lf(2);
fTableState = TableState::kNone;
}
switch (def->fMarkType) {
case MarkType::kAlias:
break;
- case MarkType::kAnchor:
- break;
+ case MarkType::kAnchor: {
+ if (fColumn > 0) {
+ this->writeSpace();
+ }
+ this->writePending();
+ TextParser parser(def);
+ const char* start = parser.fChar;
+ parser.skipToEndBracket(" # ");
+ string anchorText(start, parser.fChar - start);
+ parser.skipExact(" # ");
+ string anchorLink(parser.fChar, parser.fEnd - parser.fChar);
+ FPRINTF("<a href=\"%s\">%s", anchorLink.c_str(), anchorText.c_str());
+ } break;
case MarkType::kBug:
break;
case MarkType::kClass:
this->mdHeaderOut(1);
- fprintf(fOut, "<a name=\"%s\"></a> Class %s", this->linkName(def).c_str(),
+ FPRINTF("<a name=\"%s\"></a> Class %s", this->linkName(def).c_str(),
def->fName.c_str());
this->lf(1);
break;
case MarkType::kCode:
this->lfAlways(2);
- fprintf(fOut, "<pre style=\"padding: 1em 1em 1em 1em;"
+ FPRINTF("<pre style=\"padding: 1em 1em 1em 1em;"
"width: 62.5em; background-color: #f0f0f0\">");
this->lf(1);
break;
case MarkType::kColumn:
this->writePending();
if (fInList) {
- fprintf(fOut, " <td>");
+ FPRINTF(" <td>");
} else {
- fprintf(fOut, "| ");
+ FPRINTF("| ");
}
break;
case MarkType::kComment:
@@ -678,7 +718,7 @@ void MdOut::markTypeOut(Definition* def) {
case MarkType::kConst: {
if (TableState::kNone == fTableState) {
this->mdHeaderOut(3);
- fprintf(fOut, "Constants\n"
+ FPRINTF("Constants\n"
"\n"
"<table>");
fTableState = TableState::kRow;
@@ -686,19 +726,19 @@ void MdOut::markTypeOut(Definition* def) {
}
if (TableState::kRow == fTableState) {
this->writePending();
- fprintf(fOut, " <tr>");
+ FPRINTF(" <tr>");
this->lf(1);
fTableState = TableState::kColumn;
}
this->writePending();
- fprintf(fOut, " <td><a name=\"%s\"> <code><strong>%s </strong></code> </a></td>",
+ FPRINTF(" <td><a name=\"%s\"> <code><strong>%s </strong></code> </a></td>",
def->fFiddle.c_str(), def->fName.c_str());
const char* lineEnd = strchr(textStart, '\n');
SkASSERT(lineEnd < def->fTerminator);
SkASSERT(lineEnd > textStart);
SkASSERT((int) (lineEnd - textStart) == lineEnd - textStart);
- fprintf(fOut, "<td>%.*s</td>", (int) (lineEnd - textStart), textStart);
- fprintf(fOut, "<td>");
+ FPRINTF("<td>%.*s</td>", (int) (lineEnd - textStart), textStart);
+ FPRINTF("<td>");
textStart = lineEnd;
} break;
case MarkType::kDefine:
@@ -710,21 +750,21 @@ void MdOut::markTypeOut(Definition* def) {
case MarkType::kDescription:
fInDescription = true;
this->writePending();
- fprintf(fOut, "<div>");
+ FPRINTF("<div>");
break;
case MarkType::kDoxygen:
break;
case MarkType::kEnum:
case MarkType::kEnumClass:
this->mdHeaderOut(2);
- fprintf(fOut, "<a name=\"%s\"></a> Enum %s", def->fFiddle.c_str(), def->fName.c_str());
+ FPRINTF("<a name=\"%s\"></a> Enum %s", def->fFiddle.c_str(), def->fName.c_str());
this->lf(2);
break;
case MarkType::kError:
break;
case MarkType::kExample: {
this->mdHeaderOut(3);
- fprintf(fOut, "Example\n"
+ FPRINTF("Example\n"
"\n");
fHasFiddle = true;
bool showGpu = false;
@@ -740,21 +780,21 @@ void MdOut::markTypeOut(Definition* def) {
}
if (fHasFiddle && !def->hasChild(MarkType::kError)) {
SkASSERT(def->fHash.length() > 0);
- fprintf(fOut, "<div><fiddle-embed name=\"%s\"", def->fHash.c_str());
+ FPRINTF("<div><fiddle-embed name=\"%s\"", def->fHash.c_str());
if (showGpu) {
- fprintf(fOut, " gpu=\"true\"");
+ FPRINTF(" gpu=\"true\"");
if (gpuAndCpu) {
- fprintf(fOut, " cpu=\"true\"");
+ FPRINTF(" cpu=\"true\"");
}
}
- fprintf(fOut, ">");
+ FPRINTF(">");
} else {
SkASSERT(def->fHash.length() == 0);
- fprintf(fOut, "<pre style=\"padding: 1em 1em 1em 1em; font-size: 13px"
+ FPRINTF("<pre style=\"padding: 1em 1em 1em 1em; font-size: 13px"
" width: 62.5em; background-color: #f0f0f0\">");
this->lfAlways(1);
if (def->fWrapper.length() > 0) {
- fprintf(fOut, "%s", def->fWrapper.c_str());
+ FPRINTF("%s", def->fWrapper.c_str());
}
fRespectLeadingSpace = true;
}
@@ -780,7 +820,7 @@ void MdOut::markTypeOut(Definition* def) {
case MarkType::kList:
fInList = true;
this->lfAlways(2);
- fprintf(fOut, "<table>");
+ FPRINTF("<table>");
this->lf(1);
break;
case MarkType::kLiteral:
@@ -794,7 +834,7 @@ void MdOut::markTypeOut(Definition* def) {
tp.skipWhiteSpace();
const char* end = tp.trimmedBracketEnd('\n');
this->lfAlways(2);
- fprintf(fOut, "<a name=\"%s\"> <code><strong>%.*s</strong></code> </a>",
+ FPRINTF("<a name=\"%s\"> <code><strong>%.*s</strong></code> </a>",
def->fFiddle.c_str(), (int) (end - tp.fChar), tp.fChar);
this->lf(2);
} break;
@@ -804,9 +844,9 @@ void MdOut::markTypeOut(Definition* def) {
if (!def->isClone()) {
this->lfAlways(2);
- fprintf(fOut, "<a name=\"%s\"></a>", def->fFiddle.c_str());
+ FPRINTF("<a name=\"%s\"></a>", def->fFiddle.c_str());
this->mdHeaderOutLF(2, 1);
- fprintf(fOut, "%s", method_name.c_str());
+ FPRINTF("%s", method_name.c_str());
this->lf(2);
}
@@ -814,7 +854,7 @@ void MdOut::markTypeOut(Definition* def) {
// TODO: 50em below should match limit = 80 in formatFunction()
this->writePending();
string preformattedStr = preformat(formattedStr);
- fprintf(fOut, "<pre style=\"padding: 1em 1em 1em 1em;"
+ FPRINTF("<pre style=\"padding: 1em 1em 1em 1em;"
"width: 62.5em; background-color: #f0f0f0\">\n"
"%s\n"
"</pre>", preformattedStr.c_str());
@@ -838,7 +878,7 @@ void MdOut::markTypeOut(Definition* def) {
fTableState = TableState::kRow;
}
if (TableState::kRow == fTableState) {
- fprintf(fOut, " <tr>");
+ FPRINTF(" <tr>");
this->lf(1);
fTableState = TableState::kColumn;
}
@@ -866,7 +906,7 @@ void MdOut::markTypeOut(Definition* def) {
break;
case MarkType::kReturn:
this->mdHeaderOut(3);
- fprintf(fOut, "Return Value");
+ FPRINTF("Return Value");
if (!this->checkParamReturnBody(def)) {
return;
}
@@ -874,13 +914,13 @@ void MdOut::markTypeOut(Definition* def) {
break;
case MarkType::kRow:
if (fInList) {
- fprintf(fOut, " <tr>");
+ FPRINTF(" <tr>");
this->lf(1);
}
break;
case MarkType::kSeeAlso:
this->mdHeaderOut(3);
- fprintf(fOut, "See Also");
+ FPRINTF("See Also");
this->lf(2);
break;
case MarkType::kSet:
@@ -896,23 +936,23 @@ void MdOut::markTypeOut(Definition* def) {
code.skipSpace();
while (!code.eof()) {
const char* end = code.trimmedLineEnd();
- fprintf(fOut, "%.*s\n", (int) (end - code.fChar), code.fChar);
+ FPRINTF("%.*s\n", (int) (end - code.fChar), code.fChar);
code.skipToLineStart();
}
- fprintf(fOut, "~~~~");
+ FPRINTF("~~~~");
this->lf(2);
} break;
case MarkType::kStruct:
fRoot = def->asRoot();
this->mdHeaderOut(1);
- fprintf(fOut, "<a name=\"%s\"></a> Struct %s", def->fFiddle.c_str(), def->fName.c_str());
+ FPRINTF("<a name=\"%s\"></a> Struct %s", def->fFiddle.c_str(), def->fName.c_str());
this->lf(1);
break;
case MarkType::kSubstitute:
break;
case MarkType::kSubtopic:
this->mdHeaderOut(2);
- fprintf(fOut, "<a name=\"%s\"></a> %s", def->fName.c_str(), printable.c_str());
+ FPRINTF("<a name=\"%s\"></a> %s", def->fName.c_str(), printable.c_str());
this->lf(2);
break;
case MarkType::kTable:
@@ -928,7 +968,7 @@ void MdOut::markTypeOut(Definition* def) {
break;
case MarkType::kTopic:
this->mdHeaderOut(1);
- fprintf(fOut, "<a name=\"%s\"></a> %s", this->linkName(def).c_str(),
+ FPRINTF("<a name=\"%s\"></a> %s", this->linkName(def).c_str(),
printable.c_str());
this->lf(1);
break;
@@ -951,23 +991,28 @@ void MdOut::markTypeOut(Definition* def) {
}
this->childrenOut(def, textStart);
switch (def->fMarkType) { // post child work, at least for tables
+ case MarkType::kAnchor:
+ if (fColumn > 0) {
+ this->writeSpace();
+ }
+ break;
case MarkType::kCode:
this->writePending();
- fprintf(fOut, "</pre>");
+ FPRINTF("</pre>");
this->lf(2);
break;
case MarkType::kColumn:
if (fInList) {
this->writePending();
- fprintf(fOut, "</td>");
+ FPRINTF("</td>");
this->lf(1);
} else {
- fprintf(fOut, " ");
+ FPRINTF(" ");
}
break;
case MarkType::kDescription:
this->writePending();
- fprintf(fOut, "</div>");
+ FPRINTF("</div>");
fInDescription = false;
break;
case MarkType::kEnum:
@@ -977,22 +1022,26 @@ void MdOut::markTypeOut(Definition* def) {
case MarkType::kExample:
this->writePending();
if (fHasFiddle) {
- fprintf(fOut, "</fiddle-embed></div>");
+ FPRINTF("</fiddle-embed></div>");
} else {
this->lfAlways(1);
if (def->fWrapper.length() > 0) {
- fprintf(fOut, "}");
+ FPRINTF("}");
this->lfAlways(1);
}
- fprintf(fOut, "</pre>");
+ FPRINTF("</pre>");
}
this->lf(2);
fRespectLeadingSpace = false;
break;
+ case MarkType::kLink:
+ this->writeString("</a>");
+ this->writeSpace();
+ break;
case MarkType::kList:
fInList = false;
this->writePending();
- fprintf(fOut, "</table>");
+ FPRINTF("</table>");
this->lf(2);
break;
case MarkType::kLegend: {
@@ -1003,15 +1052,15 @@ void MdOut::markTypeOut(Definition* def) {
SkASSERT(columnCount > 0);
this->writePending();
for (size_t index = 0; index < columnCount; ++index) {
- fprintf(fOut, "| --- ");
+ FPRINTF("| --- ");
}
- fprintf(fOut, " |");
+ FPRINTF(" |");
this->lf(1);
} break;
case MarkType::kMethod:
fMethod = nullptr;
this->lfAlways(2);
- fprintf(fOut, "---");
+ FPRINTF("---");
this->lf(2);
break;
case MarkType::kConst:
@@ -1019,8 +1068,8 @@ void MdOut::markTypeOut(Definition* def) {
SkASSERT(TableState::kColumn == fTableState);
fTableState = TableState::kRow;
this->writePending();
- fprintf(fOut, "</td>\n");
- fprintf(fOut, " </tr>");
+ FPRINTF("</td>\n");
+ FPRINTF(" </tr>");
this->lf(1);
break;
case MarkType::kReturn:
@@ -1029,9 +1078,9 @@ void MdOut::markTypeOut(Definition* def) {
break;
case MarkType::kRow:
if (fInList) {
- fprintf(fOut, " </tr>");
+ FPRINTF(" </tr>");
} else {
- fprintf(fOut, "|");
+ FPRINTF("|");
}
this->lf(1);
break;
@@ -1051,9 +1100,9 @@ void MdOut::markTypeOut(Definition* def) {
void MdOut::mdHeaderOutLF(int depth, int lf) {
this->lfAlways(lf);
for (int index = 0; index < depth; ++index) {
- fprintf(fOut, "#");
+ FPRINTF("#");
}
- fprintf(fOut, " ");
+ FPRINTF(" ");
}
void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable resolvable) {
@@ -1098,22 +1147,28 @@ void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable
paragraph.skipToEndBracket('\n');
ptrdiff_t lineLength = paragraph.fChar - contentStart;
if (lineLength) {
- this->writePending();
- fprintf(fOut, "%.*s", (int) lineLength, contentStart);
+ while (lineLength && contentStart[lineLength - 1] <= ' ') {
+ --lineLength;
+ }
+ 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;
}
if ('\n' == paragraph.next()) {
- linefeeds = 1;
+ int linefeeds = 1;
if (!paragraph.eof() && '\n' == paragraph.peek()) {
linefeeds = 2;
}
@@ -1122,7 +1177,7 @@ void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable
}
#if 0
while (end > start && end[0] == '\n') {
- fprintf(fOut, "\n");
+ FPRINTF("\n");
--end;
}
#endif
diff --git a/tools/bookmaker/parserCommon.cpp b/tools/bookmaker/parserCommon.cpp
index af1031ac43..cfd42f700f 100644
--- a/tools/bookmaker/parserCommon.cpp
+++ b/tools/bookmaker/parserCommon.cpp
@@ -224,6 +224,52 @@ void ParserCommon::writeString(const char* str) {
fMaxLF = 2;
}
+const char* ParserCommon::ReadToBuffer(string filename, int* size) {
+ FILE* file = fopen(filename.c_str(), "rb");
+ if (!file) {
+ return nullptr;
+ }
+ fseek(file, 0L, SEEK_END);
+ *size = (int) ftell(file);
+ rewind(file);
+ char* buffer = new char[*size];
+ memset(buffer, ' ', *size);
+ SkAssertResult(*size == (int)fread(buffer, 1, *size, file));
+ fclose(file);
+ fflush(file);
+ return buffer;
+}
+
+bool ParserCommon::writtenFileDiffers(string filename, string readname) {
+ int writtenSize, readSize;
+ const char* written = ReadToBuffer(filename, &writtenSize);
+ if (!written) {
+ return true;
+ }
+ const char* read = ReadToBuffer(readname, &readSize);
+ if (!read) {
+ delete[] written;
+ return true;
+ }
+#if 0 // enable for debugging this
+ int smaller = SkTMin(writtenSize, readSize);
+ for (int index = 0; index < smaller; ++index) {
+ if (written[index] != read[index]) {
+ SkDebugf("%.*s\n", 40, &written[index]);
+ SkDebugf("%.*s\n", 40, &read[index]);
+ break;
+ }
+ }
+#endif
+ if (readSize != writtenSize) {
+ return true;
+ }
+ bool result = !!memcmp(written, read, writtenSize);
+ delete[] written;
+ delete[] read;
+ return result;
+}
+
StatusIter::StatusIter(const char* statusFile, const char* suffix, StatusFilter filter)
: fSuffix(suffix)
, fFilter(filter) {