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 "bookmaker.h"
9
parseFiddles()10 bool FiddleBase::parseFiddles() {
11 if (!this->skipExact("{\n")) {
12 return false;
13 }
14 while (!this->eof()) {
15 if (!this->skipExact(" \"")) {
16 return false;
17 }
18 const char* nameLoc = fChar;
19 if (!this->skipToEndBracket("\"")) {
20 return false;
21 }
22 string name(nameLoc, fChar - nameLoc);
23 if (!this->skipExact("\": {\n")) {
24 return false;
25 }
26 if (!this->skipExact(" \"compile_errors\": [")) {
27 return false;
28 }
29 if (']' != this->peek()) {
30 // report compiler errors
31 int brackets = 1;
32 do {
33 if ('[' == this->peek()) {
34 ++brackets;
35 } else if (']' == this->peek()) {
36 --brackets;
37 }
38 } while (!this->eof() && this->next() && brackets > 0);
39 this->reportError("fiddle compile error");
40 }
41 if (!this->skipExact("],\n")) {
42 return false;
43 }
44 if (!this->skipExact(" \"runtime_error\": \"")) {
45 return false;
46 }
47 if ('"' != this->peek()) {
48 if (!this->skipToEndBracket('"')) {
49 return false;
50 }
51 this->reportError("fiddle runtime error");
52 }
53 if (!this->skipExact("\",\n")) {
54 return false;
55 }
56 if (!this->skipExact(" \"fiddleHash\": \"")) {
57 return false;
58 }
59 const char* hashStart = fChar;
60 if (!this->skipToEndBracket('"')) {
61 return false;
62 }
63 Definition* example = this->findExample(name);
64 if (!example) {
65 this->reportError("missing example");
66 }
67 string hash(hashStart, fChar - hashStart);
68 if (example) {
69 example->fHash = hash;
70 }
71 if (!this->skipExact("\",\n")) {
72 return false;
73 }
74 if (!this->skipExact(" \"text\": \"")) {
75 return false;
76 }
77 if ('"' != this->peek()) {
78 const char* stdOutStart = fChar;
79 do {
80 if ('\\' == this->peek()) {
81 this->next();
82 } else if ('"' == this->peek()) {
83 break;
84 }
85 } while (!this->eof() && this->next());
86 const char* stdOutEnd = fChar;
87 if (example && fTextOut) {
88 if (!this->textOut(example, stdOutStart, stdOutEnd)) {
89 return false;
90 }
91 }
92 } else {
93 if (example && fPngOut) {
94 if (!this->pngOut(example)) {
95 return false;
96 }
97 }
98 }
99 if (!this->skipExact("\"\n")) {
100 return false;
101 }
102 if (!this->skipExact(" }")) {
103 return false;
104 }
105 if ('\n' == this->peek()) {
106 break;
107 }
108 if (!this->skipExact(",\n")) {
109 return false;
110 }
111 }
112 return true;
113 }
114
textOut(Definition * example,const char * stdOutStart,const char * stdOutEnd)115 bool FiddleParser::textOut(Definition* example, const char* stdOutStart,
116 const char* stdOutEnd) {
117 bool foundStdOut = false;
118 for (auto& textOut : example->fChildren) {
119 if (MarkType::kStdOut != textOut->fMarkType) {
120 continue;
121 }
122 foundStdOut = true;
123 bool foundVolatile = false;
124 for (auto& stdOutChild : textOut->fChildren) {
125 if (MarkType::kVolatile == stdOutChild->fMarkType) {
126 foundVolatile = true;
127 break;
128 }
129 }
130 TextParser bmh(textOut);
131 EscapeParser fiddle(stdOutStart, stdOutEnd);
132 do {
133 bmh.skipWhiteSpace();
134 fiddle.skipWhiteSpace();
135 const char* bmhEnd = bmh.trimmedLineEnd();
136 const char* fiddleEnd = fiddle.trimmedLineEnd();
137 ptrdiff_t bmhLen = bmhEnd - bmh.fChar;
138 SkASSERT(bmhLen > 0);
139 ptrdiff_t fiddleLen = fiddleEnd - fiddle.fChar;
140 SkASSERT(fiddleLen > 0);
141 if (bmhLen != fiddleLen) {
142 if (!foundVolatile) {
143 bmh.reportError("mismatched stdout len\n");
144 }
145 } else if (strncmp(bmh.fChar, fiddle.fChar, fiddleLen)) {
146 if (!foundVolatile) {
147 bmh.reportError("mismatched stdout text\n");
148 }
149 }
150 bmh.skipToLineStart();
151 fiddle.skipToLineStart();
152 } while (!bmh.eof() && !fiddle.eof());
153 if (!foundStdOut) {
154 bmh.reportError("bmh %s missing stdout\n");
155 } else if (!bmh.eof() || !fiddle.eof()) {
156 if (!foundVolatile) {
157 bmh.reportError("%s mismatched stdout eof\n");
158 }
159 }
160 }
161 return true;
162 }
163