New Text by H.G. Wells: War of the Worlds
[ccbib.git] / psutils / psselect.c
blob295b57a0aff049f13ab74263cb41aaa2edc44364
1 /* psselect.c
2 * Copyright (C) Angus J. C. Duggan 1991-1995
3 * See file LICENSE for details.
5 * rearrange pages in conforming PS file for printing in signatures
7 * Usage:
8 * psselect [-q] [-e] [-o] [-r] [-p<pages>] [infile [outfile]]
9 */
11 #include "psutil.h"
12 #include "pserror.h"
13 #include "patchlev.h"
15 char *program ;
16 int pages ;
17 int verbose ;
18 FILE *infile ;
19 FILE *outfile ;
20 char pagelabel[BUFSIZ] ;
21 int pageno ;
23 static void usage(void)
25 fprintf(stderr, "%s release %d patchlevel %d\n", program, RELEASE, PATCHLEVEL);
26 fprintf(stderr, "Copyright (C) Angus J. C. Duggan, 1991-1995. See file LICENSE for details.\n");
27 fprintf(stderr,
28 "Usage: %s [-q] [-e] [-o] [-r] [-p<pages>] [infile [outfile]]\n",
29 program);
30 fflush(stderr);
31 exit(1);
34 typedef struct pgrange {
35 int first, last;
36 struct pgrange *next;
37 } PageRange ;
39 static PageRange *makerange(int beg, int end, PageRange *next)
41 PageRange *new;
42 if ((new = (PageRange *)malloc(sizeof(PageRange))) == NULL)
43 message(FATAL, "out of memory\n");
44 new->first = beg;
45 new->last = end;
46 new->next = next;
47 return (new);
51 static PageRange *addrange(char *str, PageRange *rp)
53 int first=0;
54 int sign;
55 sign = (*str == '_' && ++str) ? -1 : 1;
56 if (isdigit(*str)) {
57 first = sign*atoi(str);
58 while (isdigit(*str)) str++;
60 switch (*str) {
61 case '\0':
62 if (first || sign < 0)
63 return (makerange(first, first, rp));
64 break;
65 case ',':
66 if (first || sign < 0)
67 return (addrange(str+1, makerange(first, first, rp)));
68 break;
69 case '-':
70 case ':':
71 str++;
72 sign = (*str == '_' && ++str) ? -1 : 1;
73 if (!first)
74 first = 1;
75 if (isdigit(*str)) {
76 int last = sign*atoi(str);
77 while (isdigit(*str)) str++;
78 switch (*str) {
79 case '\0':
80 return (makerange(first, last, rp));
81 case ',':
82 return (addrange(str+1, makerange(first, last, rp)));
84 } else if (*str == '\0')
85 return (makerange(first, -1, rp));
86 else if (*str == ',')
87 return (addrange(str+1, makerange(first, -1, rp)));
89 message(FATAL, "invalid page range\n");
90 return (PageRange *)0 ;
94 void main(int argc, char *argv[])
96 int currentpg, maxpage = 0;
97 int even = 0, odd = 0, reverse = 0;
98 int pass, all;
99 PageRange *pagerange = NULL;
101 infile = stdin;
102 outfile = stdout;
103 verbose = 1;
104 for (program = *argv++; --argc; argv++) {
105 if (argv[0][0] == '-') {
106 switch (argv[0][1]) {
107 case 'e': /* even pages */
108 even = 1;
109 break;
110 case 'o': /* odd pages */
111 odd = 1;
112 break;
113 case 'r': /* reverse */
114 reverse = 1;
115 break;
116 case 'p': /* page spec */
117 pagerange = addrange(*argv+2, pagerange);
118 break;
119 case 'q': /* quiet */
120 verbose = 0;
121 break;
122 case 'v': /* version */
123 default:
124 usage();
126 } else if (pagerange == NULL && !reverse && !even && !odd) {
127 pagerange = addrange(*argv, NULL);
128 } else if (infile == stdin) {
129 if ((infile = fopen(*argv, OPEN_READ)) == NULL)
130 message(FATAL, "can't open input file %s\n", *argv);
131 } else if (outfile == stdout) {
132 if ((outfile = fopen(*argv, OPEN_WRITE)) == NULL)
133 message(FATAL, "can't open output file %s\n", *argv);
134 } else usage();
136 #if defined(MSDOS) || defined(WINNT)
137 if ( infile == stdin ) {
138 int fd = fileno(stdin) ;
139 if ( setmode(fd, O_BINARY) < 0 )
140 message(FATAL, "can't open input file %s\n", argv[4]);
142 if ( outfile == stdout ) {
143 int fd = fileno(stdout) ;
144 if ( setmode(fd, O_BINARY) < 0 )
145 message(FATAL, "can't reset stdout to binary mode\n");
147 #endif
148 if ((infile=seekable(infile))==NULL)
149 message(FATAL, "can't seek input\n");
151 scanpages();
153 /* select all pages or all in range if odd or even not set */
154 all = !(odd || even);
156 /* add default page range */
157 if (!pagerange)
158 pagerange = makerange(1, -1, NULL);
160 /* reverse page list if not reversing pages (list constructed bottom up) */
161 if (!reverse) {
162 PageRange *revlist = NULL;
163 PageRange *next = NULL;
164 while (pagerange) {
165 next = pagerange->next;
166 pagerange->next = revlist;
167 revlist = pagerange;
168 pagerange = next;
170 pagerange = revlist;
171 } else { /* swap start & end if reversing */
172 PageRange *r;
173 for (r = pagerange; r; r = r->next) {
174 int temp = r->last;
175 r->last = r->first;
176 r->first = temp;
180 { /* adjust for end-relative pageranges */
181 PageRange *r;
182 for (r = pagerange; r; r = r->next) {
183 if (r->first < 0) {
184 r->first += pages + 1;
185 if (r->first < 1)
186 r->first = 1;
188 if (r->last < 0) {
189 r->last += pages + 1;
190 if (r->last < 1)
191 r->last = 1;
196 /* count pages on first pass, select pages on second pass */
197 for (pass = 0; pass < 2; pass++) {
198 PageRange *r;
199 if (pass) { /* write header on second pass */
200 writeheader(maxpage);
201 writeprolog();
202 writesetup();
204 for (r = pagerange; r; r = r->next) {
205 if (r->last < r->first) {
206 for (currentpg = r->first; currentpg >= r->last; currentpg--) {
207 if (currentpg == 0 ||
208 (currentpg <= pages &&
209 ((currentpg&1) ? (odd || all) : (even || all)))) {
210 if (pass) {
211 if (currentpg)
212 writepage(currentpg-1);
213 else
214 writeemptypage() ;
215 } else
216 maxpage++;
219 } else {
220 for (currentpg = r->first; currentpg <= r->last; currentpg++) {
221 if (currentpg == 0 ||
222 (currentpg <= pages &&
223 ((currentpg&1) ? (odd || all) : (even || all)))) {
224 if (pass) {
225 if (currentpg)
226 writepage(currentpg-1);
227 else
228 writeemptypage() ;
229 } else
230 maxpage++;
236 writetrailer();
238 exit(0);