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