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
8 * psselect [-q] [-e] [-o] [-r] [-p<pages>] [infile [outfile]]
20 char pagelabel
[BUFSIZ
] ;
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");
28 "Usage: %s [-q] [-e] [-o] [-r] [-p<pages>] [infile [outfile]]\n",
34 typedef struct pgrange
{
39 static PageRange
*makerange(int beg
, int end
, PageRange
*next
)
42 if ((new = (PageRange
*)malloc(sizeof(PageRange
))) == NULL
)
43 message(FATAL
, "out of memory\n");
51 static PageRange
*addrange(char *str
, PageRange
*rp
)
55 sign
= (*str
== '_' && ++str
) ? -1 : 1;
57 first
= sign
*atoi(str
);
58 while (isdigit(*str
)) str
++;
62 if (first
|| sign
< 0)
63 return (makerange(first
, first
, rp
));
66 if (first
|| sign
< 0)
67 return (addrange(str
+1, makerange(first
, first
, rp
)));
72 sign
= (*str
== '_' && ++str
) ? -1 : 1;
76 int last
= sign
*atoi(str
);
77 while (isdigit(*str
)) str
++;
80 return (makerange(first
, last
, rp
));
82 return (addrange(str
+1, makerange(first
, last
, rp
)));
84 } else if (*str
== '\0')
85 return (makerange(first
, -1, rp
));
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;
99 PageRange
*pagerange
= NULL
;
104 for (program
= *argv
++; --argc
; argv
++) {
105 if (argv
[0][0] == '-') {
106 switch (argv
[0][1]) {
107 case 'e': /* even pages */
110 case 'o': /* odd pages */
113 case 'r': /* reverse */
116 case 'p': /* page spec */
117 pagerange
= addrange(*argv
+2, pagerange
);
119 case 'q': /* quiet */
122 case 'v': /* version */
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
);
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");
148 if ((infile
=seekable(infile
))==NULL
)
149 message(FATAL
, "can't seek input\n");
153 /* select all pages or all in range if odd or even not set */
154 all
= !(odd
|| even
);
156 /* add default page range */
158 pagerange
= makerange(1, -1, NULL
);
160 /* reverse page list if not reversing pages (list constructed bottom up) */
162 PageRange
*revlist
= NULL
;
163 PageRange
*next
= NULL
;
165 next
= pagerange
->next
;
166 pagerange
->next
= revlist
;
171 } else { /* swap start & end if reversing */
173 for (r
= pagerange
; r
; r
= r
->next
) {
180 { /* adjust for end-relative pageranges */
182 for (r
= pagerange
; r
; r
= r
->next
) {
184 r
->first
+= pages
+ 1;
189 r
->last
+= pages
+ 1;
196 /* count pages on first pass, select pages on second pass */
197 for (pass
= 0; pass
< 2; pass
++) {
199 if (pass
) { /* write header on second pass */
200 writeheader(maxpage
);
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
)))) {
212 writepage(currentpg
-1);
220 for (currentpg
= r
->first
; currentpg
<= r
->last
; currentpg
++) {
221 if (currentpg
== 0 ||
222 (currentpg
<= pages
&&
223 ((currentpg
&1) ? (odd
|| all
) : (even
|| all
)))) {
226 writepage(currentpg
-1);