blob: 33615433016a98a541021646c82cb39a4b8b3f94 [file] [log] [blame]
Cary Clark8032b982017-07-28 11:04:54 -04001/*
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 "bookmaker.h"
9
10static Definition* find_fiddle(Definition* def, const string& name) {
11 if (MarkType::kExample == def->fMarkType && name == def->fFiddle) {
12 return def;
13 }
14 for (auto& child : def->fChildren) {
15 Definition* result = find_fiddle(child, name);
16 if (result) {
17 return result;
18 }
19 }
20 return nullptr;
21}
22
23Definition* FiddleParser::findExample(const string& name) const {
24 for (const auto& topic : fBmhParser->fTopicMap) {
25 if (topic.second->fParent) {
26 continue;
27 }
28 Definition* def = find_fiddle(topic.second, name);
29 if (def) {
30 return def;
31 }
32 }
33 return nullptr;
34}
35
36bool FiddleParser::parseFiddles() {
37 if (!this->skipExact("{\n")) {
38 return false;
39 }
40 while (!this->eof()) {
41 if (!this->skipExact(" \"")) {
42 return false;
43 }
44 const char* nameLoc = fChar;
45 if (!this->skipToEndBracket("\"")) {
46 return false;
47 }
48 string name(nameLoc, fChar - nameLoc);
49 if (!this->skipExact("\": {\n")) {
50 return false;
51 }
52 if (!this->skipExact(" \"compile_errors\": [")) {
53 return false;
54 }
55 if (']' != this->peek()) {
56 // report compiler errors
57 int brackets = 1;
Cary Clark8032b982017-07-28 11:04:54 -040058 do {
59 if ('[' == this->peek()) {
60 ++brackets;
61 } else if (']' == this->peek()) {
62 --brackets;
63 }
64 } while (!this->eof() && this->next() && brackets > 0);
Cary Clarkd0530ba2017-09-14 11:25:39 -040065 this->reportError("fiddle compile error");
Cary Clark8032b982017-07-28 11:04:54 -040066 }
67 if (!this->skipExact("],\n")) {
68 return false;
69 }
70 if (!this->skipExact(" \"runtime_error\": \"")) {
71 return false;
72 }
73 if ('"' != this->peek()) {
Cary Clark8032b982017-07-28 11:04:54 -040074 if (!this->skipToEndBracket('"')) {
75 return false;
76 }
Cary Clarkd0530ba2017-09-14 11:25:39 -040077 this->reportError("fiddle runtime error");
Cary Clark8032b982017-07-28 11:04:54 -040078 }
79 if (!this->skipExact("\",\n")) {
80 return false;
81 }
82 if (!this->skipExact(" \"fiddleHash\": \"")) {
83 return false;
84 }
85 const char* hashStart = fChar;
86 if (!this->skipToEndBracket('"')) {
87 return false;
88 }
89 Definition* example = this->findExample(name);
90 if (!example) {
Cary Clarkd0530ba2017-09-14 11:25:39 -040091 this->reportError("missing example");
Cary Clark8032b982017-07-28 11:04:54 -040092 }
93 string hash(hashStart, fChar - hashStart);
94 if (example) {
95 example->fHash = hash;
96 }
97 if (!this->skipExact("\",\n")) {
98 return false;
99 }
100 if (!this->skipExact(" \"text\": \"")) {
101 return false;
102 }
103 if ('"' != this->peek()) {
104 const char* stdOutStart = fChar;
105 do {
106 if ('\\' == this->peek()) {
107 this->next();
108 } else if ('"' == this->peek()) {
109 break;
110 }
111 } while (!this->eof() && this->next());
112 const char* stdOutEnd = fChar;
113 if (example) {
114 bool foundStdOut = false;
115 for (auto& textOut : example->fChildren) {
116 if (MarkType::kStdOut != textOut->fMarkType) {
117 continue;
118 }
119 foundStdOut = true;
120 bool foundVolatile = false;
121 for (auto& stdOutChild : textOut->fChildren) {
122 if (MarkType::kVolatile == stdOutChild->fMarkType) {
123 foundVolatile = true;
124 break;
125 }
126 }
127 TextParser bmh(textOut);
128 EscapeParser fiddle(stdOutStart, stdOutEnd);
129 do {
130 bmh.skipWhiteSpace();
131 fiddle.skipWhiteSpace();
132 const char* bmhEnd = bmh.trimmedLineEnd();
133 const char* fiddleEnd = fiddle.trimmedLineEnd();
134 ptrdiff_t bmhLen = bmhEnd - bmh.fChar;
135 SkASSERT(bmhLen > 0);
136 ptrdiff_t fiddleLen = fiddleEnd - fiddle.fChar;
137 SkASSERT(fiddleLen > 0);
138 if (bmhLen != fiddleLen) {
139 if (!foundVolatile) {
Cary Clarkd0530ba2017-09-14 11:25:39 -0400140 bmh.reportError("mismatched stdout len\n");
Cary Clark8032b982017-07-28 11:04:54 -0400141 }
142 } else if (strncmp(bmh.fChar, fiddle.fChar, fiddleLen)) {
143 if (!foundVolatile) {
Cary Clarkd0530ba2017-09-14 11:25:39 -0400144 bmh.reportError("mismatched stdout text\n");
Cary Clark8032b982017-07-28 11:04:54 -0400145 }
146 }
147 bmh.skipToLineStart();
148 fiddle.skipToLineStart();
149 } while (!bmh.eof() && !fiddle.eof());
150 if (!foundStdOut) {
Cary Clarkd0530ba2017-09-14 11:25:39 -0400151 bmh.reportError("bmh %s missing stdout\n");
Cary Clark8032b982017-07-28 11:04:54 -0400152 } else if (!bmh.eof() || !fiddle.eof()) {
153 if (!foundVolatile) {
Cary Clarkd0530ba2017-09-14 11:25:39 -0400154 bmh.reportError("%s mismatched stdout eof\n");
Cary Clark8032b982017-07-28 11:04:54 -0400155 }
156 }
157 }
158 }
159 }
160 if (!this->skipExact("\"\n")) {
161 return false;
162 }
163 if (!this->skipExact(" }")) {
164 return false;
165 }
166 if ('\n' == this->peek()) {
167 break;
168 }
169 if (!this->skipExact(",\n")) {
170 return false;
171 }
172 }
173#if 0
174 // compare the text output with the expected output in the markup tree
175 this->skipToSpace();
176 SkASSERT(' ' == fChar[0]);
177 this->next();
178 const char* nameLoc = fChar;
179 this->skipToNonAlphaNum();
180 const char* nameEnd = fChar;
181 string name(nameLoc, nameEnd - nameLoc);
182 const Definition* example = this->findExample(name);
183 if (!example) {
184 return this->reportError<bool>("missing stdout name");
185 }
186 SkASSERT(':' == fChar[0]);
187 this->next();
188 this->skipSpace();
189 const char* stdOutLoc = fChar;
190 do {
191 this->skipToLineStart();
192 } while (!this->eof() && !this->startsWith("fiddles.htm:"));
193 const char* stdOutEnd = fChar;
194 for (auto& textOut : example->fChildren) {
195 if (MarkType::kStdOut != textOut->fMarkType) {
196 continue;
197 }
198 TextParser bmh(textOut);
199 TextParser fiddle(fFileName, stdOutLoc, stdOutEnd, fLineCount);
200 do {
201 bmh.skipWhiteSpace();
202 fiddle.skipWhiteSpace();
203 const char* bmhEnd = bmh.trimmedLineEnd();
204 const char* fiddleEnd = fiddle.trimmedLineEnd();
205 ptrdiff_t bmhLen = bmhEnd - bmh.fChar;
206 SkASSERT(bmhLen > 0);
207 ptrdiff_t fiddleLen = fiddleEnd - fiddle.fChar;
208 SkASSERT(fiddleLen > 0);
209 if (bmhLen != fiddleLen) {
210 return this->reportError<bool>("mismatched stdout len");
211 }
212 if (strncmp(bmh.fChar, fiddle.fChar, fiddleLen)) {
213 return this->reportError<bool>("mismatched stdout text");
214 }
215 bmh.skipToLineStart();
216 fiddle.skipToLineStart();
217 } while (!bmh.eof() && !fiddle.eof());
218 if (!bmh.eof() || (!fiddle.eof() && !fiddle.startsWith("</pre>"))) {
219 return this->reportError<bool>("mismatched stdout eof");
220 }
221 break;
222 }
223 }
224 }
225#endif
226 return true;
227}