/* psselect.c * Copyright (C) Angus J. C. Duggan 1991-1995 * See file LICENSE for details. * * rearrange pages in conforming PS file for printing in signatures * * Usage: * psselect [-q] [-e] [-o] [-r] [-p] [infile [outfile]] */ #include "psutil.h" #include "pserror.h" #include "patchlev.h" char *program ; int pages ; int verbose ; FILE *infile ; FILE *outfile ; char pagelabel[BUFSIZ] ; int pageno ; static void usage(void) { fprintf(stderr, "%s release %d patchlevel %d\n", program, RELEASE, PATCHLEVEL); fprintf(stderr, "Copyright (C) Angus J. C. Duggan, 1991-1995. See file LICENSE for details.\n"); fprintf(stderr, "Usage: %s [-q] [-e] [-o] [-r] [-p] [infile [outfile]]\n", program); fflush(stderr); exit(1); } typedef struct pgrange { int first, last; struct pgrange *next; } PageRange ; static PageRange *makerange(int beg, int end, PageRange *next) { PageRange *new; if ((new = (PageRange *)malloc(sizeof(PageRange))) == NULL) message(FATAL, "out of memory\n"); new->first = beg; new->last = end; new->next = next; return (new); } static PageRange *addrange(char *str, PageRange *rp) { int first=0; int sign; sign = (*str == '_' && ++str) ? -1 : 1; if (isdigit(*str)) { first = sign*atoi(str); while (isdigit(*str)) str++; } switch (*str) { case '\0': if (first) return (makerange(first, first, rp)); break; case ',': if (first) return (addrange(str+1, makerange(first, first, rp))); break; case '-': case ':': str++; sign = (*str == '_' && ++str) ? -1 : 1; if (isdigit(*str)) { int last = sign*atoi(str); while (isdigit(*str)) str++; if (!first) first = 1; switch (*str) { case '\0': return (makerange(first, last, rp)); case ',': return (addrange(str+1, makerange(first, last, rp))); } } else if (*str == '\0') return (makerange(first, -1, rp)); else if (*str == ',') return (addrange(str+1, makerange(first, -1, rp))); } message(FATAL, "invalid page range\n"); return (PageRange *)0 ; } void main(int argc, char *argv[]) { int currentpg, maxpage = 0; int even = 0, odd = 0, reverse = 0; int pass, all; PageRange *pagerange = NULL; infile = stdin; outfile = stdout; verbose = 1; for (program = *argv++; --argc; argv++) { if (argv[0][0] == '-') { switch (argv[0][1]) { case 'e': /* even pages */ even = 1; break; case 'o': /* odd pages */ odd = 1; break; case 'r': /* reverse */ reverse = 1; break; case 'p': /* page spec */ pagerange = addrange(*argv+2, pagerange); break; case 'q': /* quiet */ verbose = 0; break; case 'v': /* version */ default: usage(); } } else if (pagerange == NULL && !reverse && !even && !odd) { pagerange = addrange(*argv, NULL); } else if (infile == stdin) { if ((infile = fopen(*argv, OPEN_READ)) == NULL) message(FATAL, "can't open input file %s\n", *argv); } else if (outfile == stdout) { if ((outfile = fopen(*argv, OPEN_WRITE)) == NULL) message(FATAL, "can't open output file %s\n", *argv); } else usage(); } #if defined(MSDOS) || defined(WINNT) if ( infile == stdin ) { int fd = fileno(stdin) ; if ( setmode(fd, O_BINARY) < 0 ) message(FATAL, "can't open input file %s\n", argv[4]); } if ( outfile == stdout ) { int fd = fileno(stdout) ; if ( setmode(fd, O_BINARY) < 0 ) message(FATAL, "can't reset stdout to binary mode\n"); } #endif if ((infile=seekable(infile))==NULL) message(FATAL, "can't seek input\n"); scanpages(); /* select all pages or all in range if odd or even not set */ all = !(odd || even); /* add default page range */ if (!pagerange) pagerange = makerange(1, -1, NULL); /* reverse page list if not reversing pages (list constructed bottom up) */ if (!reverse) { PageRange *revlist = NULL; PageRange *next = NULL; while (pagerange) { next = pagerange->next; pagerange->next = revlist; revlist = pagerange; pagerange = next; } pagerange = revlist; } else { /* swap start & end if reversing */ PageRange *r; for (r = pagerange; r; r = r->next) { int temp = r->last; r->last = r->first; r->first = temp; } } { /* adjust for end-relative pageranges */ PageRange *r; for (r = pagerange; r; r = r->next) { if (r->first < 0) { r->first += pages + 1; if (r->first < 0) r->first = 0; } if (r->last < 0) { r->last += pages + 1; if (r->last < 0) r->last = 0; } } } /* count pages on first pass, select pages on second pass */ for (pass = 0; pass < 2; pass++) { PageRange *r; if (pass) { /* write header on second pass */ writeheader(maxpage); writeprolog(); writesetup(); } for (r = pagerange; r; r = r->next) { if (r->last < r->first) { for (currentpg = r->first; currentpg >= r->last; currentpg--) { if (currentpg <= pages && ((currentpg&1) ? (odd || all) : (even || all))) { if (pass) writepage(currentpg-1); else maxpage++; } } } else { for (currentpg = r->first; currentpg <= r->last; currentpg++) { if (currentpg <= pages && ((currentpg&1) ? (odd || all) : (even || all))) { if (pass) writepage(currentpg-1); else maxpage++; } } } } } writetrailer(); exit(0); }