]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/postscript/postgif/postgif.c
mothra: never snarf the "Go:" box
[plan9front.git] / sys / src / cmd / postscript / postgif / postgif.c
1
2 #include <stdio.h>
3 #include <string.h>
4 #include <signal.h>
5 #include <ctype.h>
6 #ifdef plan9
7 #define isascii(c)      ((unsigned char)(c)<=0177)
8 #endif
9 #include <sys/types.h>
10 #include <fcntl.h>
11
12 #include "comments.h"
13 #include "gen.h"
14 #include "path.h"
15 #include "ext.h"
16
17 #define dbprt   if (debug) fprintf
18
19 char    *optnames = "a:c:fglm:n:o:p:x:y:C:E:DG:IL:P:";
20 char    *prologue = POSTGIF;            /* default PostScript prologue */
21 char    *formfile = FORMFILE;           /* stuff for multiple pages per sheet */
22 int     formsperpage = 1;               /* page images on each piece of paper */
23 int     copies = 1;                     /* and this many copies of each sheet */
24 int     page = 0;                       /* last page we worked on */
25 int     printed = 0;                    /* and the number of pages printed */
26
27 extern char *malloc();
28 extern void free();
29 extern double atof(), pow();
30
31 unsigned char ibuf[BUFSIZ];
32 unsigned char *cmap, *gcmap, *lcmap;
33 unsigned char *gmap, *ggmap, *lgmap;
34 unsigned char *pmap;
35 double gamma;
36 float cr = 0.3, cg = 0.59, cb = 0.11;
37 int maplength, gmaplength, lmaplength;
38 int scrwidth, scrheight;
39 int gcolormap, lcolormap;
40 int bitperpixel, background;
41 int imageleft, imagetop;
42 int imagewidth, imageheight;
43 int interlaced, lbitperpixel;
44 int gray = 0;
45 int gammaflag = 0;
46 int negative = 0;
47 int terminate = 0;
48 int codesize, clearcode, endcode, curstblsize, pmindex, byteinibuf, bitsleft;
49 int prefix[4096], suffix[4096], cstbl[4096];
50 int bburx = -32767, bbury = -32767;
51 FILE *fp_in = NULL;
52 FILE *fp_out = stdout;
53
54 char *
55 allocate(size)
56     int size;
57 {
58     char *p;
59
60     if ((p = malloc(size)) == NULL) error(FATAL, "not enough memory");
61     return(p);
62 }
63
64 void
65 puthex(c, fp)
66     unsigned char c;
67     FILE *fp;
68 {
69     static char hextbl[16] = {
70         '0', '1', '2', '3', '4', '5', '6', '7',
71         '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
72     };
73
74     putc(hextbl[(c >> 4) & 017], fp);
75     putc(hextbl[c & 017], fp);
76 }
77
78 void
79 setcolormap(bp)
80     int bp;
81 {
82     int i, entries = 1, scale = 1;
83     unsigned char *p, *q;
84
85     for (i = 0; i < bp; i++) entries *= 2;
86     for (i = 0; i < 8 - bp; i++) scale *= 2;
87     gcmap = (unsigned char *) allocate(entries*3);
88     ggmap = (unsigned char *) allocate(entries);
89     gmaplength = entries;
90     for (i = 0, p = gcmap, q = ggmap; i < 256; i += scale, p += 3, q++) {
91         if (negative) {
92             *p = 255 - i; p[1] = *p; p[2] = *p;
93             *q = *p;
94         }
95         else {
96             *p = i; p[1] = i; p[2] = i;
97             *q = i;
98         }
99     }
100     if (gammaflag)
101         for (i = 0, p = gcmap; i < 256; i += scale, p += 3) {
102             *p = (unsigned char) (pow((double) *p/256.0, gamma)*256);
103             p[1] = *p; p[2] = *p;
104         }
105 dbprt(stderr,"default color map:\n");
106 for (i = 0; i < entries*3; i += 3)
107 dbprt(stderr, "%d, %d, %d\n", gcmap[i], gcmap[i+1], gcmap[i+2]);
108 }
109
110 void
111 readgcolormap(bp)
112     int bp;
113 {
114     int i, entries = 1;
115     unsigned char *p, *q;
116
117     for (i = 0; i < bp; i++) entries *= 2;
118     gcmap = (unsigned char *) allocate(entries*3);
119     ggmap = (unsigned char *) allocate(entries);
120     gmaplength = entries;
121     fread(gcmap, sizeof(*gcmap), entries*3, fp_in);
122     if (negative)
123         for (i = 0, p = gcmap; i < entries*3; i++, p++) *p = 255 - *p;
124     for (i = 0, p = gcmap, q = ggmap; i < entries; i++, p += 3, q++)
125         *q = cr*(int)p[0] + cg*(int)p[1] + cb*(int)p[2] + 0.5;
126     if (gammaflag)
127         for (i = 0, p = gcmap; i < entries*3; i++, p++)
128             *p = (unsigned char) (pow((double) *p/256.0, gamma)*256);
129 dbprt(stderr,"global color map:\n");
130 for (i = 0; i < entries*3; i += 3)
131 dbprt(stderr, "%d, %d, %d\n", gcmap[i], gcmap[i+1], gcmap[i+2]);
132 }
133
134 void
135 readlcolormap(bp)
136     int bp;
137 {
138     int i, entries = 1;
139     unsigned char *p, *q;
140
141     for (i = 0; i < bp; i++) entries *= 2;
142     lcmap = (unsigned char *) allocate(entries*3);
143     lgmap = (unsigned char *) allocate(entries);
144     lmaplength = entries;
145     fread(lcmap, sizeof(*lcmap), entries*3, fp_in);
146     if (negative)
147         for (i = 0, p = lcmap; i < entries*3; i++, p++) *p = 255 - *p;
148     for (i = 0, p = lcmap, q = lgmap; i < entries; i++, p += 3, q++)
149         *q = cr*(int)p[0] + cg*(int)p[1] + cb*(int)p[2] + 0.5;
150     if (gammaflag)
151         for (i = 0, p = lcmap; i < entries*3; i++, p++)
152             *p = (unsigned char) (pow((double) *p/256.0, gamma)*256);
153 dbprt(stderr,"local color map:\n");
154 for (i = 0; i < entries*3; i += 3)
155 dbprt(stderr, "%d, %d, %d\n", lcmap[i], lcmap[i+1], lcmap[i+2]);
156 }
157
158 void
159 initstbl()
160 {
161     int i, entries = 1, *p, *s;
162
163     for (i = 0; i < codesize; i++) entries *= 2;
164     clearcode = entries;
165     endcode = clearcode + 1;
166     for (i = 0, p = prefix, s = suffix; i <= endcode; i++, p++, s++) {
167         *p = endcode;
168         *s = i;
169     }
170     curstblsize = endcode + 1;
171     pmindex = 0;
172     byteinibuf = 0;
173     bitsleft = 0;
174 }
175
176 int
177 nextbyte()
178 {
179     static ibufindex;
180
181     if (byteinibuf) {
182         byteinibuf--;
183         ibufindex++;
184     }
185     else {
186         fread(ibuf, sizeof(*ibuf), 1, fp_in);
187         byteinibuf = ibuf[0];
188 dbprt(stderr, "byte count: %d\n", byteinibuf);
189         if (byteinibuf) fread(ibuf, sizeof(*ibuf), byteinibuf, fp_in);
190         else error(FATAL, "encounter zero byte count block before end code");
191         ibufindex = 0;
192         byteinibuf--;
193         ibufindex++;
194     }
195     return(ibuf[ibufindex-1]);
196 }
197
198 int masktbl[25] = {
199     0, 01, 03, 07, 017, 037, 077, 0177, 0377, 0777, 01777, 03777, 07777,
200     017777, 037777, 077777, 0177777, 0377777, 0777777, 01777777, 03777777,
201     07777777, 017777777, 037777777, 077777777
202 };
203
204 int
205 getcode()
206 {
207     int cs, c;
208     static int oldc;
209
210     if (curstblsize < 4096) cs = cstbl[curstblsize];
211     else cs = 12;
212     while (bitsleft < cs) {
213         oldc = (oldc & masktbl[bitsleft]) | ((nextbyte() & 0377) << bitsleft);
214         bitsleft += 8;
215     }
216     c = oldc & masktbl[cs];
217     oldc = oldc >> cs;
218     bitsleft -= cs;
219 /* dbprt(stderr, "code: %d %d %d\n", curstblsize, cs, c); */
220     return(c);
221 }
222
223 void
224 putcode(c)
225     int c;
226 {
227     if (prefix[c] != endcode) {
228         putcode(prefix[c]);
229         pmap[pmindex] = suffix[c];
230         pmindex++;
231     }
232     else {
233         pmap[pmindex] = suffix[c];
234         pmindex++;
235     }
236 }
237
238 int
239 firstof(c)
240     int c;
241 {
242     while (prefix[c] != endcode) c = prefix[c];
243     return(suffix[c]);
244 }
245
246 void
247 writeimage()
248 {
249     int i, j, k;
250
251 dbprt(stderr, "pmindex: %d\n", pmindex);
252     fputs("save\n", fp_out);
253     fprintf(fp_out, "/codestr %d string def\n", imagewidth);
254     if (!gray) {
255         fprintf(fp_out, "/colortbl currentfile %d string readhexstring\n",
256             maplength*3);
257         for (i = 0; i < maplength; i++) puthex(cmap[i], fp_out);
258         fputs("\n", fp_out);
259         for (i = maplength ; i < maplength*2; i++) puthex(cmap[i], fp_out);
260         fputs("\n", fp_out);
261         for (i = maplength*2 ; i < maplength*3; i++) puthex(cmap[i], fp_out);
262         fputs("\npop def\n", fp_out);
263         fprintf(fp_out, "/graytbl currentfile %d string readhexstring\n",
264             maplength);
265         for (i = 0; i < maplength; i++) puthex(gmap[i], fp_out);
266         fputs("\npop def\n", fp_out);
267     }
268     fprintf(fp_out, "%s %d %d %d %d gifimage\n",
269         gray ? "true" : "false", imagewidth, imageheight,
270         scrwidth - imageleft - imagewidth, scrheight - imagetop - imageheight);
271     if (gray) {
272         if (interlaced) {
273             int *iltbl;
274
275             iltbl = (int *) allocate(imageheight*sizeof(int));
276             j = 0;
277             for (i = 0; i < imageheight; i += 8) {
278                 iltbl[i] = j;
279                 j += imagewidth;
280             }
281 dbprt(stderr, "pass1: %d\n", j);
282             for (i = 4; i < imageheight; i += 8) {
283                 iltbl[i] = j;
284                 j += imagewidth;
285             }
286 dbprt(stderr, "pass2: %d\n", j);
287             for (i = 2; i < imageheight; i += 4) {
288                 iltbl[i] = j;
289                 j += imagewidth;
290             }
291 dbprt(stderr, "pass3: %d\n", j);
292             for (i = 1; i < imageheight; i += 2) {
293                 iltbl[i] = j;
294                 j += imagewidth;
295             }
296 dbprt(stderr, "pass4: %d\n", j);
297
298             for (i = 0; i < imageheight; i++) {
299                 k = iltbl[i];
300                 for (j = 0; j < imagewidth; j++, k++)
301                     puthex(gmap[pmap[k]], fp_out);
302                 fputs("\n", fp_out);
303             }
304         }
305         else {
306             for (i = 0, k = 0; i < imageheight; i++) {
307                 for (j = 0; j < imagewidth; j++, k++)
308                     puthex(gmap[pmap[k]], fp_out);
309                 fputs("\n", fp_out);
310             }
311         }
312     }
313     else {
314         if (interlaced) {
315             int *iltbl;
316
317             iltbl = (int *) allocate(imageheight*sizeof(int));
318             j = 0;
319             for (i = 0; i < imageheight; i += 8) {
320                 iltbl[i] = j;
321                 j += imagewidth;
322             }
323 dbprt(stderr, "pass1: %d\n", j);
324             for (i = 4; i < imageheight; i += 8) {
325                 iltbl[i] = j;
326                 j += imagewidth;
327             }
328 dbprt(stderr, "pass2: %d\n", j);
329             for (i = 2; i < imageheight; i += 4) {
330                 iltbl[i] = j;
331                 j += imagewidth;
332             }
333 dbprt(stderr, "pass3: %d\n", j);
334             for (i = 1; i < imageheight; i += 2) {
335                 iltbl[i] = j;
336                 j += imagewidth;
337             }
338 dbprt(stderr, "pass4: %d\n", j);
339
340             for (i = 0; i < imageheight; i++) {
341                 k = iltbl[i];
342                 for (j = 0; j < imagewidth; j++, k++) puthex(pmap[k], fp_out);
343                 fputs("\n", fp_out);
344             }
345         }
346         else {
347             for (i = 0, k = 0; i < imageheight; i++) {
348                 for (j = 0; j < imagewidth; j++, k++) puthex(pmap[k], fp_out);
349                 fputs("\n", fp_out);
350             }
351         }
352     }
353     fputs("restore\n", fp_out);
354 }
355
356 void
357 readimage()
358 {
359     int bytecount, zerobytecount = 0;
360     int code, oldcode;
361
362     fread(ibuf, sizeof(*ibuf), 9, fp_in);
363     imageleft = ibuf[0] + 256*ibuf[1];
364     imagetop = ibuf[2] + 256*ibuf[3];
365     imagewidth = ibuf[4] + 256*ibuf[5];
366     imageheight = ibuf[6] + 256*ibuf[7];
367     lcolormap = ibuf[8] & 0200;
368     interlaced = ibuf[8] & 0100;
369     lbitperpixel = (ibuf[8] & 07) + 1;
370 dbprt(stderr, "imageleft: %d\n", imageleft);
371 dbprt(stderr, "imagetop: %d\n", imagetop);
372 dbprt(stderr, "imagewidth: %d\n", imagewidth);
373 dbprt(stderr, "imgaeheight: %d\n", imageheight);
374 dbprt(stderr, "lcolormap: %d\n", lcolormap ? 1 : 0);
375 dbprt(stderr, "interlaced: %d\n", interlaced ? 1 : 0);
376 dbprt(stderr, "lbitperpixel: %d\n", lbitperpixel);
377     if (lcolormap) {
378         readlcolormap(lbitperpixel);
379         cmap = lcmap;
380         gmap = lgmap;
381         maplength = lmaplength;
382     }
383
384 dbprt(stderr, "start reading raster data\n");
385     fread(ibuf, sizeof(*ibuf), 1, fp_in);
386     codesize = ibuf[0];
387 dbprt(stderr, "codesize: %d\n", codesize);
388     pmap = (unsigned char *) allocate(imagewidth*imageheight);
389     initstbl();
390     while ((code = getcode()) != endcode) {
391         if (code == clearcode) {
392             curstblsize = endcode + 1;
393             code = getcode();
394             putcode(code);
395             oldcode = code;
396         }
397         else if (code < curstblsize) {
398             putcode(code);
399             prefix[curstblsize] = oldcode;
400             suffix[curstblsize] = firstof(code);
401             curstblsize++;
402             oldcode = code;
403         }
404         else {
405            if (code != curstblsize) error(FATAL, "code out of order");
406            prefix[curstblsize] = oldcode;
407            suffix[curstblsize] = firstof(oldcode);
408            curstblsize++;
409            putcode(curstblsize-1);
410            oldcode = code;
411         }
412     }
413 dbprt(stderr, "finish reading raster data\n");
414
415     /* read the rest of the raster data */
416     do {
417         fread(ibuf, sizeof(*ibuf), 1, fp_in);
418         bytecount = ibuf[0];
419 dbprt(stderr, "byte count: %d\n", bytecount);
420         if (bytecount) fread(ibuf, sizeof(*ibuf), bytecount, fp_in);
421         else zerobytecount = 1;
422     } while (!zerobytecount);
423
424     writeimage();
425
426     if (lcolormap) {
427         cmap = gcmap;
428         gmap = ggmap;
429         maplength = gmaplength;
430         free(lcmap);
431         free(lgmap);
432     }
433 }
434
435 void
436 readextensionblock()
437 {
438     int functioncode, bytecount, zerobytecount = 0;
439
440     fread(ibuf, sizeof(*ibuf), 1, fp_in);
441     functioncode = ibuf[0];
442 dbprt(stderr, "function code: %d\n", functioncode);
443     do {
444         fread(ibuf, sizeof(*ibuf), 1, fp_in);
445         bytecount = ibuf[0];
446 dbprt(stderr, "byte count: %d\n", bytecount);
447         if (bytecount) fread(ibuf, sizeof(*ibuf), bytecount, fp_in);
448         else zerobytecount = 1;
449     } while (!zerobytecount);
450 }
451
452 void
453 writebgscr()
454 {
455     fprintf(fp_out, "%s %d %d\n", PAGE, page, printed+1);
456     fputs("/saveobj save def\n", fp_out);
457     fprintf(fp_out, "%s: %d %d %d %d\n",
458         "%%PageBoundingBox", 0, 0, scrwidth, scrheight);
459     if (scrwidth > bburx) bburx = scrwidth;
460     if (scrheight > bbury) bbury = scrheight;
461     fprintf(fp_out, "%d %d gifscreen\n", scrwidth, scrheight);
462 }
463
464 void
465 writeendscr()
466 {
467     if ( fp_out == stdout ) printed++;
468     fputs("showpage\n", fp_out);
469     fputs("saveobj restore\n", fp_out);
470     fprintf(fp_out, "%s %d %d\n", ENDPAGE, page, printed);
471 }
472
473 void
474 redirect(pg)
475     int         pg;                     /* next page we're printing */
476 {
477     static FILE *fp_null = NULL;        /* if output is turned off */
478
479     if ( pg >= 0 && in_olist(pg) == ON )
480         fp_out = stdout;
481     else if ( (fp_out = fp_null) == NULL )
482         fp_out = fp_null = fopen("/dev/null", "w");
483
484 }
485
486 void
487 readgif()
488 {
489     int i, j, k;
490
491     for (i = 0, j = 1, k = 0; i < 13; i++) {
492         for (; k < j; k++) cstbl[k] = i;
493         j *= 2;
494     }
495
496     fread(ibuf, sizeof(*ibuf), 6, fp_in);
497 dbprt(stderr, "%.6s\n", ibuf);
498     if (strncmp((char *)ibuf, "GIF87a", 6) != 0) {
499         fread(ibuf, sizeof(*ibuf), 122, fp_in);
500         fread(ibuf, sizeof(*ibuf), 6, fp_in);
501 dbprt(stderr, "%.6s\n", ibuf);
502         if (strncmp((char *)ibuf, "GIF87a", 6) != 0)
503                  error(FATAL, "wrong GIF signature");
504     }
505     fread(ibuf, sizeof(*ibuf), 7, fp_in);
506     scrwidth = ibuf[0] + 256*ibuf[1];
507     scrheight = ibuf[2] + 256*ibuf[3];
508     gcolormap = ibuf[4] & 0200;
509     bitperpixel = (ibuf[4] & 07) + 1;
510     background = ibuf[5];
511 dbprt(stderr, "scrwidth: %d\n", scrwidth);
512 dbprt(stderr, "scrheight: %d\n", scrheight);
513 dbprt(stderr, "gcolormap: %d\n", gcolormap ? 1 : 0);
514 dbprt(stderr, "bitperpixel: %d\n", bitperpixel);
515 dbprt(stderr, "background: %d\n", background);
516     if (ibuf[6] != 0) error(FATAL, "wrong screen descriptor");
517     if (gcolormap) readgcolormap(bitperpixel);
518     else setcolormap(bitperpixel);
519
520     redirect(++page);
521     writebgscr();
522
523     cmap = gcmap;
524     gmap = ggmap;
525     maplength = gmaplength;
526
527     do {
528         fread(ibuf, sizeof(*ibuf), 1, fp_in);
529         if (ibuf[0] == ',') readimage();
530         else if (ibuf[0] == ';') terminate = 1;
531         else if (ibuf[0] == '!') readextensionblock();
532         else
533         error(FATAL, "wrong image separator character or wrong GIF terminator");
534     } while (!terminate);
535
536     writeendscr();
537
538     free(gcmap);
539     free(ggmap);
540 }
541
542 void
543 init_signals()
544 {
545
546     if ( signal(SIGINT, interrupt) == SIG_IGN )  {
547         signal(SIGINT, SIG_IGN);
548         signal(SIGQUIT, SIG_IGN);
549         signal(SIGHUP, SIG_IGN);
550     }
551     else {
552         signal(SIGHUP, interrupt);
553         signal(SIGQUIT, interrupt);
554     }
555
556     signal(SIGTERM, interrupt);
557 }
558
559 void
560 header()
561 {
562     int         ch;                     /* return value from getopt() */
563     int         old_optind = optind;    /* for restoring optind - should be 1 */
564
565     while ( (ch = getopt(argc, argv, optnames)) != EOF )
566         if ( ch == 'L' )
567             prologue = optarg;
568         else if ( ch == '?' )
569             error(FATAL, "");
570
571     optind = old_optind;                /* get ready for option scanning */
572
573     fprintf(stdout, "%s", CONFORMING);
574     fprintf(stdout, "%s %s\n", VERSION, PROGRAMVERSION);
575     fprintf(stdout, "%s %s\n", BOUNDINGBOX, ATEND);
576     fprintf(stdout, "%s %s\n", PAGES, ATEND);
577     fprintf(stdout, "%s", ENDCOMMENTS);
578
579     if ( cat(prologue) == FALSE )
580         error(FATAL, "can't read %s", prologue);
581
582     fprintf(stdout, "%s", ENDPROLOG);
583     fprintf(stdout, "%s", BEGINSETUP);
584     fprintf(stdout, "mark\n");
585
586 }
587
588 void
589 options()
590 {
591     int         ch;                     /* return value from getopt() */
592
593     while ( (ch = getopt(argc, argv, optnames)) != EOF )  {
594         switch ( ch )  {
595
596             case 'a':                   /* aspect ratio */
597                     fprintf(stdout, "/aspectratio %s def\n", optarg);
598                     break;
599
600             case 'c':                   /* copies */
601                     copies = atoi(optarg);
602                     fprintf(stdout, "/#copies %s store\n", optarg);
603                     break;
604
605             case 'f':
606                     negative = TRUE;
607                     break;
608
609             case 'g':
610                     gray = TRUE;
611                     break;
612
613             case 'l':
614                     fprintf(stdout, "/alignment true def\n");
615                     break;
616
617             case 'm':                   /* magnification */
618                     fprintf(stdout, "/magnification %s def\n", optarg);
619                     break;
620
621             case 'n':                   /* forms per page */
622                     formsperpage = atoi(optarg);
623                     fprintf(stdout, "%s %s\n", FORMSPERPAGE, optarg);
624                     fprintf(stdout, "/formsperpage %s def\n", optarg);
625                     break;
626
627             case 'o':                   /* output page list */
628                     out_list(optarg);
629                     break;
630
631             case 'p':                   /* landscape or portrait mode */
632                     if ( *optarg == 'l' )
633                         fprintf(stdout, "/landscape true def\n");
634                     else fprintf(stdout, "/landscape false def\n");
635                     break;
636
637             case 'x':                   /* shift things horizontally */
638                     fprintf(stdout, "/xoffset %s def\n", optarg);
639                     break;
640
641             case 'y':                   /* and vertically on the page */
642                     fprintf(stdout, "/yoffset %s def\n", optarg);
643                     break;
644
645             case 'C':                   /* copy file straight to output */
646                     if ( cat(optarg) == FALSE )
647                         error(FATAL, "can't read %s", optarg);
648                     break;
649
650             case 'E':                   /* text font encoding - unnecessary */
651                     fontencoding = optarg;
652                     break;
653
654             case 'D':                   /* debug flag */
655                     debug = ON;
656                     break;
657
658             case 'G':
659                     gammaflag = ON;
660                     gamma = atof(optarg);
661                     break;
662
663             case 'I':                   /* ignore FATAL errors */
664                     ignore = ON;
665                     break;
666
667             case 'L':                   /* PostScript prologue file */
668                     prologue = optarg;
669                     break;
670
671             case 'P':                   /* PostScript pass through */
672                     fprintf(stdout, "%s\n", optarg);
673                     break;
674
675             case '?':                   /* don't understand the option */
676                     error(FATAL, "");
677                     break;
678
679             default:                    /* don't know what to do for ch */
680                     error(FATAL, "missing case for option %c\n", ch);
681                     break;
682
683         }
684     }
685
686     argc -= optind;                     /* get ready for non-option args */
687     argv += optind;
688 }
689
690 void
691 setup()
692 {
693     /*setencoding(fontencoding);*/
694     fprintf(stdout, "setup\n");
695
696     if ( formsperpage > 1 )  {          /* followed by stuff for multiple pages
697 */
698         if ( cat(formfile) == FALSE )
699             error(FATAL, "can't read %s", formfile);
700         fprintf(stdout, "%d setupforms\n", formsperpage);
701     }   /* End if */
702
703     fprintf(stdout, "%s", ENDSETUP);
704
705 }
706
707 void
708 arguments()
709 {
710     if ( argc < 1 ) {
711         fp_in = stdin;
712         readgif();
713     }
714     else  {                             /* at least one argument is left */
715         while ( argc > 0 )  {
716             if ( strcmp(*argv, "-") == 0 )
717                 fp_in = stdin;
718             else if ( (fp_in = fopen(*argv, "r")) == NULL )
719                 error(FATAL, "can't open %s", *argv);
720             readgif();
721             if ( fp_in != stdin )
722                 fclose(fp_in);
723             argc--;
724             argv++;
725         }
726     }
727 }
728
729 void
730 done()
731 {
732     fprintf(stdout, "%s", TRAILER);
733     fprintf(stdout, "done\n");
734     fprintf(stdout, "%s 0 0 %d %d\n", BOUNDINGBOX, bburx, bbury);
735     fprintf(stdout, "%s %d\n", PAGES, printed); 
736 }
737
738 main(agc, agv)
739     int agc;
740     char *agv[];
741 {
742     argc = agc;
743     argv = agv;
744     prog_name = argv[0];
745
746     init_signals();
747     header();
748     options();
749     setup();
750     arguments();
751     done();
752
753     exit(0);
754 }
755