diff options
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-1.6/src/PSInterpreter.cpp')
-rw-r--r-- | Build/source/texk/dvisvgm/dvisvgm-1.6/src/PSInterpreter.cpp | 357 |
1 files changed, 0 insertions, 357 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-1.6/src/PSInterpreter.cpp b/Build/source/texk/dvisvgm/dvisvgm-1.6/src/PSInterpreter.cpp deleted file mode 100644 index 9ca5ed39c27..00000000000 --- a/Build/source/texk/dvisvgm/dvisvgm-1.6/src/PSInterpreter.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/************************************************************************* -** PSInterpreter.cpp ** -** ** -** This file is part of dvisvgm -- the DVI to SVG converter ** -** Copyright (C) 2005-2014 Martin Gieseking <martin.gieseking@uos.de> ** -** ** -** This program is free software; you can redistribute it and/or ** -** modify it under the terms of the GNU General Public License as ** -** published by the Free Software Foundation; either version 3 of ** -** the License, or (at your option) any later version. ** -** ** -** This program is distributed in the hope that it will be useful, but ** -** WITHOUT ANY WARRANTY; without even the implied warranty of ** -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** -** GNU General Public License for more details. ** -** ** -** You should have received a copy of the GNU General Public License ** -** along with this program; if not, see <http://www.gnu.org/licenses/>. ** -*************************************************************************/ - -#include <config.h> -#include <cstring> -#include <fstream> -#include <iostream> -#include <sstream> -#include "FileFinder.h" -#include "InputReader.h" -#include "Message.h" -#include "PSFilter.h" -#include "PSInterpreter.h" -#include "SignalHandler.h" - -using namespace std; - - -const char *PSInterpreter::GSARGS[] = { - "gs", // dummy name - "-q", // be quiet, suppress gs banner - "-dSAFER", // disallow writing of files - "-dNODISPLAY", // we don't need a display device - "-dNOPAUSE", // keep going - "-dWRITESYSTEMDICT", // leave systemdict writable as some operators must be replaced - "-dNOPROMPT", -// "-dNOBIND", -}; - - -/** Constructs a new PSInterpreter object. - * @param[in] actions template methods to be executed after recognizing the corresponding PS operator. */ -PSInterpreter::PSInterpreter (PSActions *actions) - : _mode(PS_NONE), _actions(actions), _filter(0), _bytesToRead(0), _inError(false), _initialized(false) -{ -} - - -void PSInterpreter::init () { - if (!_initialized) { - _gs.init(sizeof(GSARGS)/sizeof(char*), GSARGS, this); - _gs.set_stdio(input, output, error); - _initialized = true; - // Before executing any random PS code redefine some operators and run - // initializing PS code. This cannot be done in the constructor because we - // need the completely initialized PSInterpreter object here. - execute(PSDEFS); - } -} - - -PSActions* PSInterpreter::setActions (PSActions *actions) { - PSActions *old_actions = _actions; - _actions = actions; - return old_actions; -} - - -/** Checks if the given status value returned by Ghostscript indicates an error. - * @param[in] status status value returned by Ghostscript after the execution of a PS snippet - * @throw PSException if the status value indicates a PostScript error */ -void PSInterpreter::checkStatus (int status) { - if (status < 0) { - _mode = PS_QUIT; - if (status < -100) - throw PSException("fatal error"); - if (_errorMessage.empty()) - throw PSException(_gs.error_name(status)); - throw PSException(_errorMessage); - } -} - - -/** Executes a chunk of PostScript code. - * @param[in] str buffer containing the code - * @param[in] len number of characters in buffer - * @param[in] flush If true, a final 'flush' is sent which forces the output buffer to be written immediately. - * @return true if the assigned number of bytes have been read */ -bool PSInterpreter::execute (const char *str, size_t len, bool flush) { - init(); - if (_mode == PS_QUIT) - return false; - - int status=0; - if (_mode == PS_NONE) { - _gs.run_string_begin(0, &status); - _mode = PS_RUNNING; - } - checkStatus(status); - - bool complete=false; - if (_bytesToRead > 0 && len >= _bytesToRead) { - len = _bytesToRead; - complete = true; - } - - if (_filter && _filter->active()) { - PSFilter *filter = _filter; - _filter = 0; // prevent recursion when filter calls execute() - filter->execute(str, len); - if (filter->active()) // filter still active after execution? - _filter = filter; - return complete; - } - - // feed Ghostscript with code chunks that are not larger than 64KB - // => see documentation of gsapi_run_string_foo() - const char *p=str; - while (PS_RUNNING && len > 0) { - SignalHandler::instance().check(); - size_t chunksize = min(len, (size_t)0xffff); - _gs.run_string_continue(p, chunksize, 0, &status); - p += chunksize; - len -= chunksize; - if (_bytesToRead > 0) - _bytesToRead -= chunksize; - if (status == -101) // e_Quit - _mode = PS_QUIT; - else - checkStatus(status); - } - if (flush) { - // force writing contents of output buffer - _gs.run_string_continue("\nflush ", 7, 0, &status); - } - return complete; -} - - -/** Executes a chunk of PostScript code read from a stream. The method returns on EOF. - * @param[in] is the input stream - * @param[in] flush If true, a final 'flush' is sent which forces the output buffer to be written immediately. - * @return true if the assigned number of bytes have been read */ -bool PSInterpreter::execute (istream &is, bool flush) { - char buf[4096]; - bool finished = false; - while (is && !is.eof() && !finished) { - is.read(buf, 4096); - finished = execute(buf, is.gcount(), false); - } - execute("\n", 1, flush); - return finished; -} - - -bool PSInterpreter::executeRaw (const string &str, int n) { - _rawData.clear(); - ostringstream oss; - oss << str << ' ' << n << " (raw) prcmd\n"; - execute(oss.str()); - return !_rawData.empty(); -} - - -/** This callback function handles input from stdin to Ghostscript. Currently not needed. - * @param[in] inst pointer to calling instance of PSInterpreter - * @param[in] buf takes the read characters - * @param[in] len size of buffer buf - * @return number of characters read */ -int GSDLLCALL PSInterpreter::input (void *inst, char *buf, int len) { - return 0; -} - - -/** This callback function handles output from Ghostscript to stdout. It looks for - * emitted commands staring with "dvi." and executes them by calling method callActions. - * Ghostscript sends the text in chunks by several calls of this function. - * Unfortunately, the PostScript specification wants error messages also to be sent to stdout - * instead of stderr. Thus, we must collect and concatenate the chunks until an evaluable text - * snippet is completely received. Furthermore, error messages have to be recognized and to be - * filtered out. - * @param[in] inst pointer to calling instance of PSInterpreter - * @param[in] buf contains the characters to be output - * @param[in] len number of characters in buf - * @return number of processed characters (equals 'len') */ -int GSDLLCALL PSInterpreter::output (void *inst, const char *buf, int len) { - PSInterpreter *self = static_cast<PSInterpreter*>(inst); - if (self && self->_actions) { - const size_t MAXLEN = 512; // maximal line length (longer lines are of no interest) - const char *end = buf+len-1; // last position of buf - for (const char *first=buf, *last=buf; first <= end; last++, first=last) { - // move first and last to begin and end of the next line, respectively - while (last < end && *last != '\n') - last++; - size_t linelength = last-first+1; - if (linelength > MAXLEN) // skip long lines since they don't contain any relevant information - continue; - - vector<char> &linebuf = self->_linebuf; // just a shorter name... - if ((*last == '\n' || !self->active()) || self->_inError) { - if (linelength + linebuf.size() > 1) { // prefix "dvi." plus final newline - SplittedCharInputBuffer ib(linebuf.empty() ? 0 : &linebuf[0], linebuf.size(), first, linelength); - BufferInputReader in(ib); - if (self->_inError) - self->_errorMessage += string(first, linelength); - else { - in.skipSpace(); - if (in.check("Unrecoverable error: ")) { - self->_errorMessage.clear(); - while (!in.eof()) - self->_errorMessage += in.get(); - self->_inError = true; - } - else if (in.check("dvi.")) - self->callActions(in); - } - } - linebuf.clear(); - } - else { // no line end found => - // save remaining characters and prepend them to the next incoming chunk of characters - if (linebuf.size() + linelength > MAXLEN) - linebuf.clear(); // don't care for long lines - else { - size_t currsize = linebuf.size(); - linebuf.resize(currsize+linelength); - memcpy(&linebuf[currsize], first, linelength); - } - } - } - } - return len; -} - - -/** Converts a vector of strings to a vector of doubles. - * @param[in] str the strings to be converted - * @param[out] d the resulting doubles */ -static void str2double (const vector<string> &str, vector<double> &d) { - for (size_t i=0; i < str.size(); i++) { - istringstream iss(str[i]); - iss >> d[i]; - } -} - - -/** Evaluates a command emitted by Ghostscript and invokes the corresponding - * method of interface class PSActions. - * @param[in] in reader pointing to the next command */ -void PSInterpreter::callActions (InputReader &in) { - // array of currently supported operators (must be ascendingly sorted) - static const struct Operator { - const char *name; // name of operator - int pcount; // number of parameters (< 0 : variable number of parameters) - void (PSActions::*op)(vector<double> &p); // operation handler - } operators [] = { - {"applyscalevals", 3, &PSActions::applyscalevals}, - {"clip", 0, &PSActions::clip}, - {"closepath", 0, &PSActions::closepath}, - {"curveto", 6, &PSActions::curveto}, - {"eoclip", 0, &PSActions::eoclip}, - {"eofill", 0, &PSActions::eofill}, - {"fill", 0, &PSActions::fill}, - {"grestore", 0, &PSActions::grestore}, - {"grestoreall", 0, &PSActions::grestoreall}, - {"gsave", 0, &PSActions::gsave}, - {"initclip", 0, &PSActions::initclip}, - {"lineto", 2, &PSActions::lineto}, - {"makepattern", -1, &PSActions::makepattern}, - {"moveto", 2, &PSActions::moveto}, - {"newpath", 0, &PSActions::newpath}, - {"querypos", 2, &PSActions::querypos}, - {"raw", -1, 0}, - {"restore", 1, &PSActions::restore}, - {"rotate", 1, &PSActions::rotate}, - {"save", 1, &PSActions::save}, - {"scale", 2, &PSActions::scale}, - {"setcmykcolor", 4, &PSActions::setcmykcolor}, - {"setdash", -1, &PSActions::setdash}, - {"setgray", 1, &PSActions::setgray}, - {"sethsbcolor", 3, &PSActions::sethsbcolor}, - {"setlinecap", 1, &PSActions::setlinecap}, - {"setlinejoin", 1, &PSActions::setlinejoin}, - {"setlinewidth", 1, &PSActions::setlinewidth}, - {"setmatrix", 6, &PSActions::setmatrix}, - {"setmiterlimit", 1, &PSActions::setmiterlimit}, - {"setopacityalpha", 1, &PSActions::setopacityalpha}, - {"setpattern", -1, &PSActions::setpattern}, - {"setrgbcolor", 3, &PSActions::setrgbcolor}, - {"stroke", 0, &PSActions::stroke}, - {"translate", 2, &PSActions::translate}, - }; - if (_actions) { - in.skipSpace(); - // binary search - int first=0, last=sizeof(operators)/sizeof(Operator)-1; - while (first <= last) { - int mid = first+(last-first)/2; - int cmp = in.compare(operators[mid].name); - if (cmp > 0) - last = mid-1; - else if (cmp < 0) - first = mid+1; - else { - if (!operators[mid].op) { // raw string data received - _rawData.clear(); - in.skipSpace(); - while (!in.eof()) { - _rawData.push_back(in.getString()); - in.skipSpace(); - } - } - else { - // collect parameters and call handler - vector<string> params; - int pcount = operators[mid].pcount; - if (pcount < 0) { // variable number of parameters? - in.skipSpace(); - while (!in.eof()) { // read all available parameters - params.push_back(in.getString()); - in.skipSpace(); - } - } - else { // fix number of parameters - for (int i=0; i < pcount; i++) { - in.skipSpace(); - params.push_back(in.getString()); - } - } - vector<double> v(params.size()); - str2double(params, v); - (_actions->*operators[mid].op)(v); - _actions->executed(); - } - break; - } - } - } -} - - -/** This callback function handles output from Ghostscript to stderr. - * @param[in] inst pointer to calling instance of PSInterpreter - * @param[in] buf contains the characters to be output - * @param[in] len number of chars in buf - * @return number of processed characters */ -int GSDLLCALL PSInterpreter::error (void *inst, const char *buf, int len) { - return len; -} - |