summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-1.6/src/PSInterpreter.cpp
diff options
context:
space:
mode:
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.cpp357
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;
-}
-