home *** CD-ROM | disk | FTP | other *** search
- /* ======== PSpage - a page manipulation program ======== */
- /*
- * Copyright 1991, 1990 by Adobe Systems Incorporated. All rights reserved.
- *
- * This file may be freely copied and redistributed as long as:
- * 1) This entire notice continues to be included in the file,
- * 2) If the file has been modified in any way, a notice of such
- * modification is conspicuously indicated.
- *
- * PostScript, Display PostScript, and Adobe are registered trademarks of
- * Adobe Systems Incorporated.
- *
- * ************************************************************************
- * THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO CHANGE WITHOUT
- * NOTICE, AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY ADOBE SYSTEMS
- * INCORPORATED. ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY OR
- * LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO WARRANTY OF ANY
- * KIND (EXPRESS, IMPLIED OR STATUTORY) WITH RESPECT TO THIS INFORMATION,
- * AND EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
- * ************************************************************************
- */
-
- /*
- * SUMMARY:
- * This program will manipulate a properly formatted PostScript document,
- * that is, one that complies with the Adobe Document Structuring Conventions.
- * Given the simplicity of this program, it is really only interested in the
- * following comments;
- * %!PS-Adobe-X.x
- * %%EndSetup
- * %%Page:
- * %%Trailer
- *
- * OPTIONS:
- * p - allows a range of pages to be specified in the form
- * of a list separated by commas. E.g. 4,5-13,22
- * Ranges can be specified forwards, e.g. 5-13, or backwards, e.g. 13-5
- * r - will cause PSpage to page reverse the document.
- *
- * DEFAULTS:
- * If options are not specified, all pages are output without page reversal.
- *
- * KNOWN BUGS:
- * For page reversal: PSpage does not check the %%Pages: comment to see if
- * the second argument is a 0, which indicates that page order should not
- * be changed.
- *
- * PSpage does not handle included documents, that would be better serviced
- * by a proper state machine implementation.
- *
- * Specifying an open range (e.g. 5-) to indicate that the current page until
- * the end of the document is desired but is not supported.
- *
- * THINGS TO TWEAK:
- * ** MAXPAGES defines the maximum number of pages that can be reversed
- * ** MAXRANGES defines the maximum number of ranges that can be specified
- * ** In the #include section, the file <stdarg.h> may be <varargs.h> or
- * <sys/varagrs.h> on your system.
- *
- * CHANGE HISTORY:
- * 90-June-01 orthlieb created
- * 91-June-05 mackay incorporated comments; made lines < 80 chars;
- * 91-Sept-26 mackay added comment on #include <stdarg.h>
- */
-
-
- /* ----------------------- includes ----------------------*/
- #include <stdio.h>
- #include <string.h>
- #include <stdarg.h>
- /* ------------------------ defines ----------------------*/
- #define TRUE 1
- #define FALSE 0
- #define VERBOSE TRUE
- #define TERSE FALSE
- #define error printf
-
- /* MAXPAGES defines the maximum number of pages that can be reversed */
- #define MAXPAGES 100
-
- /* MAXRANGES defines the maximum number of ranges that can be specified */
- #define MAXRANGES 25
-
- /* ----------------------- typedefs --------------------- */
- typedef char bool;
-
- /* ------------------------ globals ----------------------*/
- long pageloc[MAXPAGES];
- int numpages;
- bool pagereverse = FALSE; /* Default: No page reversal */
- char *pageranges[MAXRANGES];
- int numranges = 0;
- FILE *infile, *outfile;
-
- /* ------------------------ externs ----------------------*/
- extern void find_page_locations(FILE *thefile);
- extern void output_document(FILE *infile, FILE *outfile);
- extern void check_args(int numargs, char **args);
-
- /* ----------------------- mainline ----------------------*/
- void main (int argc, char **argv)
- {
-
- /* Setup page ranges */
- numranges = 1;
- pageranges[0] = "*";
- pageranges[1] = NULL;
-
- check_args(argc, argv);
- find_page_locations(infile);
- rewind(infile);
- output_document(infile, outfile);
- }
-
- void print_instructions(bool howlong)
- {
- error("PSpage [-p <pages>] [-r] <infile> <outfile>\n");
- if (howlong == TERSE) return;
- error("This program will manipulate a properly formatted PostScript\n");
- error("document, that is, one that complies with the Adobe Document\n");
- error("Structuring Conventions. \n\n");
- error("Options:\n");
- error("p - allows a range of pages to be specified in the form\n");
- error(" of a list separated by commas. E.g. 4,5-13,22\n");
- error(" Ranges can be specified forwards, e.g. 5-13,\n");
- error(" or backwards, e.g. 13-5\n");
- error("r - will cause PSpage to page reverse the document.\n\n");
- error("Defaults:\n");
- error("If options are not specified, all pages are output");
- error(" without page reversal\n\n");
- error("Known Bugs:\n");
- error("For page reversal: PSpage does not check the %%Pages: comment\n");
- error("to see if the second argument is a 0, which indicates that page\n");
- error("order should not be changed.\n");
- error("PSpage does not handle included documents, that would be better\n");
- error("serviced by a proper state machine implementation.\n");
- }
-
- void check_args(int numargs, char **arg)
- {
- int mark;
- char *cmd;
-
- /* Check to see if long instructions are desired */
- if (numargs < 2 || arg[1][0] == '?') {
- print_instructions(VERBOSE);
- exit(0);
- }
- if (numargs < 3) {
- error("PSpage ERROR: Not enough arguments\n");
- print_instructions(TERSE);
- exit(0);
- }
-
- mark = 1;
- while(mark < numargs) {
- /* If we've found a command */
- if (arg[mark][0] == '-') {
- for (cmd = &arg[mark][1]; *cmd != '\0'; cmd++) {
- /* Scan the arguments */
- switch (*cmd) {
- case 'p': /* Page number list */
- error("PSpage STATUS: using page range option.\n");
- /* The next argument must be a list of page ranges */
- /* Breakout the page ranges into individual tokens */
- numranges = 0;
- pageranges[numranges++] = strtok(arg[mark+1],",");
- while ((pageranges[numranges++] = strtok(NULL,",")) != NULL);
- numranges--; /* Reset to reflect actual number of ranges */
- mark++; /* move to next token */
- break;
- case 'r': /* Page reversal desired */
- error("PSpage STATUS: performing page reversal.\n");
- pagereverse = TRUE;
- break;
- default:
- error("PSpage ERROR: invalid option\n");
- print_instructions(TERSE);
- exit(-1);
- break;
- }
- }
- }
- else {
- if (infile == NULL) {
- if ((infile = fopen(arg[mark],"rb")) == NULL) {
- error("PSpage ERROR: cannot open input file %s.\n",arg[mark]);
- exit(-1);
- }
- }
- else {
- if ((outfile = fopen(arg[mark],"wb")) == NULL) {
- error("PSpage ERROR: cannot open output file %s.\n",arg[mark]);
- exit(-1);
- }
- }
- }
- mark++;
- }
- }
-
- int check_comment(char *str, int numargs, ...)
- {
- va_list ap;
- char *comment;
-
- va_start(ap, numargs);
-
- while (numargs-- > 0) {
- comment = va_arg(ap, char *);
- if (strncmp(str, comment, strlen(comment)) == 0) {
- va_end(ap);
- return TRUE;
- }
- }
- va_end(ap);
- return FALSE;
- }
-
- void find_page_locations(FILE *thefile)
- {
- int i;
- bool endoffile = FALSE;
- long oldpos = 0;
- char buf[256];
- char *junk;
-
- while (endoffile == FALSE) {
- /* Save our current position */
- oldpos = ftell(thefile);
-
- /* Get a line from the file */
- if (fgets(buf, 256, thefile) == NULL) {
- /* No %%Trailer, No %%EOF */
- if (!pageloc[numpages]) pageloc[numpages] = oldpos;
- endoffile = TRUE;
- }
- else {
- /* Check to see if we've found a comment */
- if (buf[0] == '%' && buf[1] == '%') {
- /* Check for the Page comment, record the location */
- if (check_comment(buf, 1, "%%Page:") == TRUE) {
- /* Note the location of this page */
- pageloc[numpages++] = oldpos;
- }
- /* Check for the trailer or EOF to see if it's time to leave */
- if (check_comment(buf, 2, "%%Trailer", "%%EOF") == TRUE) {
- /* End of the last page */
- pageloc[numpages] = oldpos;
- endoffile = TRUE; /* No use searching any more */
- }
- }
- }
- }
- if (numpages == 0) {
- error("PSpage ERROR: No %%%%Page: comments in this document.\n");
- exit(-2);
- } else {
- error("PSpage STATUS: This document has %d pages.\n", numpages);
- }
- }
-
- void find_page_parms(char *range, int *start, int *end)
- {
- char *pdash = NULL;
- int temp;
-
- if (range[0] == '*') {
- *start = 1;
- *end = numpages;
- }
- /* Single number */
- else if ((pdash = strchr(range,'-')) == NULL) {
- *start = *end = atoi(range);
- }
- else {
- /* Range of numbers */
- *pdash++ = '\0';
- *start = atoi(range); *end = atoi(pdash);
- }
-
- if (*start < 1 | *end < 1 | *start > numpages | *end > numpages) {
- error("PSpage ERROR: page range is invalid [%d-%d].\n", start, end);
- exit(-3);
- }
- (*start)--; (*end)--;
-
- /* Pull a little sneaky to help with page reversal */
- if (pagereverse == TRUE) {
- temp = *start; *start = *end; *end = temp;
- }
- }
-
- void print_page(FILE *infile, FILE *outfile, int page)
- {
- long i;
-
- if (fseek(infile, pageloc[page], SEEK_SET) != 0) {
- error("PSpage ERROR: Seek at position %d, page %d\n",
- pageloc[page], page+1);
- exit(-2);
- }
- for (i = pageloc[page]; i < pageloc[page+1]; i++)
- fputc(fgetc(infile), outfile);
- }
-
- void output_document(FILE *infile, FILE *outfile)
- {
- char c;
- int pagestart, pageend, pageincr, rangeindex, rangeincr;
- long i;
- register int r, p;
-
- /* Print out the top of the file */
- for (i = 0; i < pageloc[0]; i++)
- fputc(fgetc(infile),outfile);
-
- /* Now start the page manipulations */
- /* Flip the order of ranges for page reversal */
- rangeincr = 1; rangeindex = 0;
- if (pagereverse == TRUE) {
- rangeincr = -1;
- rangeindex = numranges - 1;
- }
-
- for (r = rangeindex; r < numranges && r >= 0; r += rangeincr) {
- find_page_parms(pageranges[r], &pagestart, &pageend);
- /* Print out each individual page */
- if (pagestart > pageend)
- for (p = pagestart; p >= pageend;p--)
- print_page(infile, outfile, p);
- else
- for (p = pagestart; p <= pageend; p++)
- print_page(infile, outfile, p);
- }
-
- /* Now print out the end of the file */
- if (fseek(infile, pageloc[numpages], SEEK_SET) != 0) {
- error("PSpage ERROR: Seek at position %d while writing trailer %d\n",
- pageloc[numpages]);
- exit(-2);
- }
- while ((c = fgetc(infile)) != EOF)
- fputc(c,outfile);
- }
-