summaryrefslogtreecommitdiff
path: root/Build/source/texk/psutils/psutils-1.23/psutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/psutils/psutils-1.23/psutil.c')
-rw-r--r--Build/source/texk/psutils/psutils-1.23/psutil.c407
1 files changed, 407 insertions, 0 deletions
diff --git a/Build/source/texk/psutils/psutils-1.23/psutil.c b/Build/source/texk/psutils/psutils-1.23/psutil.c
new file mode 100644
index 00000000000..8533bff4906
--- /dev/null
+++ b/Build/source/texk/psutils/psutils-1.23/psutil.c
@@ -0,0 +1,407 @@
+/* psutil.c
+ * PSUtils utility functions
+ *
+ * (c) Reuben Thomas 2012-2014
+ * (c) Angus J. C. Duggan 1991-1997
+ * See file LICENSE for details.
+ */
+
+#include "config.h"
+
+#define _FILE_OFFSET_BITS 64
+
+#include "psutil.h"
+#include "psspec.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+#include "progname.h"
+#include "xvasprintf.h"
+#include "verror.h"
+
+#define iscomment(x,y) (strncmp(x,y,strlen(y)) == 0)
+
+int pages;
+int verbose;
+FILE *infile;
+FILE *outfile;
+char pagelabel[BUFSIZ];
+int pageno;
+
+static char buffer[BUFSIZ];
+static long bytes = 0;
+static off_t pagescmt = 0;
+static off_t headerpos = 0;
+static off_t endsetup = 0;
+static off_t beginprocset = 0; /* start of pstops procset */
+static off_t endprocset = 0;
+static int outputpage = 0;
+static int maxpages = 100;
+static off_t *pageptr;
+
+_Noreturn void usage(void)
+{
+ fprintf(stderr, "%s %s\n%sUsage: %s %s", program_name, PACKAGE_VERSION, COPYRIGHT_STRING, program_name, syntax);
+ exit(1);
+}
+
+void argerror(void)
+{
+ die(argerr_message);
+}
+
+/* Message function: for messages, warnings, and errors sent to stderr.
+ The routine does not return. */
+void die(const char *format, ...)
+{
+ va_list args;
+
+ if (verbose) /* We may be in the middle of a line */
+ putc('\n', stderr);
+
+ va_start(args, format);
+ verror(1, 0, format, args); /* Does not return */
+}
+
+#if 0 /* not used for TeX Live */
+/* Read a line from a pipe and return it without any trailing newline. */
+static char *pgetline(const char *cmd)
+{
+ char *l = NULL;
+ FILE *fp = popen(cmd, "r");
+ if (fp) {
+ size_t n, len;
+ len = getline(&l, &n, fp);
+ if (l && l[len - 1] == '\n')
+ l[len - 1] = '\0';
+ pclose(fp);
+ }
+ return l;
+}
+
+/* Get the size of the given paper, or the default paper if paper_name == NULL. */
+int paper_size(const char *paper_name, double *width, double *height)
+{
+ char *cmd = NULL, *l = NULL;
+ int res = 0;
+ if (paper_name == NULL) /* Use default paper name */
+ paper_name = pgetline(PAPER);
+ if (paper_name && (cmd = xasprintf(PAPER " --unit=pt --size %s", paper_name)) && (l = pgetline(cmd)))
+ res = sscanf(l, "%lg %lg", width, height);
+ free(l);
+ free(cmd);
+ return res == 2;
+}
+#endif /* not used for TeX Live */
+
+/* Make a file seekable, using temporary files if necessary */
+FILE *seekable(FILE *fp)
+{
+ FILE *ft;
+ long r, w ;
+ char *p;
+ char buffer[BUFSIZ] ;
+ off_t fpos;
+
+ if ((fpos = ftello(fp)) >= 0)
+ if (!fseeko(fp, (off_t) 0, SEEK_END) && !fseeko(fp, fpos, SEEK_SET))
+ return (fp);
+
+ if ((ft = tmpfile()) == NULL)
+ return (NULL);
+
+ while ((r = fread(p = buffer, sizeof(char), BUFSIZ, fp)) > 0) {
+ do {
+ if ((w = fwrite(p, sizeof(char), r, ft)) == 0)
+ return (NULL) ;
+ p += w ;
+ r -= w ;
+ } while (r > 0) ;
+ }
+
+ if (!feof(fp))
+ return (NULL) ;
+
+ /* discard the input file, and rewind the temporary */
+ (void) fclose(fp);
+ if (fseeko(ft, (off_t) 0, SEEK_SET) != 0)
+ return (NULL) ;
+
+ return (ft);
+}
+
+
+/* copy input file from current position upto new position to output file,
+ * ignoring the lines starting at something ignorelist points to */
+static int fcopy(off_t upto, off_t *ignorelist)
+{
+ off_t here = ftello(infile);
+ off_t bytes_left;
+
+ if (ignorelist != NULL) {
+ while (*ignorelist > 0 && *ignorelist < here)
+ ignorelist++;
+
+ while (*ignorelist > 0 && *ignorelist < upto) {
+ int r = fcopy(*ignorelist, NULL);
+ if (!r || fgets(buffer, BUFSIZ, infile) == NULL)
+ return 0;
+ ignorelist++;
+ here = ftello(infile);
+ while (*ignorelist > 0 && *ignorelist < here)
+ ignorelist++;
+ }
+ }
+ bytes_left = upto - here;
+
+ while (bytes_left > 0) {
+ size_t rw_result;
+ const size_t numtocopy = (bytes_left > BUFSIZ) ? BUFSIZ : bytes_left;
+ rw_result = fread(buffer, 1, numtocopy, infile);
+ if (rw_result < numtocopy) return (0);
+ rw_result = fwrite(buffer, 1, numtocopy, outfile);
+ if (rw_result < numtocopy) return (0);
+ bytes_left -= numtocopy;
+ bytes += numtocopy;
+ }
+ return (1);
+}
+
+/* build array of pointers to start/end of pages */
+void scanpages(off_t *sizeheaders)
+{
+ register char *comment = buffer+2;
+ register int nesting = 0;
+ register off_t record;
+
+ if (sizeheaders)
+ *sizeheaders = 0;
+
+ if ((pageptr = (off_t *)malloc(sizeof(off_t)*maxpages)) == NULL)
+ die("out of memory");
+ pages = 0;
+ fseeko(infile, (off_t) 0, SEEK_SET);
+ while (record = ftello(infile), fgets(buffer, BUFSIZ, infile) != NULL)
+ if (*buffer == '%') {
+ if (buffer[1] == '%') {
+ if (nesting == 0 && iscomment(comment, "Page:")) {
+ if (pages >= maxpages-1) {
+ maxpages *= 2;
+ if ((pageptr = (off_t *)realloc((char *)pageptr,
+ sizeof(off_t)*maxpages)) == NULL)
+ die("out of memory");
+ }
+ pageptr[pages++] = record;
+ } else if (headerpos == 0 && iscomment(comment, "BoundingBox:")) {
+ if (sizeheaders) {
+ *(sizeheaders++) = record;
+ *sizeheaders = 0;
+ }
+ } else if (headerpos == 0 && iscomment(comment, "HiResBoundingBox:")) {
+ if (sizeheaders) {
+ *(sizeheaders++) = record;
+ *sizeheaders = 0;
+ }
+ } else if (headerpos == 0 && iscomment(comment,"DocumentPaperSizes:")) {
+ if (sizeheaders) {
+ *(sizeheaders++) = record;
+ *sizeheaders = 0;
+ }
+ } else if (headerpos == 0 && iscomment(comment,"DocumentMedia:")) {
+ if (sizeheaders) {
+ *(sizeheaders++) = record;
+ *sizeheaders = 0;
+ }
+ } else if (headerpos == 0 && iscomment(comment, "Pages:"))
+ pagescmt = record;
+ else if (headerpos == 0 && iscomment(comment, "EndComments"))
+ headerpos = ftello(infile);
+ else if (iscomment(comment, "BeginDocument") ||
+ iscomment(comment, "BeginBinary") ||
+ iscomment(comment, "BeginFile"))
+ nesting++;
+ else if (iscomment(comment, "EndDocument") ||
+ iscomment(comment, "EndBinary") ||
+ iscomment(comment, "EndFile"))
+ nesting--;
+ else if (nesting == 0 && iscomment(comment, "EndSetup"))
+ endsetup = record;
+ else if (nesting == 0 && iscomment(comment, "BeginProlog"))
+ headerpos = ftello(infile);
+ else if (nesting == 0 &&
+ iscomment(comment, "BeginProcSet: PStoPS"))
+ beginprocset = record;
+ else if (beginprocset && !endprocset &&
+ iscomment(comment, "EndProcSet"))
+ endprocset = ftello(infile);
+ else if (nesting == 0 && (iscomment(comment, "Trailer") ||
+ iscomment(comment, "EOF"))) {
+ fseeko(infile, record, SEEK_SET);
+ break;
+ }
+ } else if (headerpos == 0 && buffer[1] != '!')
+ headerpos = record;
+ } else if (headerpos == 0)
+ headerpos = record;
+ pageptr[pages] = ftello(infile);
+ if (endsetup == 0 || endsetup > pageptr[0])
+ endsetup = pageptr[0];
+}
+
+/* seek a particular page */
+void seekpage(int p)
+{
+ fseeko(infile, pageptr[p], SEEK_SET);
+ if (fgets(buffer, BUFSIZ, infile) != NULL &&
+ iscomment(buffer, "%%Page:")) {
+ char *start, *end;
+ for (start = buffer+7; isspace(*start); start++);
+ if (*start == '(') {
+ int paren = 1;
+ for (end = start+1; paren > 0; end++)
+ switch (*end) {
+ case '\0':
+ die("Bad page label while seeking page %d", p);
+ case '(':
+ paren++;
+ break;
+ case ')':
+ paren--;
+ break;
+ default:
+ break;
+ }
+ } else
+ for (end = start; !isspace(*end); end++);
+ strncpy(pagelabel, start, end-start);
+ pagelabel[end-start] = '\0';
+ pageno = atoi(end);
+ } else
+ die("I/O error seeking page %d", p);
+}
+
+/* Output routines. These all update the global variable bytes with the number
+ * of bytes written */
+void writestring(const char *s)
+{
+ fputs(s, outfile);
+ bytes += strlen(s);
+}
+
+/* write page comment */
+void writepageheader(const char *label, int page)
+{
+ if (verbose)
+ fprintf(stderr, "[%d] ", page);
+ sprintf(buffer, "%%%%Page: %s %d\n", label, ++outputpage);
+ writestring(buffer);
+}
+
+/* search for page setup */
+void writepagesetup(void)
+{
+ char buffer[BUFSIZ];
+ if (beginprocset) {
+ for (;;) {
+ if (fgets(buffer, BUFSIZ, infile) == NULL)
+ die("I/O error reading page setup %d", outputpage);
+ if (!strncmp(buffer, "PStoPSxform", 11))
+ break;
+ if (fputs(buffer, outfile) == EOF)
+ die("I/O error writing page setup %d", outputpage);
+ bytes += strlen(buffer);
+ }
+ }
+}
+
+/* write the body of a page */
+void writepagebody(int p)
+{
+ if (!fcopy(pageptr[p+1], NULL))
+ die("I/O error writing page %d", outputpage);
+}
+
+/* write a whole page */
+void writepage(int p)
+{
+ seekpage(p);
+ writepageheader(pagelabel, p+1);
+ writepagebody(p);
+}
+
+/* write from start of file to end of header comments */
+void writeheader(int p, off_t *ignore)
+{
+ writeheadermedia(p, ignore, -1, -1);
+}
+
+void writeheadermedia(int p, off_t *ignore, double width, double height)
+{
+ fseeko(infile, (off_t) 0, SEEK_SET);
+ if (pagescmt) {
+ if (!fcopy(pagescmt, ignore) || fgets(buffer, BUFSIZ, infile) == NULL)
+ die("I/O error in header");
+ if (width > -1 && height > -1) {
+ sprintf(buffer, "%%%%DocumentMedia: plain %d %d 0 () ()\n", (int) width, (int) height);
+ writestring(buffer);
+ sprintf(buffer, "%%%%BoundingBox: 0 0 %d %d\n", (int) width, (int) height);
+ writestring(buffer);
+ }
+ sprintf(buffer, "%%%%Pages: %d 0\n", p);
+ writestring(buffer);
+ }
+ if (!fcopy(headerpos, ignore))
+ die("I/O error in header");
+}
+
+/* write prologue to end of setup section excluding PStoPS procset */
+int writepartprolog(void)
+{
+ if (beginprocset && !fcopy(beginprocset, NULL))
+ die("I/O error in prologue");
+ if (endprocset)
+ fseeko(infile, endprocset, SEEK_SET);
+ writeprolog();
+ return !beginprocset;
+}
+
+/* write prologue up to end of setup section */
+void writeprolog(void)
+{
+ if (!fcopy(endsetup, NULL))
+ die("I/O error in prologue");
+}
+
+/* write from end of setup to start of pages */
+void writesetup(void)
+{
+ if (!fcopy(pageptr[0], NULL))
+ die("I/O error in prologue");
+}
+
+/* write trailer */
+void writetrailer(void)
+{
+ fseeko(infile, pageptr[pages], SEEK_SET);
+ while (fgets(buffer, BUFSIZ, infile) != NULL) {
+ writestring(buffer);
+ }
+ if (verbose)
+ fprintf(stderr, "Wrote %d pages, %ld bytes\n", outputpage, bytes);
+}
+
+/* write a page with nothing on it */
+void writeemptypage(void)
+{
+ if (verbose)
+ fprintf(stderr, "[*] ");
+ sprintf(buffer, "%%%%Page: * %d\n", ++outputpage);
+ writestring(buffer);
+ if (beginprocset)
+ writestring("PStoPSxform concat\n");
+ writestring("showpage\n");
+}
+