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