1 /*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "bmhParser.h"
9 #include "fiddleParser.h"
10
11 #include "SkOSFile.h"
12 #include "SkOSPath.h"
13
14 const string kCatalogFileName("catalog.htm");
15
appendFile(string path)16 bool Catalog::appendFile(string path) {
17 FILE* file = fopen(path.c_str(), "r");
18 if (!file) {
19 SkDebugf("could not append %s\n", path.c_str());
20 return false;
21 }
22 fseek(file, 0L, SEEK_END);
23 int sz = (int) ftell(file);
24 rewind(file);
25 char* buffer = new char[sz];
26 memset(buffer, ' ', sz);
27 SkAssertResult(sz == (int)fread(buffer, 1, sz, file));
28 fclose(file);
29 this->writeBlock(sz, buffer);
30 return true;
31 }
32
openCatalog(const char * inDir)33 bool Catalog::openCatalog(const char* inDir) {
34 fDocsDir = inDir;
35 if ('/' != fDocsDir.back()) {
36 fDocsDir += '/';
37 }
38 fOut = fopen(kCatalogFileName.c_str(), "wb");
39 fFullName = kCatalogFileName;
40 if (!fOut) {
41 SkDebugf("could not open output file %s\n", kCatalogFileName.c_str());
42 return false;
43 }
44 fContinuation = false;
45 if (!appendFile(fDocsDir + "catalogHeader.txt")) {
46 return false;
47 }
48 this->lf(1);
49
50 return true;
51 }
52
openStatus(const char * statusFile)53 bool Catalog::openStatus(const char* statusFile) {
54 StatusIter iter(statusFile, ".bmh", StatusFilter::kInProgress);
55 // FIXME: iterate through only chosen files by setting fDocsDir to iter
56 // read one file to find directory
57 if (!iter.next(nullptr, nullptr)) {
58 return false;
59 }
60 return openCatalog(iter.baseDir().c_str());
61 }
62
closeCatalog(const char * outDir)63 bool Catalog::closeCatalog(const char* outDir) {
64 if (fOut) {
65 this->lf(1);
66 this->writeString("}");
67 this->lf(1);
68 if (!appendFile(fDocsDir + "catalogTrailer.txt")) {
69 return false;
70 }
71 this->lf(1);
72 this->writePending();
73 fclose(fOut);
74 string outie = outDir;
75 if ('/' != outie.back()) {
76 outie += '/';
77 }
78 string fullName = outie + kCatalogFileName;
79 if (ParserCommon::WrittenFileDiffers(fullName, kCatalogFileName)) {
80 ParserCommon::CopyToFile(fullName, kCatalogFileName);
81 SkDebugf("wrote %s\n", fullName.c_str());
82 } else {
83 remove(kCatalogFileName.c_str());
84 }
85 fOut = nullptr;
86 }
87 return true;
88 }
89
parseFromFile(const char * path)90 bool Catalog::parseFromFile(const char* path) {
91 if (!INHERITED::parseFromFile(path)) {
92 return false;
93 }
94 fIndent = 4;
95 this->writeString("var text = {");
96 this->lf(1);
97 fTextOut = true;
98 if (!parseFiddles()) {
99 return false;
100 }
101 this->lf(1);
102 this->writeString("}");
103 this->lf(2);
104 this->writeString("var pngs = {");
105 fTextOut = false;
106 fPngOut = true;
107 JsonStatus* status = &fStack.back();
108 status->fIter = status->fObject.begin();
109 fContinuation = false;
110 return parseFiddles();
111 }
112
pngOut(Definition * example)113 bool Catalog::pngOut(Definition* example) {
114 string result;
115 if (!fBmhParser->exampleToScript(example, BmhParser::ExampleOptions::kPng, &result)) {
116 return false;
117 }
118 if (result.length() > 0) {
119 if (fContinuation) {
120 this->writeString(",");
121 this->lf(1);
122 } else {
123 fContinuation = true;
124 }
125 this->writeBlock(result.size(), result.c_str());
126 }
127 return true;
128 }
129
textOut(Definition * def,const char * stdOutStart,const char * stdOutEnd)130 bool Catalog::textOut(Definition* def, const char* stdOutStart,
131 const char* stdOutEnd) {
132 string result;
133 if (!fBmhParser->exampleToScript(def, BmhParser::ExampleOptions::kText, &result)) {
134 return false;
135 }
136 if (result.length() > 0) {
137 if (fContinuation) {
138 this->writeString(",");
139 this->lf(1);
140 } else {
141 fContinuation = true;
142 }
143 fIndent = 8;
144 this->writeBlock(result.size(), result.c_str());
145 this->lf(1);
146 this->writeString("\"stdout\": \"");
147 size_t pos = 0;
148 size_t len = stdOutEnd - stdOutStart;
149 string example;
150 const Definition* stdOut = def->hasChild(MarkType::kStdOut);
151 const Definition* outVolatile = stdOut ? stdOut->hasChild(MarkType::kVolatile) : nullptr;
152 if (outVolatile) {
153 stdOutStart = outVolatile->fContentStart;
154 while ('\n' == stdOutStart[0]) {
155 ++stdOutStart;
156 }
157 len = stdOut->fContentEnd - stdOutStart;
158 }
159 while ((size_t) pos < len) {
160 example += '"' == stdOutStart[pos] ? "\\\"" :
161 '\\' == stdOutStart[pos] ? "\\\\" :
162 '\n' == stdOutStart[pos] ? "\\\\n" :
163 string(&stdOutStart[pos], 1);
164 if (outVolatile && '\n' == stdOutStart[pos]) {
165 ++pos;
166 while ((size_t) pos < len && ' ' == stdOutStart[pos]) {
167 ++pos;
168 }
169 continue;
170 }
171 ++pos;
172 }
173 if (outVolatile) {
174 example += "\\\\n";
175 }
176 this->writeBlock(example.length(), example.c_str());
177 this->writeString("\"");
178 this->lf(1);
179 fIndent = 4;
180 this->writeString("}");
181 }
182 return true;
183 }
184