1 /*
2 * This is the main routine.
3 */
4 #include "dvips.h" /* The copyright notice there is included too! */
5 #ifdef KPATHSEA
6 #include <kpathsea/c-pathch.h>
7 #include <kpathsea/proginit.h>
8 #include <kpathsea/progname.h>
9 #include <kpathsea/tex-hush.h>
10 #include <kpathsea/tex-make.h>
11 #include <kpathsea/variable.h>
12 #include <kpathsea/version.h>
13 #include <kpathsea/lib.h>
14 #ifdef strdup
15 #undef strdup
16 #endif
17 #define strdup xstrdup
18 #include "paths.h"
19 #else /* ! KPATHSEA */
20 #include <stdlib.h> /* for malloc, etc. */
21 #if !defined(SYSV) && !defined(WIN32)
22 extern char *strtok(); /* some systems don't have this in strings.h */
23 #endif
24 #if defined(WIN32)
25 #include <io.h>
26 #include <fcntl.h>
27 #include <string.h>
28 #define O_BINARY _O_BINARY
29 #endif
30 #define DIR_SEP DIRSEP
31 #endif /* KPATHSEA */
32 #ifdef VMS
33 #define GLOBAL globaldef
34 #ifdef __GNUC__
35 #include "climsgdef.h" /* created by hand, extracted from STARLET.MLB */
36 /* and put in GNU_CC:[INCLUDE.LOCAL] */
37 #include "ctype.h"
38 #include "descrip.h"
39 #else
40 #include climsgdef
41 #include ctype
42 #include descrip
43 #endif
44 #endif
45 #ifdef __APPLE__ /* for Mac OS X, T. Uchiyama */
46 #include <sys/types.h>
47 #include <sys/time.h>
48 #include <sys/resource.h>
49 #endif
50
51 #if defined(WIN32) && defined(KPATHSEA)
52 #undef fopen
53 #define fopen(file, fmode) fsyscp_fopen(file, fmode)
54 #endif
55
56 #ifndef DEFRES
57 #define DEFRES (600)
58 #endif
59
60 /*
61 * The external declarations:
62 */
63 #include "protos.h"
64
65 /*
66 * First we define some globals.
67 */
68 #ifdef VMS
69 static char ofnme[252],infnme[252],pap[40],thh[20];
70 #endif
71
72 /* PS fonts fully downloaded as headers */
73 char *downloadedpsnames[DOWNLOADEDPSSIZE];
74
75 int unused_top_of_psnames; /* unused top number of downloadedpsnames[#] */
76 fontdesctype *fonthead; /* list of all fonts mentioned so far */
77 fontdesctype *curfnt; /* the currently selected font */
78 sectiontype *sections; /* sections to process document in */
79 Boolean partialdownload = 1; /* turn on partial downloading */
80 Boolean manualfeed; /* manual feed? */
81 Boolean compressed; /* compressed? */
82 Boolean downloadpspk; /* use PK for downloaded PS fonts? */
83 Boolean safetyenclose; /* enclose in save/restore for stupid spoolers? */
84 Boolean removecomments = 0; /* remove comments from included PS? */
85 Boolean nosmallchars; /* disable small char optimization for X4045? */
86 Boolean cropmarks; /* add cropmarks? */
87 Boolean abspage = 0; /* are page numbers absolute? */
88 Boolean tryepsf = 0; /* should we try to make it espf? */
89 int secure = 1; /* make safe for suid */
90 int secure_option = 0; /* set by -R */
91 int collatedcopies = 1; /* how many collated copies? */
92 int sectioncopies = 1; /* how many times to repeat each section? */
93 integer pagecopies = 1; /* how many times to repeat each page? */
94 shalfword linepos = 0; /* where are we on the line being output? */
95 integer maxpages; /* the maximum number of pages */
96 Boolean notfirst, notlast; /* true if a first page was specified */
97 Boolean evenpages, oddpages; /* true if doing only even/only odd pages */
98 Boolean pagelist; /* true if using page ranges */
99 Boolean sendcontrolD; /* should we send a control D at end? */
100 Boolean shiftlowchars; /* shift [0-32, 127] characters higher? */
101 integer firstpage; /* the number of the first page if specified */
102 integer lastpage;
103 integer firstseq;
104 integer lastseq;
105 integer hpapersize, vpapersize; /* horizontal and vertical paper size */
106 integer hoff, voff; /* horizontal and vertical offsets */
107 integer maxsecsize = 0; /* the maximum size of a section */
108 integer firstboploc; /* where the first bop is */
109 Boolean sepfiles; /* each section in its own file? */
110 int numcopies; /* number of copies of each page to print */
111 const char *oname; /* output file name */
112 char *iname; /* dvi file name */
113 char *fulliname; /* same, with current working directory */
114 char *strings; /* strings for program */
115 char *nextstring, *maxstring; /* string pointers */
116 FILE *dvifile, *bitfile; /* dvi and output files */
117 quarterword *curpos; /* current position in virtual character packet */
118 quarterword *curlim; /* final byte in virtual character packet */
119 fontmaptype *ffont; /* first font in current frame */
120 real conv; /* conversion ratio, pixels per DVI unit */
121 real vconv; /* conversion ratio, pixels per DVI unit */
122 real alpha; /* conversion ratio, DVI unit per TFM unit */
123 double mag; /* the magnification of this document */
124 integer num, den; /* the numerator and denominator */
125 int overridemag; /* substitute for mag value in DVI file? */
126 int actualdpi = DEFRES; /* the actual resolution of the printer */
127 int vactualdpi = DEFRES; /* the actual resolution of the printer */
128 int maxdrift; /* max pixels away from true rounded position */
129 int vmaxdrift; /* max pixels away from true rounded position */
130 char *paperfmt; /* command-line paper format */
131 int landscape = 0; /* landscape mode */
132 integer fontmem; /* memory remaining in printer */
133 integer pagecount; /* page counter for the sections */
134 integer pagenum; /* the page number we currently look at */
135 long bytesleft; /* number of bytes left in raster */
136 quarterword *raster; /* area for raster manipulations */
137 integer hh, vv; /* horizontal and vertical pixel positions */
138 Boolean noomega = 0; /* Omega extensions are enabled */
139 Boolean noptex = 0; /* pTeX extensions are enabled */
140
141 /*-----------------------------------------------------------------------*
142 * The PATH definitions cannot be defined on the command line because so many
143 * DEFINE's overflow the DCL buffer when using the GNU CC compiler.
144 *-----------------------------------------------------------------------*/
145 #if defined(VMS) && defined(__GNUC__)
146 #include "vms_gcc_paths.h"
147 #endif
148
149 const char *infont; /* is the file we are downloading a font? */
150 #ifndef KPATHSEA
151 #ifdef ATARIST
152 # define TFMPATH "."
153 # define PKPATH "."
154 # define VFPATH "."
155 # define FIGPATH "."
156 # define HEADERPATH "."
157 # define CONFIGPATH "."
158 #endif
159 char *tfmpath = TFMPATH; /* pointer to directories for tfm files */
160 char *pkpath = PKPATH; /* pointer to directories for pk files */
161 char *vfpath = VFPATH; /* pointer to directories for vf files */
162 char *figpath = FIGPATH; /* pointer to directories for figure files */
163 char *headerpath = HEADERPATH; /* pointer to directories for header files */
164 char *configpath = CONFIGPATH; /* where to find config files */
165 #ifndef PICTPATH
166 #ifndef __THINK__
167 #define PICTPATH "."
168 #else
169 #define PICTPATH ":"
170 #endif
171 #endif
172 char *pictpath = PICTPATH; /* where IFF/etc. pictures are found */
173 #ifdef SEARCH_SUBDIRECTORIES
174 char *fontsubdirpath = FONTSUBDIRPATH;
175 #endif
176 #endif /* ! KPATHSEA */
177 #ifdef FONTLIB
178 char *flipath = FLIPATH; /* pointer to directories for fli files */
179 char *fliname = FLINAME; /* pointer to names of fli files */
180 #endif
181 integer swmem; /* font memory in the PostScript printer */
182 int quiet; /* should we only print errors to stderr? */
183 int filter; /* act as filter default output to stdout,
184 default input to stdin? */
185 int dvips_debug_flag; /* output config and map files to stderr if 1 */
186 int prettycolumn; /* the column we are at when running pretty */
187 int gargc; /* global argument count */
188 char **gargv; /* global argument vector */
189 int totalpages = 0; /* total number of pages */
190 Boolean reverse; /* are we going reverse? */
191 Boolean usesPSfonts; /* do we use local PostScript fonts? */
192 Boolean usesspecial; /* do we use \special? */
193 Boolean headers_off; /* do we send headers or not? */
194 Boolean usescolor; /* IBM: color - do we use colors? */
195 const char *headerfile; /* default header file */
196 char *warningmsg; /* a message to write, if set in config file */
197 Boolean multiplesects; /* more than one section? */
198 Boolean disablecomments; /* should we suppress any EPSF comments? */
199 char *printer; /* what printer to send this to? */
200 char *mfmode; /* default MF mode */
201 char *mflandmode; /* allow an optional landscape mode def */
202 int mfmode_option; /* set by -mode command-line option */
203 int oname_option; /* set by -o option */
204 frametype frames[MAXFRAME]; /* stack for virtual fonts */
205 integer pagecost; /* memory used on the page being prescanned */
206 int delchar; /* characters to delete from prescanned page */
207 integer fsizetol; /* max dvi units error for psfile font sizes */
208 Boolean includesfonts; /* are fonts used in included psfiles? */
209 fontdesctype *fonthd[MAXFONTHD];/* list headers for included fonts of 1 name */
210 int nextfonthd; /* next unused fonthd[] index */
211 char xdig[256]; /* table for reading hexadecimal digits */
212 char banner[] = BANNER; /* our startup message */
213 char banner2[] = BANNER2; /* our second startup message */
214 Boolean noenv = 0; /* ignore PRINTER envir variable? */
215 Boolean dopprescan = 0; /* do we do a scan before the prescan? */
216 struct papsiz *papsizes; /* all available paper size */
217 int headersready; /* ready to check headers? */
218 #if defined(MSDOS) || defined(OS2) || defined(ATARIST)
219 char *mfjobname = NULL; /* name of mfjob file if given */
220 FILE *mfjobfile = NULL; /* mfjob file for font making instructions */
221 #endif
222 #ifdef DEBUG
223 integer debug_flag = 0;
224 #endif /* DEBUG */
225 char queryline[256]; /* interactive query of options */
226 int qargc;
227 char *qargv[32];
228 char queryoptions;
229 #ifdef HPS
230 Boolean HPS_FLAG = 0;
231 #endif
232
233 /* Declare the routine to get the current working directory. */
234
235 /* The getwd/getcwd stuff here is not portable, and I don't think it's
236 worth it to include xgetcwd.d just so we can print the full pathname
237 of the DVI file in the output. --karl */
238 #define IGNORE_CWD
239
240 #ifndef IGNORE_CWD
241 #ifndef HAVE_GETCWD
242 extern char *getwd (); /* said to be faster than getcwd (SunOS man page) */
243 #define getcwd(b, len) getwd(b) /* used here only when b nonnull */
244 #else
245 #ifdef ANSI
246 extern char *getcwd (char *, int);
247 #else
248 extern char *getcwd ();
249 #endif /* not ANSI */
250 #endif /* not HAVE_GETWD */
251 #if defined(SYSV) || defined(VMS) || (defined(MSDOS) && !defined(__DJGPP__)) || defined(OS2) || defined(ATARIST)
252 #define MAXPATHLEN (256)
253 #else
254 #include <sys/param.h> /* for MAXPATHLEN */
255 #endif
256 #endif /* not IGNORE_CWD */
257
258 static const char *helparr[] = {
259 #ifndef VMCMS
260 "Usage: dvips [OPTION]... FILENAME[.dvi]",
261 #else
262 " VM/CMS Usage:",
263 " dvips fname [ftype [fmode]] [options]",
264 "or",
265 " dvips fname[.ftype[.fmode]] [options]",
266 #endif
267 "Convert DVI input files to PostScript.",
268 "See http://tug.org/dvips/ for the full manual and other information.",
269 "",
270 "Options:",
271 "-a* Conserve memory, not time -A Print only odd (TeX) pages",
272 "-b # Page copies, for posters e.g. -B Print only even (TeX) pages",
273 "-c # Uncollated copies -C # Collated copies",
274 "-d # Debugging -D # Resolution",
275 "-e # Maxdrift value -E* Try to create EPSF",
276 "-f* Run as filter -F* Send control-D at end",
277 #ifdef SHIFTLOWCHARS
278 " -G* Shift low chars to higher pos.",
279 #endif
280 "-h f Add header file",
281 "-i* Separate file per section",
282 "-j* Download fonts partially",
283 "-k* Print crop marks -K* Pull comments from inclusions",
284 "-l # Last page",
285 "-m* Manual feed -M* Don't make fonts",
286 "-mode s Metafont device name",
287 "-n # Maximum number of pages -N* No structured comments",
288 "-noomega Disable Omega extensions",
289 "-noptex Disable pTeX extensions",
290 "-o f Output file -O c Set/change paper offset",
291 #if defined(MSDOS) || defined(OS2)
292 "-p # First page -P s Load $s.cfg",
293 #else
294 "-p # First page -P s Load config.$s",
295 #endif
296 "-pp l Print only pages listed",
297 "-q* Run quietly",
298 "-r* Reverse order of pages -R* Run securely",
299 "-s* Enclose output in save/restore -S # Max section size in pages",
300 "-t s Paper format -T c Specify desired page size",
301 "-u s PS mapfile -U* Disable string param trick",
302 "-v Print version number and quit -V* Send downloadable PS fonts as PK",
303 "-x # Override dvi magnification -X # Horizontal resolution",
304 "-y # Multiply by dvi magnification -Y # Vertical resolution",
305 #ifdef HPS
306 "-z* Hyper PS -Z* Compress bitmap fonts",
307 #else
308 " -Z* Compress bitmap fonts",
309 #endif
310 /*"- Interactive query of options", */
311 " # = number f = file s = string * = suffix, `0' to turn off",
312 " c = comma-separated dimension pair (e.g., 3.2in,-32.1cm)",
313 " l = comma-separated list of page ranges (e.g., 1-4,7-9)", 0};
314
315 void
help(int status)316 help(int status)
317 {
318 const char **p;
319 FILE *f = status == 0 ? stdout : stderr;
320 for (p=helparr; *p; p++)
321 fprintf (f, "%s\n", *p);
322
323 putc ('\n', f);
324 #ifdef KPATHSEA
325 fputs (kpse_bug_address, f);
326 #endif
327 }
328
329 static void
freememforpsnames(void)330 freememforpsnames(void)
331 {
332 int i;
333
334 for (i = 0; i < unused_top_of_psnames && downloadedpsnames[i]; i++)
335 free (downloadedpsnames[i]);
336 }
337
338 /*
339 * This error routine prints an error message; if the first
340 * character is !, it aborts the job.
341 */
342
343 static char *progname;
344
345 void
error_with_perror(const char * s,const char * fname)346 error_with_perror(const char *s, const char *fname)
347 {
348 if (prettycolumn > 0)
349 fprintf(stderr,"\n");
350 prettycolumn = 0;
351 fprintf(stderr, "%s: %s", progname, s);
352 if (fname) {
353 putc (' ', stderr);
354 perror (fname);
355 } else {
356 putc ('\n', stderr);
357 }
358
359 if (*s=='!') {
360 freememforpsnames();
361 if (bitfile != NULL) {
362 cleanprinter();
363 }
364 exit(1); /* fatal */
365 }
366 }
367
368 /*
369 * This error routine prints an error message; if the first
370 * character is !, it aborts the job.
371 */
372 void
error(const char * s)373 error(const char *s)
374 {
375 error_with_perror (s, NULL);
376 }
377
378 #ifndef KPATHSEA
379 char *
concat(char * s1,char * s2)380 concat(char *s1, char *s2)
381 {
382 char *s = malloc(strlen(s1)+strlen(s2)+1);
383 if (s == NULL) {
384 fprintf(stderr, "Malloc failed to give %d bytes.\nAborting\n",
385 strlen(s1)+strlen(s2)+1);
386 exit(1);
387 }
388 strcpy(s, s1);
389 strcat(s, s2);
390 }
391 #endif
392
393 /* Report a warning if both checksums are nonzero, they don't match, and
394 the user hasn't turned it off. */
395
396 void
check_checksum(unsigned c1,unsigned c2,const char * name)397 check_checksum(unsigned c1, unsigned c2, const char *name)
398 {
399 if (c1 && c2 && c1 != c2
400 #ifdef KPATHSEA
401 && !kpse_tex_hush ("checksum")
402 #endif
403 ) {
404 char *msg = concat ("Checksum mismatch in %s", name);
405 error (msg);
406 free (msg);
407 }
408 }
409
410 /*
411 * This is our malloc that checks the results. We debug the
412 * allocations but not the frees, since memory fragmentation
413 * might be such that we can never use the free'd memory and
414 * it's wise to be conservative. The only real place we free
415 * is when repacking *huge* characters anyway.
416 */
417 #ifdef DEBUG
418 static integer totalalloc = 0;
419 #endif
420 char *
mymalloc(integer n)421 mymalloc(integer n)
422 {
423 char *p;
424
425 #ifdef SMALLMALLOC
426 if (n > 65500L)
427 error("! can't allocate more than 64K!");
428 #endif
429 if (n <= 0) /* catch strange 0 mallocs in flib.c without breaking code */
430 n = 1;
431 #ifdef DEBUG
432 totalalloc += n;
433 if (dd(D_MEM)) {
434 #ifdef SHORTINT
435 fprintf(stderr, "Alloc %ld\n", n);
436 #else
437 fprintf(stderr, "Alloc %d\n", n);
438 #endif
439 }
440 #endif
441 p = (char *) malloc(n);
442 if (p == NULL)
443 error("! no memory");
444 return p;
445 }
446 static void
morestrings(void)447 morestrings(void) {
448 strings = mymalloc((integer)STRINGSIZE);
449 nextstring = strings;
450 maxstring = strings + STRINGSIZE - 200;
451 *nextstring++ = 0;
452 }
453 void
checkstrings(void)454 checkstrings(void) {
455 if (nextstring - strings > STRINGSIZE / 2)
456 morestrings();
457 }
458 /*
459 * Initialize sets up all the globals and data structures.
460 */
461 static void
initialize(void)462 initialize(void)
463 {
464 int i;
465 const char *s;
466
467 nextfonthd = 0;
468 for (i=0; i<256; i++)
469 xdig[i] = 0;
470 i = 0;
471 for (s="0123456789ABCDEF"; *s!=0; s++)
472 xdig[(int)*s] = i++;
473 i = 10;
474 for (s="abcdef"; *s!=0; s++)
475 xdig[(int)*s] = i++;
476 for(i=0; i < DOWNLOADEDPSSIZE; i++)
477 downloadedpsnames[i] = NULL;
478 unused_top_of_psnames = 0;
479 morestrings();
480 maxpages = 100000;
481 numcopies = 1;
482 iname = fulliname = strings;
483 bitfile = NULL;
484 bytesleft = 0;
485 swmem = SWMEM;
486 oname = OUTPATH;
487 sendcontrolD = 0;
488 shiftlowchars = 0;
489 multiplesects = 0;
490 disablecomments = 0;
491 maxdrift = -1;
492 vmaxdrift = -1;
493 dontmakefont = !MAKE_TEX_PK_BY_DEFAULT;
494 }
495 /*
496 * This routine copies a string into the string `pool', safely.
497 */
498 char *
newstring(const char * s)499 newstring(const char *s)
500 {
501 int l;
502 char *q;
503
504 if (s == NULL)
505 return(NULL);
506 l = strlen(s);
507 if (nextstring + l >= maxstring)
508 morestrings();
509 if (nextstring + l >= maxstring)
510 error("! out of string space");
511 strcpy(nextstring, s);
512 q = nextstring;
513 nextstring += l + 1;
514 return(q);
515 }
516 static void
newoutname(void)517 newoutname(void) {
518 static int seq = 0;
519 static char *seqptr = 0;
520 char *p, *q;
521
522 if (oname == 0 || *oname == 0)
523 error("! need an output file name to specify separate files");
524 if (*oname != '!' && *oname != '|') {
525 if (seqptr == 0) {
526 q = newstring(oname);
527 for (p = q; *p; p++) /* find last dot after last slash */
528 if (*p == '.')
529 seqptr = p + 1;
530 else if (IS_DIR_SEP (*p))
531 seqptr = 0;
532 #ifdef WIN32
533 else if (IS_KANJI(p))
534 p++;
535 #endif
536 if (seqptr == 0)
537 seqptr = p;
538 nextstring += 5; /* make room for the number, up to five digits */
539 oname = q;
540 }
541 sprintf(seqptr, "%03d", ++seq);
542 }
543 }
544 /*
545 * This routine reverses a list, where a list is defined to be any
546 * structure whose first element is a pointer to another such structure.
547 */
548 VOID *
revlist(VOID * p)549 revlist(VOID *p)
550 {
551 struct list {
552 struct list *next;
553 } *pp = (struct list *)p, *qq = 0, *tt;
554
555 while (pp) {
556 tt = pp->next;
557 pp->next = qq;
558 qq = pp;
559 pp = tt;
560 }
561 return (VOID *)qq;
562 }
563 /* this asks for a new set of arguments from the command line */
564 static void
queryargs(void)565 queryargs(void)
566 {
567 fputs("Options: ",stdout);
568 fgets(queryline,256,stdin);
569 qargc=1;
570 if ( (qargv[1] = strtok(queryline," \n")) != (char *)NULL ) {
571 qargc=2;
572 while ( ((qargv[qargc] = strtok((char *)NULL," \n")) != (char *)NULL)
573 && (qargc < 31) )
574 qargc++;
575 }
576 qargv[qargc] = (char *)NULL;
577 }
578
579 /*
580 * Finally, our main routine.
581 */
582 #ifdef VMS
main(void)583 main(void)
584 #else
585 int
586 main(int argc, char **argv)
587 #endif
588 {
589 int i, lastext = -1;
590 #ifdef MVSXA
591 int firstext = -1;
592 #endif
593 sectiontype *sects;
594
595 #ifdef WIN32
596 #if defined(KPATHSEA)
597 int ac;
598 char **av, *enc;
599 #endif
600 SET_BINARY(fileno(stdin));
601 SET_BINARY(fileno(stdout));
602 #endif
603
604 #ifdef __APPLE__ /* for Mac OS X, T. Uchiyama */
605 struct rlimit rl;
606 getrlimit(RLIMIT_STACK, &rl);
607 rl.rlim_cur = 2048 * 1024;
608 setrlimit(RLIMIT_STACK, &rl);
609 #endif
610 #ifdef KPATHSEA
611 kpse_set_program_name (argv[0], "dvips");
612 kpse_set_program_enabled (kpse_pk_format, MAKE_TEX_PK_BY_DEFAULT, kpse_src_compile);
613 #ifdef WIN32
614 enc = kpse_var_value("command_line_encoding");
615 if (get_command_line_args_utf8(enc, &ac, &av)) {
616 argc = ac;
617 argv = av;
618 }
619 #endif
620 #endif
621
622 #ifdef __THINK__
623 argc = dcommand(&argv); /* do I/O stream redirection */
624 #endif
625 #ifdef VMS /* Grab the command-line buffer */
626 short len_arg;
627 $DESCRIPTOR( verb_dsc, "DVIPS "); /* assume the verb is always DVIPS */
628 struct dsc$descriptor_d temp_dsc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_D, 0};
629
630 progname = &thh[0];
631 strcpy(progname,"DVIPS%ERROR");
632
633 lib$get_foreign( &temp_dsc, 0, &len_arg, 0); /* Get the command line */
634 str$prefix(&temp_dsc, &verb_dsc); /* prepend the VERB */
635 len_arg += verb_dsc.dsc$w_length; /* update the length */
636 temp_dsc.dsc$a_pointer[len_arg] = '\0'; /* terminate the string */
637 gargv = &temp_dsc.dsc$a_pointer; /* point to the buffer */
638 gargc = 1; /* only one big argv */
639 #else
640 progname = argv[0];
641 gargv = argv;
642 gargc = argc;
643 /* we sneak a look at the first arg in case it's debugging */
644 #ifdef DEBUG
645 if (argc > 1 && strncmp(argv[1], "-d", 2)==0) {
646 if (argv[1][2]==0 && argc > 2) {
647 if (sscanf(argv[2], "%d", &debug_flag)==0)
648 debug_flag = 0;
649 } else {
650 if (sscanf(argv[1]+2, "%d", &debug_flag)==0)
651 debug_flag = 0;
652 }
653 }
654 #if defined(KPATHSEA) && defined(KPSE_DEBUG)
655 if (dd(D_FILES)) KPSE_DEBUG_SET (KPSE_DEBUG_FOPEN);
656 if (dd(D_PATHS)) KPSE_DEBUG_SET (KPSE_DEBUG_PATHS);
657 if (dd(D_STAT)) KPSE_DEBUG_SET (KPSE_DEBUG_STAT);
658 if (dd(D_HASH)) KPSE_DEBUG_SET (KPSE_DEBUG_HASH);
659 if (dd(D_EXPAND)) KPSE_DEBUG_SET (KPSE_DEBUG_EXPAND);
660 if (dd(D_SEARCH)) KPSE_DEBUG_SET (KPSE_DEBUG_SEARCH);
661 #endif /* KPATHSEA && KPSE_DEBUG */
662 #endif /* DEBUG */
663 #ifdef KPATHSEA
664 if (argc > 1) {
665 if (strcmp (argv[1], "--help") == 0) {
666 help (0);
667 exit (0);
668 } else if (strcmp (argv[1], "--version") == 0) {
669 puts (BANNER);
670 puts (kpathsea_version_string);
671 puts ("Copyright 2015 Radical Eye Software.\n\
672 There is NO warranty. You may redistribute this software\n\
673 under the terms of the GNU General Public License\n\
674 and the Dvips copyright.\n\
675 For more information about these matters, see the files\n\
676 named COPYING and dvips.h.\n\
677 Primary author of Dvips: T. Rokicki.");
678 exit (0);
679 }
680 if (argc == 2 && strncmp(argv[1], "-?", 2) == 0) {
681 printf("%s %s\n", banner, banner2);
682 help(0);
683 exit(0);
684 }
685 if (argc == 2 && strncmp(argv[1], "-v", 2) == 0) {
686 printf("%s %s\n", banner, banner2);
687 exit(0);
688 }
689 }
690 #endif
691 #endif
692 dvips_debug_flag = 0;
693 { /* for compilers incompatible with c99 */
694 char *s = getenv ("DVIPSDEBUG");
695 if (s) {
696 dvips_debug_flag = 1;
697 } else {
698 s = getenv ("KPATHSEA_DEBUG");
699 if (s) {
700 dvips_debug_flag = 1;
701 }
702 }
703 }
704 initialize();
705 checkenv(0);
706 getdefaults(CONFIGFILE);
707 getdefaults((char *)0);
708 /*
709 * This next whole big section of code is straightforward; we just scan
710 * the options. An argument can either immediately follow its option letter
711 * or be separated by spaces. Any argument not preceded by '-' and an
712 * option letter is considered a file name; the program complains if more
713 * than one file name is given, and uses stdin if none is given.
714 */
715 #ifdef VMS
716 vmscli(void);
717 papsizes = (struct papsiz *)revlist((void *)papsizes); /* Added by PWD 21-Mar-1997 */
718 #else
719 queryoptions = 0;
720 do
721 {
722 for (i=1; i<argc; i++) {
723 if (*argv[i]=='-') {
724 char *p=argv[i]+2;
725 char c=argv[i][1];
726 switch (c) {
727 case '-':
728 queryoptions = 1;
729 break;
730 case 'a':
731 dopprescan = (*p != '0');
732 break;
733 case 'b':
734 if (*p == 0 && argv[i+1])
735 p = argv[++i];
736 if (sscanf(p, "%d", &pagecopies)==0)
737 error("! Bad number of page copies option (-b).");
738 if (pagecopies < 1 || pagecopies > 1000)
739 error("! can only print one to a thousand page copies");
740 break;
741 case 'c' :
742 if (*p == 0 && argv[i+1])
743 p = argv[++i];
744 if (sscanf(p, "%d", &numcopies)==0)
745 error("! Bad number of copies option (-c).");
746 break;
747 case 'd' :
748 #ifdef DEBUG
749 {
750 int old_debug = debug_flag;
751 static int warned_already = 0;
752
753 if (*p == 0 && argv[i+1])
754 p = argv[++i];
755 if (sscanf(p, "%d", &debug_flag)==0)
756 error("! Bad debug option (-d).");
757 if (debug_flag != old_debug && warned_already++ == 0) {
758 fprintf(stderr,
759 "I found a debug option that was not the first argument to the dvips\n");
760 fprintf(stderr,
761 "command. Some debugging output may have been lost because of this.\n");
762 }
763 break;
764 }
765 #else
766 error("not compiled in debug mode");
767 break;
768 #endif /* DEBUG */
769 case 'e' :
770 if (*p == 0 && argv[i+1])
771 p = argv[++i];
772 if (sscanf(p, "%d", &maxdrift)==0 || maxdrift<0)
773 error("! Bad maxdrift option (-e).");
774 vmaxdrift = maxdrift;
775 break;
776 case 'f' :
777 filter = (*p != '0');
778 if (filter)
779 oname = "";
780 noenv = 1;
781 sendcontrolD = 0;
782 break;
783 case 'u' :
784 {
785 char PSname[300];
786 if (*p == 0 && argv[i+1])
787 p = argv[++i];
788 strcpy(PSname, p);
789 if (!strchr(PSname, '.'))
790 strcat(PSname, ".map"); /* default extension */
791 if (PSname[0] == '+')
792 getpsinfo(PSname+1);
793 else
794 psmapfile = strdup(PSname); /* a cute small memory leak (just as in 'p' option handling in resident.c) */
795 }
796 break;
797 case 'h' : case 'H' :
798 if (*p == 0 && argv[i+1])
799 p = argv[++i];
800 if (strcmp(p, "-") == 0)
801 headers_off = 1;
802 else
803 add_header(p);
804 break;
805 case 'i':
806 sepfiles = (*p != '0');
807 if (sepfiles && maxsecsize == 0) {
808 maxsecsize = 1; /* default section size to one page/file */
809 }
810 break;
811 case 'j':
812 partialdownload = (*p != '0');
813 break;
814 case 'k':
815 cropmarks = (*p != '0');
816 break;
817 case 'R':
818 if (*p == '0') {
819 secure = 0;
820 } else if (*p == '2') {
821 secure = 2;
822 } else {
823 secure = 1;
824 }
825 if (secure)
826 secure_option = 1; /* Never used */
827 break;
828 case 'S':
829 if (*p == 0 && argv[i+1])
830 p = argv[++i];
831 if (sscanf(p, "%d", &maxsecsize)==0)
832 error("! Bad section size arg (-S).");
833 break;
834 case 'm' :
835 if (STREQ (p, "ode") && argv[i+1]) {
836 mfmode = argv[++i];
837 mfmode_option = 1;
838 } else
839 manualfeed = (*p != '0');
840 break;
841 case 'n' :
842 if (STREQ (p, "oomega")) {
843 noomega = 1;
844 } else if (STREQ (p, "optex")) {
845 noptex = 1;
846 } else {
847 if (*p == 0 && argv[i+1])
848 p = argv[++i];
849 #ifdef SHORTINT
850 if (sscanf(p, "%ld", &maxpages)==0)
851 #else /* ~SHORTINT */
852 if (sscanf(p, "%d", &maxpages)==0)
853 #endif /* ~SHORTINT */
854 error("! Bad number of pages option (-n).");
855 }
856 break;
857 case 'o' :
858 if (*p == 0 && argv[i+1] &&
859 (STREQ (argv[i+1], "-") || argv[i+1][0] != '-'))
860 p = argv[++i];
861 oname_option = 1;
862 oname = p;
863 noenv = 1;
864 sendcontrolD = 0;
865 #if defined(MSDOS) || defined(OS2)
866 if (*oname && oname[strlen(oname)-1] == ':')
867 oname[strlen(oname)-1] = 0; /* strip ':' off */
868 #endif
869 break;
870 case 'O' :
871 if (*p == 0 && argv[i+1])
872 p = argv[++i];
873 handlepapersize(p, &hoff, &voff);
874 break;
875 case 'T' :
876 if (*p == 0 && argv[i+1])
877 p = argv[++i];
878 handlepapersize(p, &hpapersize, &vpapersize);
879 if (landscape) {
880 error(
881 "both landscape and papersize specified; ignoring landscape");
882 landscape = 0;
883 }
884 break;
885 case 'p' :
886 #if defined(MSDOS) || defined(OS2) || defined(ATARIST)
887 /* check for emTeX job file (-pj=filename) */
888 if (*p == 'j') {
889 p++;
890 if (*p == '=' || *p == ':')
891 p++;
892 mfjobname = newstring(p);
893 break;
894 }
895 /* must be page number instead */
896 #endif
897 if (*p == 'p') { /* a -pp specifier for a page list? */
898 p++;
899 if (*p == 0 && argv[i+1])
900 p = argv[++i];
901 if (ParsePages(p))
902 error("! Bad page list specifier (-pp).");
903 pagelist = 1;
904 break;
905 }
906 if (*p == 0 && argv[i+1])
907 p = argv[++i];
908 if (*p == '=') {
909 abspage = 1;
910 p++;
911 }
912 #ifdef SHORTINT
913 switch(sscanf(p, "%ld.%ld", &firstpage, &firstseq)) {
914 #else /* ~SHORTINT */
915 switch(sscanf(p, "%d.%d", &firstpage, &firstseq)) {
916 #endif /* ~SHORTINT */
917 case 1: firstseq = 0;
918 case 2: break;
919 default:
920 #ifdef KPATHSEA
921 error(concat3 ("! Bad first page option (-p ", p, ")."));
922 #else
923 error("! Bad first page option (-p).");
924 #endif
925 }
926 notfirst = 1;
927 break;
928 case 'l':
929 if (*p == 0 && argv[i+1])
930 p = argv[++i];
931 if (*p == '=') {
932 abspage = 1;
933 p++;
934 }
935 #ifdef SHORTINT
936 switch(sscanf(p, "%ld.%ld", &lastpage, &lastseq)) {
937 #else /* ~SHORTINT */
938 switch(sscanf(p, "%d.%d", &lastpage, &lastseq)) {
939 #endif /* ~SHORTINT */
940 case 1: lastseq = 0;
941 case 2: break;
942 default:
943 #ifdef KPATHSEA
944 error(concat3 ("! Bad last page option (-l ", p, ")."));
945 #else
946 error("! Bad last page option (-l).");
947 #endif
948 }
949 notlast = 1;
950 break;
951 case 'A':
952 oddpages = 1;
953 break;
954 case 'B':
955 evenpages = 1;
956 break;
957 case 'q' : case 'Q' :
958 quiet = (*p != '0');
959 break;
960 case 'r' :
961 reverse = (*p != '0');
962 break;
963 case 't' :
964 if (*p == 0 && argv[i+1])
965 p = argv[++i];
966 if (strcmp(p, "landscape") == 0) {
967 if (hpapersize || vpapersize)
968 error(
969 "both landscape and papersize specified; ignoring landscape");
970 else
971 landscape = 1;
972 } else
973 paperfmt = p;
974 break;
975 case 'v':
976 printf ("%s %s\n", banner, banner2);
977 exit (0);
978 break;
979 case 'x' : case 'y' :
980 if (*p == 0 && argv[i+1])
981 p = argv[++i];
982 if (sscanf(p, "%lg", &mag)==0 || mag < 1 ||
983 mag > 1000000)
984 error("! Bad magnification parameter (-x or -y).");
985 overridemag = (c == 'x' ? 1 : -1);
986 break;
987 case 'C' :
988 if (*p == 0 && argv[i+1])
989 p = argv[++i];
990 if (sscanf(p, "%d", &collatedcopies)==0)
991 error("! Bad number of collated copies option (-C).");
992 break;
993 case 'D' :
994 if (*p == 0 && argv[i+1])
995 p = argv[++i];
996 if (sscanf(p, "%d", &actualdpi)==0 || actualdpi < 10 ||
997 actualdpi > 10000)
998 error("! Bad dpi parameter (-D).");
999 vactualdpi = actualdpi;
1000 /* If we had the mode from config.ps, don't use it.
1001 If they specified one with -mode, keep it. */
1002 if (!mfmode_option)
1003 mfmode = NULL;
1004 break;
1005 case 'E' :
1006 tryepsf = (*p != '0');
1007 removecomments = disablecomments = 0;
1008 if (tryepsf && maxsecsize == 0)
1009 maxsecsize = 1;
1010 break;
1011 case 'K' :
1012 removecomments = (*p != '0');
1013 break;
1014 case 'U' :
1015 nosmallchars = (*p != '0');
1016 break;
1017 case 'X' :
1018 if (*p == 0 && argv[i+1])
1019 p = argv[++i];
1020 if (sscanf(p, "%d", &actualdpi)==0 || actualdpi < 10 ||
1021 actualdpi > 10000)
1022 error("! Bad dpi parameter (-D).");
1023 break;
1024 case 'Y' :
1025 if (*p == 0 && argv[i+1])
1026 p = argv[++i];
1027 if (sscanf(p, "%d", &vactualdpi)==0 || vactualdpi < 10 ||
1028 vactualdpi > 10000)
1029 error("! Bad dpi parameter (-D).");
1030 vactualdpi = vactualdpi;
1031 break;
1032 case 'F' :
1033 sendcontrolD = (*p != '0');
1034 break;
1035 case 'G' :
1036 shiftlowchars = (*p != '0');
1037 break;
1038 case 'M':
1039 dontmakefont = (*p != '0');
1040 #ifdef KPATHSEA
1041 kpse_set_program_enabled (kpse_pk_format, !dontmakefont,
1042 kpse_src_cmdline);
1043 #endif
1044 break;
1045 case 'N' :
1046 disablecomments = (*p != '0');
1047 break;
1048 case 'P' :
1049 {
1050 struct papsiz *opapsiz = papsizes;
1051 struct papsiz *npapsiz;
1052 papsizes = 0;
1053 if (*p == 0 && argv[i+1])
1054 p = argv[++i];
1055 printer = p;
1056 noenv = 1;
1057 if (!getdefaults("")) {
1058 /* If no config file, default the output name. */
1059 oname = concat ("| lpr -P", printer);
1060 }
1061 npapsiz = opapsiz;
1062 while (npapsiz && npapsiz->next)
1063 npapsiz = npapsiz->next;
1064 if (npapsiz) {
1065 npapsiz->next = papsizes;
1066 papsizes = opapsiz;
1067 }
1068 }
1069 break;
1070 case 's':
1071 safetyenclose = (*p != '0');
1072 break;
1073 case 'V':
1074 downloadpspk = (*p != '0');
1075 break;
1076 case 'Z':
1077 compressed = (*p != '0');
1078 break;
1079 #ifdef HPS
1080 case 'z':
1081 HPS_FLAG = (*p != '0');
1082 break;
1083 #endif
1084 case '?':
1085 break; /* We print the banner and help msg below. */
1086 default:
1087 #ifdef KPATHSEA
1088 error(concat3 ("! Invalid option `", argv[i],
1089 "'. Try --help for more information."));
1090 #else
1091 error(
1092 "! Bad option, not one of acdefhijklmnopqrstxyzABCDEFKMNOPSTUXYZ?");
1093 #endif
1094 }
1095 } else {
1096 if (*iname == 0) {
1097 register char *p;
1098
1099 lastext = 0;
1100 iname = nextstring;
1101 p = argv[i];
1102 if (NAME_BEGINS_WITH_DEVICE(p)) { /* get past DOSISH drive */
1103 *nextstring++ = *p++;
1104 *nextstring++ = *p++;
1105 }
1106 while (*p) {
1107 *nextstring = *p++;
1108 if (*nextstring == '.')
1109 lastext = nextstring - iname;
1110 else if (IS_DIR_SEP(*nextstring))
1111 lastext = 0;
1112 #ifdef WIN32
1113 else if (IS_KANJI(p-1)) {
1114 nextstring++;
1115 *nextstring = *p++;
1116 }
1117 #endif
1118 nextstring++;
1119 }
1120 *nextstring++ = '.';
1121 *nextstring++ = 'd';
1122 *nextstring++ = 'v';
1123 *nextstring++ = 'i';
1124 *nextstring++ = 0;
1125 } else
1126 #ifdef KPATHSEA
1127 error(concat3("! Second input filename (", argv[i],
1128 ") specified."));
1129 #else
1130 error("! Two input file names specified.");
1131 #endif
1132 }
1133 }
1134 if (noenv == 0) {
1135 register char *p;
1136 struct papsiz *opapsiz = papsizes;
1137 papsizes = 0;
1138 if (0 != (p = getenv("PRINTER"))) {
1139 #if defined(MSDOS) || defined(OS2)
1140 strcpy(nextstring, p);
1141 strcat(nextstring, ".cfg");
1142 #else
1143 strcpy(nextstring, "config.");
1144 strcat(nextstring, p);
1145 #endif
1146 getdefaults(nextstring);
1147 }
1148 {
1149 struct papsiz *npapsiz = opapsiz;
1150 while (npapsiz && npapsiz->next)
1151 npapsiz = npapsiz->next;
1152 if (npapsiz) {
1153 npapsiz->next = papsizes;
1154 papsizes = opapsiz;
1155 }
1156 }
1157 }
1158 papsizes = (struct papsiz *)revlist((void *)papsizes);
1159 if (queryoptions != 0) { /* get new options */
1160 fprintf(stderr, "%s %s\n", banner, banner2);
1161 help(1);
1162 queryargs();
1163 if (qargc == 1)
1164 queryoptions = 0;
1165 else {
1166 qargv[0] = argv[0];
1167 argc=qargc;
1168 argv=qargv;
1169 }
1170 }
1171 } while (queryoptions != 0);
1172 #endif
1173 #if defined(KPATHSEA) && defined(KPSE_DEBUG) && defined(DEBUG) /* this should really be part of a subroutine */
1174 if (dd(D_FILES)) KPSE_DEBUG_SET (KPSE_DEBUG_FOPEN);
1175 if (dd(D_PATHS)) KPSE_DEBUG_SET (KPSE_DEBUG_PATHS);
1176 if (dd(D_STAT)) KPSE_DEBUG_SET (KPSE_DEBUG_STAT);
1177 if (dd(D_HASH)) KPSE_DEBUG_SET (KPSE_DEBUG_HASH);
1178 if (dd(D_EXPAND)) KPSE_DEBUG_SET (KPSE_DEBUG_EXPAND);
1179 if (dd(D_SEARCH)) KPSE_DEBUG_SET (KPSE_DEBUG_SEARCH);
1180 #endif /* KPATHSEA && KPSE_DEBUG && DEBUG */
1181 checkenv(1);
1182 #ifdef KPATHSEA
1183 kpse_init_prog ("DVIPS", actualdpi, mfmode, "cmr10");
1184 kpse_make_tex_discard_errors = quiet;
1185 #endif
1186 /*
1187 * The logic here is a bit convoluted. Since all `additional'
1188 * PostScript font information files are loaded *before* the master
1189 * one, and yet they should be able to override the master one, we
1190 * have to add the information in the master list to the *ends* of
1191 * the hash chain. We do this by reversing the lists, adding them
1192 * to the front, and then reversing them again.
1193 */
1194 revpslists();
1195 getpsinfo((char *)NULL);
1196 revpslists();
1197 if (dvips_debug_flag) {
1198 if (!quiet)
1199 fprintf(stderr, "\n%s %s\n", banner, banner2);
1200 prettycolumn = 0;
1201 } else {
1202 if (!quiet)
1203 fprintf(stderr, "%s %s\n", banner, banner2);
1204 }
1205 if (*iname) {
1206 dvifile = fopen(iname, READBIN);
1207 /*
1208 * Allow names like a.b.
1209 */
1210 if (dvifile == 0) {
1211 iname[strlen(iname)-4] = 0; /* remove the .dvi suffix */
1212 dvifile = fopen(iname, READBIN);
1213 }
1214 }
1215 if (oname[0] == '-' && oname[1] == 0)
1216 oname = "";
1217 else if (*oname == 0 && ! filter && *iname) {
1218 /* determine output name from input name */
1219 oname = nextstring;
1220 #ifndef VMCMS /* get stuff before LAST "." */
1221 lastext = strlen(iname) - 1;
1222 while (iname[lastext] != '.' && lastext > 0)
1223 lastext--;
1224 if (iname[lastext] != '.')
1225 lastext = strlen(iname) - 1;
1226 #else /* for VM/CMS we take the stuff before FIRST "." */
1227 lastext = strchr(iname,'.') - iname;
1228 if ( lastext <= 0 ) /* if no '.' in "iname" */
1229 lastext = strlen(iname) -1;
1230 #endif
1231 #ifdef MVSXA /* IBM: MVS/XA */
1232 if (strchr(iname, '(') != NULL &&
1233 strchr(iname, ')') != NULL) {
1234 firstext = strchr(iname, '(') - iname + 1;
1235 lastext = strrchr(iname, ')') - iname - 1;
1236 }
1237 else {
1238 if (strrchr(iname, '.') != NULL) {
1239 lastext = strrchr(iname, '.') - iname - 1;
1240 }
1241 else lastext = strlen(iname) - 1;
1242 if (strchr(iname, '\'') != NULL)
1243 firstext = strchr(iname, '.') - iname + 1;
1244 else firstext = 0;
1245 }
1246 #endif /* IBM: MVS/XA */
1247 #ifdef MVSXA /* IBM: MVS/XA */
1248 for (i=firstext; i<=lastext; i++)
1249 #else
1250 for (i=0; i<=lastext; i++)
1251 #endif
1252 *nextstring++ = iname[i];
1253 if (iname[lastext] != '.')
1254 *nextstring++ = '.';
1255 #ifndef VMCMS
1256 *nextstring++ = 'p';
1257 *nextstring++ = 's';
1258 #else /* might as well keep things uppercase */
1259 *nextstring++ = 'P';
1260 *nextstring++ = 'S';
1261 #endif
1262 *nextstring++ = 0;
1263 /*
1264 * Now we check the name, and `throw away' any prefix information.
1265 * This means throwing away anything before (and including) a colon
1266 * or slash.
1267 */
1268 {
1269 const char *p = NAME_BEGINS_WITH_DEVICE(oname) ? oname + 2 : oname;
1270
1271 for (oname=p; *p && p[1]; p++)
1272 if (IS_DIR_SEP(*p))
1273 oname = p + 1;
1274 #ifdef WIN32
1275 else if (IS_KANJI(p))
1276 p++;
1277 #endif
1278 }
1279 }
1280 #ifdef DEBUG
1281 if (dd(D_PATHS)) {
1282 #ifdef SHORTINT
1283 fprintf(stderr,"input file %s output file %s swmem %ld\n",
1284 #else /* ~SHORTINT */
1285 fprintf(stderr,"input file %s output file %s swmem %d\n",
1286 #endif /* ~SHORTINT */
1287 iname, oname, swmem);
1288 #ifndef KPATHSEA
1289 fprintf(stderr,"tfm path %s\npk path %s\n", tfmpath, pkpath);
1290 fprintf(stderr,"fig path %s\nvf path %s\n", figpath, vfpath);
1291 fprintf(stderr,"config path %s\nheader path %s\n",
1292 configpath, headerpath);
1293 #endif
1294 #ifdef FONTLIB
1295 fprintf(stderr,"fli path %s\nfli names %s\n", flipath, fliname);
1296 #endif
1297 } /* dd(D_PATHS) */
1298 #endif /* DEBUG */
1299
1300 /*
1301 * Check if oname != iname
1302 */
1303 if (iname && *iname && oname && *oname) {
1304 #ifdef DOSISH
1305 if (strcasecmp (iname, oname) == 0) {
1306 #else
1307 if (strcmp (iname, oname) == 0) {
1308 #endif
1309 fprintf (stderr, "! Output name should be different from input name.\n");
1310 exit (20);
1311 }
1312 }
1313 /*
1314 * Now we try to open the dvi file.
1315 */
1316 if (!quiet && warningmsg)
1317 error(warningmsg);
1318 headersready = 1;
1319 headerfile = (compressed? CHEADERFILE : HEADERFILE);
1320 add_header(headerfile);
1321 if (*iname != 0) {
1322 fulliname = nextstring;
1323 #ifndef IGNORE_CWD
1324 if (!IS_DIR_SEP(*iname) && !NAME_BEGINS_WITH_DEVICE(iname)) {
1325 getcwd(nextstring, MAXPATHLEN + 2);
1326 while (*nextstring++);
1327 #ifdef VMS /* VMS doesn't need the '/' character appended */
1328 nextstring--; /* so just back up one byte. */
1329 #else
1330 *(nextstring-1) = '/';
1331 #endif
1332 }
1333 #endif
1334 strcpy(nextstring,iname);
1335 while (*nextstring++); /* advance nextstring past iname */
1336 } else if (filter) {
1337 dvifile = stdin;
1338 if (O_BINARY && !isatty(fileno(stdin)))
1339 SET_BINARY(fileno(stdin));
1340 } else {
1341 #ifdef KPATHSEA
1342 fprintf (stderr, "dvips: Missing DVI file argument (or -f).\n");
1343 fprintf (stderr, "dvips: Try --help for more information.\n");
1344 #else
1345 help(1);
1346 #endif
1347 exit(1);
1348 }
1349 if (dvifile==NULL) {
1350 error_with_perror("DVI file can't be opened:", iname);
1351 exit(1);
1352 }
1353 if (fseek(dvifile, 0L, 0) < 0)
1354 error("! DVI file must not be a pipe.");
1355
1356 initcolor();
1357 #ifdef FONTLIB
1358 fliload(); /* read the font libaries */
1359 #endif
1360 /*
1361 * Now we do our main work.
1362 */
1363 swmem += fontmem;
1364 if (maxdrift < 0) {
1365 if (actualdpi <= 599)
1366 maxdrift = actualdpi / 100;
1367 else if (actualdpi < 1199)
1368 maxdrift = actualdpi / 200 + 3;
1369 else
1370 maxdrift = actualdpi / 400 + 6;
1371 }
1372 if (vmaxdrift < 0) {
1373 if (vactualdpi <= 599)
1374 vmaxdrift = vactualdpi / 100;
1375 else if (vactualdpi < 1199)
1376 vmaxdrift = vactualdpi / 200 + 3;
1377 else
1378 vmaxdrift = vactualdpi / 400 + 6;
1379 }
1380 if (dopprescan)
1381 pprescanpages();
1382 prescanpages();
1383 #if defined MSDOS || defined OS2 || defined(ATARIST)
1384 if (mfjobfile != (FILE*)NULL) {
1385 char answer[5];
1386 fputs("}\n",mfjobfile);
1387 fclose(mfjobfile);
1388 fputs("Exit to make missing fonts now (y/n)? ",stdout);
1389 fgets(answer,4,stdin);
1390 if (*answer=='y' || *answer=='Y')
1391 exit(8); /* exit with errorlevel 8 for emTeX dvidrv */
1392 }
1393 #endif
1394 if (includesfonts)
1395 add_header(IFONTHEADER);
1396 if (usesPSfonts)
1397 add_header(PSFONTHEADER);
1398 if (usesspecial)
1399 add_header(SPECIALHEADER);
1400 if (usescolor) /* IBM: color */
1401 add_header(COLORHEADER);
1402 #ifdef HPS
1403 if (HPS_FLAG)
1404 add_header(HPSHEADER);
1405 #endif
1406 sects = sections;
1407 totalpages *= collatedcopies;
1408 if (sects == NULL || sects->next == NULL) {
1409 sectioncopies = collatedcopies;
1410 collatedcopies = 1;
1411 } else {
1412 if (! sepfiles)
1413 multiplesects = 1;
1414 }
1415 totalpages *= pagecopies;
1416 if (tryepsf) {
1417 if (paperfmt || landscape || manualfeed ||
1418 collatedcopies > 1 || numcopies > 1 || cropmarks ||
1419 *iname == 0 ||
1420 (totalpages > 1 && !(sepfiles && maxsecsize == 1))) {
1421 error("Can't make it EPSF, sorry");
1422 tryepsf = 0;
1423 }
1424 }
1425 #ifdef HPS
1426 if (HPS_FLAG)
1427 set_bitfile("head.tmp", 0);
1428 #endif
1429 if (! sepfiles) {
1430 initprinter(sections);
1431 outbangspecials();
1432 }
1433
1434 for (i=0; i<collatedcopies; i++) {
1435 sects = sections;
1436 while (sects != NULL) {
1437 if (sepfiles) {
1438 newoutname();
1439 if (! quiet) {
1440 if (prettycolumn + strlen(oname) + 6 > STDOUTSIZE) {
1441 fprintf(stderr, "\n");
1442 prettycolumn = 0;
1443 }
1444 fprintf(stderr, "(-> %s) ", oname);
1445 prettycolumn += strlen(oname) + 6;
1446 }
1447 #ifdef HPS
1448 if (HPS_FLAG)
1449 set_bitfile("head.tmp", 0);
1450 #endif
1451 initprinter(sects);
1452 outbangspecials();
1453 } else if (! quiet) {
1454 if (prettycolumn > STDOUTSIZE) {
1455 fprintf(stderr, "\n");
1456 prettycolumn = 0;
1457 }
1458 fprintf(stderr, ". ");
1459 prettycolumn += 2;
1460 }
1461 fflush(stderr);
1462 dosection(sects, sectioncopies);
1463 sects = sects->next;
1464 if (sepfiles) {
1465 #ifdef HPS
1466 if (HPS_FLAG)
1467 finish_hps();
1468 #endif
1469 cleanprinter();
1470 }
1471 }
1472 }
1473 freememforpsnames();
1474 if (! sepfiles) {
1475 #ifdef HPS
1476 if (HPS_FLAG)
1477 finish_hps();
1478 #endif
1479 cleanprinter();
1480 }
1481 if (! quiet)
1482 fprintf(stderr, "\n");
1483 #ifdef DEBUG
1484 if (dd(D_MEM)) {
1485 #ifdef SHORTINT
1486 fprintf(stderr, "Total memory allocated: %ld\n", totalalloc);
1487 #else
1488 fprintf(stderr, "Total memory allocated: %d\n", totalalloc);
1489 #endif
1490 }
1491 #endif
1492 return 0;
1493 /*NOTREACHED*/
1494 }
1495 #ifdef VMS
1496 #include "[.vms]vmscli.c"
1497 #endif
1498
1499 #ifdef VMCMS /* IBM: VM/CMS */
1500 #include "dvipscms.h"
1501 #endif
1502
1503 #ifdef MVSXA /* IBM: MVS/XA */
1504 #include "dvipsmvs.h"
1505 #endif
1506