diff options
Diffstat (limited to 'Build/source/texk/psutils/psutils-1.23/psutil.c')
-rw-r--r-- | Build/source/texk/psutils/psutils-1.23/psutil.c | 407 |
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"); +} + |