Generate bookmaker indices

First cut at splitting bookmaker documentation into reference
and overview. Reference starts with a hyperlinked index,
generated from a public include.

This moves towards typing once, minimizing the information
duplicated in the .h file and the .bmh file.

TBR=caryclark@google.com
Docs-Preview: https://skia.org/?cl=154630
Change-Id: I836622db9b1786bd28c0bce2536cd3caef6e5a32
Reviewed-on: https://skia-review.googlesource.com/c/154630
Commit-Queue: Cary Clark <caryclark@skia.org>
Auto-Submit: Cary Clark <caryclark@skia.org>
Reviewed-by: Cary Clark <caryclark@skia.org>
diff --git a/tools/bookmaker/parserCommon.cpp b/tools/bookmaker/parserCommon.cpp
index 20e5604..5500a1b 100644
--- a/tools/bookmaker/parserCommon.cpp
+++ b/tools/bookmaker/parserCommon.cpp
@@ -84,7 +84,7 @@
     if (iter.empty()) {
         return false;
     }
-    for (string file; iter.next(&file); ) {
+    for (string file; iter.next(&file, nullptr); ) {
         SkString p = SkOSPath::Join(iter.baseDir().c_str(), file.c_str());
         const char* hunk = p.c_str();
         if (!this->parseFromFile(hunk)) {
@@ -137,6 +137,35 @@
     return true;
 }
 
+void ParserCommon::stringAppend(string& result, char ch) const {
+    if (fDebugWriteCodeBlock) {
+        SkDebugf("%c", ch);
+    }
+    result += ch;
+}
+
+void ParserCommon::stringAppend(string& result, string str) const {
+    string condense;
+    char last = result.size() ? result.back() : '\n';
+    for (auto c : str) {
+        if (' ' == c && ' ' == last) {
+            continue;
+        }
+        condense += c;
+        if ('\n' != last || ' ' != c) {
+            last = c;
+        }
+    }
+    if (fDebugWriteCodeBlock) {
+        SkDebugf("%s", condense.c_str());
+    }
+    result += condense;
+}
+
+void ParserCommon::stringAppend(string& result, const Definition* def) const {
+    this->stringAppend(result, string(def->fContentStart, def->length()));
+}
+
 bool ParserCommon::writeBlockIndent(int size, const char* data, bool ignoreIdent) {
     bool wroteSomething = false;
     while (size && ' ' >= data[size - 1]) {
@@ -387,8 +416,10 @@
 
 // FIXME: need to compare fBlockName against fFilter
 // need to compare fSuffix against next value returned
-bool StatusIter::next(string* str) {
+bool StatusIter::next(string* strPtr, StatusFilter *filter) {
+    string str;
     JsonStatus* status;
+    StatusFilter blockType = StatusFilter::kCompleted;
     do {
         do {
             if (fStack.empty()) {
@@ -402,7 +433,7 @@
         } while (true);
         if (1 == fStack.size()) {
             do {
-                StatusFilter blockType = StatusFilter::kUnknown;
+                blockType = StatusFilter::kUnknown;
                 for (unsigned index = 0; index < SK_ARRAY_COUNT(block_names); ++index) {
                     if (status->fIter.key().asString() == block_names[index]) {
                         blockType = (StatusFilter) index;
@@ -423,7 +454,8 @@
             JsonStatus block = {
                 *status->fIter,
                 status->fIter->begin(),
-                status->fIter.key().asString()
+                status->fIter.key().asString(),
+                blockType
             };
             fStack.emplace_back(block);
             status = &(&fStack.back())[-1];
@@ -431,9 +463,15 @@
             status = &fStack.back();
             continue;
         }
-        *str = status->fIter->asString();
+        str = status->fIter->asString();
+        if (strPtr) {
+            *strPtr = str;
+        }
+        if (filter) {
+            *filter = status->fStatusFilter;
+        }
         status->fIter++;
-        if (str->length() - strlen(fSuffix) == str->find(fSuffix)) {
+        if (str.length() - strlen(fSuffix) == str.find(fSuffix)) {
             return true;
         }
     } while (true);
@@ -452,7 +490,7 @@
         SkDebugf("file %s:\n", path);
         return this->reportError<bool>("file not parsable");
     }
-    JsonStatus block = { fRoot, fRoot.begin(), "" };
+    JsonStatus block = { fRoot, fRoot.begin(), "", StatusFilter::kUnknown };
     fStack.emplace_back(block);
     return true;
 }