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