2017-07-28 15:04:54 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2017 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2018-11-01 13:29:36 +00:00
|
|
|
#include "bmhParser.h"
|
|
|
|
#include "fiddleParser.h"
|
2017-07-28 15:04:54 +00:00
|
|
|
|
2018-09-14 13:12:38 +00:00
|
|
|
// could make this more elaborate and look up the example definition in the bmh file;
|
|
|
|
// see if a simpler hint provided is sufficient
|
|
|
|
static bool report_error(const char* blockName, const char* errorMessage) {
|
|
|
|
SkDebugf("%s: %s\n", blockName, errorMessage);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-11-01 13:29:36 +00:00
|
|
|
Definition* FiddleBase::findExample(string name) const {
|
|
|
|
return fBmhParser->findExample(name);
|
|
|
|
}
|
|
|
|
|
2017-10-31 19:44:45 +00:00
|
|
|
bool FiddleBase::parseFiddles() {
|
2018-07-18 19:10:08 +00:00
|
|
|
if (fStack.empty()) {
|
2017-07-28 15:04:54 +00:00
|
|
|
return false;
|
|
|
|
}
|
2018-07-18 19:10:08 +00:00
|
|
|
JsonStatus* status = &fStack.back();
|
2019-02-06 14:41:58 +00:00
|
|
|
while (!status->atEnd()) {
|
|
|
|
const char* blockName = status->fObjectIter->fKey.begin();
|
2018-07-18 19:10:08 +00:00
|
|
|
Definition* example = nullptr;
|
|
|
|
string textString;
|
2019-02-06 14:41:58 +00:00
|
|
|
if (!status->fObject) {
|
2018-09-14 13:12:38 +00:00
|
|
|
return report_error(blockName, "expected object");
|
2018-07-18 19:10:08 +00:00
|
|
|
}
|
2019-02-06 14:41:58 +00:00
|
|
|
const skjson::ObjectValue* obj = status->fObjectIter->fValue;
|
|
|
|
for (auto iter = obj->begin(); obj->end() != iter; ++iter) {
|
|
|
|
const char* memberName = iter->fKey.begin();
|
2018-07-18 19:10:08 +00:00
|
|
|
if (!strcmp("compile_errors", memberName)) {
|
2019-02-06 14:41:58 +00:00
|
|
|
if (!iter->fValue.is<skjson::ArrayValue>()) {
|
2018-09-14 13:12:38 +00:00
|
|
|
return report_error(blockName, "expected array");
|
2017-07-28 15:04:54 +00:00
|
|
|
}
|
2019-02-06 14:41:58 +00:00
|
|
|
if (iter->fValue.as<skjson::ArrayValue>().size()) {
|
2018-09-14 13:12:38 +00:00
|
|
|
return report_error(blockName, "fiddle compiler error");
|
2018-07-18 19:10:08 +00:00
|
|
|
}
|
|
|
|
continue;
|
2017-07-28 15:04:54 +00:00
|
|
|
}
|
2018-07-18 19:10:08 +00:00
|
|
|
if (!strcmp("runtime_error", memberName)) {
|
2019-02-06 14:41:58 +00:00
|
|
|
if (!iter->fValue.is<skjson::StringValue>()) {
|
2018-09-14 13:12:38 +00:00
|
|
|
return report_error(blockName, "expected string 1");
|
2018-07-18 19:10:08 +00:00
|
|
|
}
|
2019-02-06 14:41:58 +00:00
|
|
|
if (iter->fValue.as<skjson::StringValue>().size()) {
|
2018-09-14 13:12:38 +00:00
|
|
|
return report_error(blockName, "fiddle runtime error");
|
2017-07-28 15:04:54 +00:00
|
|
|
}
|
2018-07-18 19:10:08 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!strcmp("fiddleHash", memberName)) {
|
2019-02-06 14:41:58 +00:00
|
|
|
const skjson::StringValue* sv = iter->fValue;
|
|
|
|
if (!sv) {
|
2018-09-14 13:12:38 +00:00
|
|
|
return report_error(blockName, "expected string 2");
|
2018-07-18 19:10:08 +00:00
|
|
|
}
|
|
|
|
example = this->findExample(blockName);
|
|
|
|
if (!example) {
|
2018-09-14 13:12:38 +00:00
|
|
|
return report_error(blockName, "missing example");
|
2018-07-18 19:10:08 +00:00
|
|
|
}
|
2019-02-06 14:41:58 +00:00
|
|
|
if (example->fHash.length() && example->fHash != sv->begin()) {
|
2018-07-18 19:10:08 +00:00
|
|
|
return example->reportError<bool>("mismatched hash");
|
2017-10-31 19:44:45 +00:00
|
|
|
}
|
2019-02-06 14:41:58 +00:00
|
|
|
example->fHash = sv->begin();
|
2018-07-18 19:10:08 +00:00
|
|
|
continue;
|
2017-10-31 19:44:45 +00:00
|
|
|
}
|
2018-07-18 19:10:08 +00:00
|
|
|
if (!strcmp("text", memberName)) {
|
2019-02-06 14:41:58 +00:00
|
|
|
const skjson::StringValue* sv = iter->fValue;
|
|
|
|
if (!sv) {
|
2018-09-14 13:12:38 +00:00
|
|
|
return report_error(blockName, "expected string 3");
|
2017-07-28 15:04:54 +00:00
|
|
|
}
|
2019-02-06 14:41:58 +00:00
|
|
|
textString = sv->begin();
|
2018-07-18 19:10:08 +00:00
|
|
|
continue;
|
2017-07-28 15:04:54 +00:00
|
|
|
}
|
2018-09-14 13:12:38 +00:00
|
|
|
return report_error(blockName, "unexpected key");
|
2017-07-28 15:04:54 +00:00
|
|
|
}
|
2018-07-18 19:10:08 +00:00
|
|
|
if (!example) {
|
2018-09-14 13:12:38 +00:00
|
|
|
return report_error(blockName, "missing fiddleHash");
|
2017-07-28 15:04:54 +00:00
|
|
|
}
|
2018-07-18 19:10:08 +00:00
|
|
|
size_t strLen = textString.length();
|
|
|
|
if (strLen) {
|
|
|
|
if (fTextOut
|
|
|
|
&& !this->textOut(example, textString.c_str(), textString.c_str() + strLen)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else if (fPngOut && !this->pngOut(example)) {
|
2017-07-28 15:04:54 +00:00
|
|
|
return false;
|
|
|
|
}
|
2019-02-06 14:41:58 +00:00
|
|
|
status->advance();
|
2017-07-28 15:04:54 +00:00
|
|
|
}
|
2017-10-31 19:44:45 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-11-01 13:29:36 +00:00
|
|
|
bool FiddleParser::parseFromFile(const char* path) {
|
|
|
|
if (!INHERITED::parseFromFile(path)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
fBmhParser->resetExampleHashes();
|
|
|
|
if (!INHERITED::parseFiddles()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return fBmhParser->checkExampleHashes();
|
|
|
|
}
|
|
|
|
|
2017-10-31 19:44:45 +00:00
|
|
|
bool FiddleParser::textOut(Definition* example, const char* stdOutStart,
|
|
|
|
const char* stdOutEnd) {
|
|
|
|
bool foundStdOut = false;
|
|
|
|
for (auto& textOut : example->fChildren) {
|
|
|
|
if (MarkType::kStdOut != textOut->fMarkType) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
foundStdOut = true;
|
|
|
|
bool foundVolatile = false;
|
|
|
|
for (auto& stdOutChild : textOut->fChildren) {
|
|
|
|
if (MarkType::kVolatile == stdOutChild->fMarkType) {
|
|
|
|
foundVolatile = true;
|
|
|
|
break;
|
2017-07-28 15:04:54 +00:00
|
|
|
}
|
2017-10-31 19:44:45 +00:00
|
|
|
}
|
|
|
|
TextParser bmh(textOut);
|
|
|
|
EscapeParser fiddle(stdOutStart, stdOutEnd);
|
|
|
|
do {
|
|
|
|
bmh.skipWhiteSpace();
|
|
|
|
fiddle.skipWhiteSpace();
|
|
|
|
const char* bmhEnd = bmh.trimmedLineEnd();
|
|
|
|
const char* fiddleEnd = fiddle.trimmedLineEnd();
|
|
|
|
ptrdiff_t bmhLen = bmhEnd - bmh.fChar;
|
|
|
|
SkASSERT(bmhLen > 0);
|
|
|
|
ptrdiff_t fiddleLen = fiddleEnd - fiddle.fChar;
|
|
|
|
SkASSERT(fiddleLen > 0);
|
|
|
|
if (bmhLen != fiddleLen) {
|
|
|
|
if (!foundVolatile) {
|
|
|
|
bmh.reportError("mismatched stdout len\n");
|
|
|
|
}
|
|
|
|
} else if (strncmp(bmh.fChar, fiddle.fChar, fiddleLen)) {
|
|
|
|
if (!foundVolatile) {
|
2018-04-16 12:37:38 +00:00
|
|
|
SkDebugf("%.*s\n", fiddleLen, fiddle.fChar);
|
2017-10-31 19:44:45 +00:00
|
|
|
bmh.reportError("mismatched stdout text\n");
|
2017-07-28 15:04:54 +00:00
|
|
|
}
|
2017-10-31 19:44:45 +00:00
|
|
|
}
|
|
|
|
bmh.skipToLineStart();
|
|
|
|
fiddle.skipToLineStart();
|
|
|
|
} while (!bmh.eof() && !fiddle.eof());
|
|
|
|
if (!foundStdOut) {
|
|
|
|
bmh.reportError("bmh %s missing stdout\n");
|
|
|
|
} else if (!bmh.eof() || !fiddle.eof()) {
|
|
|
|
if (!foundVolatile) {
|
|
|
|
bmh.reportError("%s mismatched stdout eof\n");
|
2017-07-28 15:04:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|