home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / texmf / source / dvips / dvips.c < prev    next >
C/C++ Source or Header  |  1994-09-27  |  37KB  |  1,153 lines

  1. /*
  2.  *   This is the main routine.
  3.  */
  4. #ifndef DEFRES
  5. #define DEFRES (300)
  6. #endif
  7.  
  8. #include "dvips.h" /* The copyright notice there is included too! */
  9. #ifdef AMIGA
  10. #include "amigapaths.h"
  11. #endif
  12. #ifndef SYSV
  13. extern char *strtok() ; /* some systems don't have this in strings.h */
  14. #endif
  15. #ifdef VMS
  16. #define GLOBAL globaldef
  17. #ifdef __GNUC__
  18. #include "climsgdef.h"    /* created by hand, extracted from STARLET.MLB */
  19.             /* and put in GNU_CC:[INCLUDE.LOCAL]           */
  20. #include "ctype.h"
  21. #include "descrip.h"
  22. #else
  23. #include climsgdef
  24. #include ctype
  25. #include descrip
  26. #endif
  27. #endif
  28. /*
  29.  *   First we define some globals.
  30.  */
  31. #ifdef VMS
  32.     static char ofnme[252],infnme[252],pap[40],thh[20];
  33. #endif
  34. fontdesctype *fonthead ;      /* list of all fonts mentioned so far */
  35. fontdesctype *curfnt ;        /* the currently selected font */
  36. sectiontype *sections ;       /* sections to process document in */
  37. Boolean manualfeed ;          /* manual feed? */
  38. Boolean compressed ;          /* compressed? */
  39. Boolean downloadpspk ;        /* use PK for downloaded PS fonts? */
  40. Boolean safetyenclose ;
  41.                           /* enclose in save/restore for stupid spoolers? */
  42. Boolean removecomments = 1 ;  /* remove comments from included PS? */
  43. Boolean nosmallchars ;        /* disable small char optimization for X4045? */
  44. Boolean cropmarks ;           /* add cropmarks? */
  45. Boolean abspage = 0 ;         /* are page numbers absolute? */
  46. Boolean tryepsf = 0 ;         /* should we try to make it espf? */
  47. Boolean secure = 0 ;          /* make safe for suid */
  48. int collatedcopies = 1 ;      /* how many collated copies? */
  49. int sectioncopies = 1 ;       /* how many times to repeat each section? */
  50. integer pagecopies = 1 ;          /* how many times to repeat each page? */
  51. shalfword linepos = 0 ;       /* where are we on the line being output? */
  52. integer maxpages ;            /* the maximum number of pages */
  53. Boolean notfirst, notlast ;   /* true if a first page was specified */
  54. Boolean evenpages, oddpages ; /* true if doing only even/only odd pages */
  55. Boolean pagelist ;            /* true if using page ranges */
  56. Boolean sendcontrolD ;        /* should we send a control D at end? */
  57. integer firstpage ;           /* the number of the first page if specified */
  58. integer lastpage ;
  59. integer firstseq ;
  60. integer lastseq ;
  61. integer hpapersize, vpapersize ; /* horizontal and vertical paper size */
  62. integer hoff, voff ;          /* horizontal and vertical offsets */
  63. integer maxsecsize ;          /* the maximum size of a section */
  64. integer firstboploc ;         /* where the first bop is */
  65. Boolean sepfiles ;            /* each section in its own file? */
  66. int numcopies ;               /* number of copies of each page to print */
  67. char *oname ;                 /* output file name */
  68. char *iname ;                 /* dvi file name */
  69. char *fulliname ;             /* same, with current working directory */
  70. char *strings ;               /* strings for program */
  71. char *nextstring, *maxstring ; /* string pointers */
  72. FILE *dvifile, *bitfile ;     /* dvi and output files */
  73. quarterword *curpos ;        /* current position in virtual character packet */
  74. quarterword *curlim ;         /* final byte in virtual character packet */
  75. fontmaptype *ffont ;          /* first font in current frame */
  76. real conv ;                   /* conversion ratio, pixels per DVI unit */
  77. real vconv ;                  /* conversion ratio, pixels per DVI unit */
  78. real alpha ;                  /* conversion ratio, DVI unit per TFM unit */
  79. #ifndef ATARIST
  80. integer
  81. #else
  82. long
  83. #endif
  84. mag ;                         /* the magnification of this document */
  85. integer num, den ;            /* the numerator and denominator */
  86. int overridemag ;             /* substitute for mag value in DVI file? */
  87. int actualdpi = DEFRES ;      /* the actual resolution of the printer */
  88. int vactualdpi = DEFRES ;     /* the actual resolution of the printer */
  89. int maxdrift ;                /* max pixels away from true rounded position */
  90. int vmaxdrift ;               /* max pixels away from true rounded position */
  91. char *paperfmt ;              /* command-line paper format */
  92. int landscape = 0 ;           /* landscape mode */
  93. integer fontmem ;             /* memory remaining in printer */
  94. integer pagecount ;           /* page counter for the sections */
  95. integer pagenum ;             /* the page number we currently look at */
  96. long bytesleft ;              /* number of bytes left in raster */
  97. quarterword *raster ;         /* area for raster manipulations */
  98. integer hh, vv ;              /* horizontal and vertical pixel positions */
  99.  
  100. /*-----------------------------------------------------------------------*
  101.  * The PATH definitions cannot be defined on the command line because so many
  102.  * DEFINE's overflow the DCL buffer when using the GNU CC compiler.
  103.  *-----------------------------------------------------------------------*/
  104. #if defined(VMS) && defined(__GNUC__)
  105. #include "vms_gcc_paths.h"
  106. #endif
  107.  
  108. #ifdef ATARIST
  109. #   define TFMPATH "."
  110. #   define PKPATH "."
  111. #   define VFPATH "."
  112. #   define FIGPATH "."
  113. #   define HEADERPATH "."
  114. #   define CONFIGPATH "."
  115. #endif
  116. char *tfmpath = TFMPATH ;     /* pointer to directories for tfm files */
  117. char *pkpath = PKPATH ;       /* pointer to directories for pk files */
  118. char *vfpath = VFPATH ;       /* pointer to directories for vf files */
  119. char *figpath = FIGPATH ;     /* pointer to directories for figure files */
  120. char *headerpath = HEADERPATH ; /* pointer to directories for header files */
  121. char *configpath = CONFIGPATH ; /* where to find config files */
  122. char *infont ;                /* is the file we are downloading a font? */
  123. #ifndef PICTPATH
  124. #ifndef __THINK__
  125. #define PICTPATH "."
  126. #else
  127. #define PICTPATH ":"
  128. #endif
  129. #endif
  130. char *pictpath = PICTPATH ;   /* where IFF/etc. pictures are found */
  131. #ifdef SEARCH_SUBDIRECTORIES
  132. char *fontsubdirpath = FONTSUBDIRPATH ;
  133. #endif
  134. #ifdef FONTLIB
  135. char *flipath = FLIPATH ;     /* pointer to directories for fli files */
  136. char *fliname = FLINAME ;     /* pointer to names of fli files */
  137. #endif
  138. integer swmem ;               /* font memory in the PostScript printer */
  139. int quiet ;                   /* should we only print errors to stderr? */
  140. int filter ;                  /* act as filter default output to stdout,
  141.                                                default input to stdin? */
  142. int prettycolumn ;            /* the column we are at when running pretty */
  143. int gargc ;                   /* global argument count */
  144. char **gargv ;                /* global argument vector */
  145. int totalpages = 0 ;          /* total number of pages */
  146. Boolean reverse ;             /* are we going reverse? */
  147. Boolean usesPSfonts ;         /* do we use local PostScript fonts? */
  148. Boolean usesspecial ;         /* do we use \special? */
  149. Boolean headers_off ;         /* do we send headers or not? */
  150. Boolean usescolor ;           /* IBM: color - do we use colors? */
  151. char *headerfile ;            /* default header file */
  152. char *warningmsg ;            /* a message to write, if set in config file */
  153. Boolean multiplesects ;       /* more than one section? */
  154. Boolean disablecomments ;     /* should we suppress any EPSF comments? */
  155. char *printer ;               /* what printer to send this to? */
  156. char *mfmode ;                /* default MF mode */
  157. frametype frames[MAXFRAME] ;  /* stack for virtual fonts */
  158. fontdesctype *baseFonts[256] ; /* base fonts for dvi file */
  159. integer pagecost;               /* memory used on the page being prescanned */
  160. int delchar;                    /* characters to delete from prescanned page */
  161. integer fsizetol;               /* max dvi units error for psfile font sizes */
  162. Boolean includesfonts;          /* are fonts used in included psfiles? */
  163. fontdesctype *fonthd[MAXFONTHD];/* list headers for included fonts of 1 name */
  164. int nextfonthd;                 /* next unused fonthd[] index */
  165. char xdig[256];                 /* table for reading hexadecimal digits */
  166. char banner[] = BANNER ;        /* our startup message */
  167. Boolean noenv = 0 ;             /* ignore PRINTER envir variable? */
  168. Boolean dopprescan = 0 ;        /* do we do a scan before the prescan? */
  169. integer lastheadermem ;         /* how much mem did the last header require? */
  170. extern int dontmakefont ;
  171. struct papsiz *papsizes ;       /* all available paper size */
  172. int headersready ;              /* ready to check headers? */
  173. #if defined(MSDOS) || defined(OS2) || defined(ATARIST)
  174. char *mfjobname = NULL;         /* name of mfjob file if given */
  175. FILE *mfjobfile = NULL;         /* mfjob file for font making instructions */
  176. #endif
  177. #ifdef DEBUG
  178. integer debug_flag = 0;
  179. #endif /* DEBUG */
  180. char queryline[256];                /* interactive query of options */
  181. int qargc;
  182. char *qargv[32];
  183. char queryoptions;
  184. /*
  185.  *   This routine calls the following externals:
  186.  */
  187. #ifdef AMIGA
  188. #include "dvips_protos.h"
  189. #include "output_protos.h"
  190. #include "resident_protos.h"
  191. #include "header_protos.h"
  192. #include "papersiz_protos.h"
  193. #include "search_protos.h"
  194. #include "color_protos.h"
  195. #include "pprescan_protos.h"
  196. #include "prescan_protos.h"
  197. #include "dospecial_protos.h"
  198. #include "dosection_protos.h"
  199. #include "flib_protos.h"
  200. #else
  201. extern void outbangspecials() ;
  202. extern void prescanpages() ;
  203. extern void pprescanpages() ;
  204. extern void initprinter() ;
  205. extern void cleanprinter() ;
  206. extern void dosection() ;
  207. extern void getdefaults() ;
  208. extern void cmdout() ;
  209. extern void numout() ;
  210. extern void initcolor() ;
  211. extern int add_header() ;
  212. extern int ParsePages() ;
  213. extern void checkenv() ;
  214. extern void getpsinfo(), revpslists() ;
  215. #endif /* AMIGA */
  216. #ifdef FONTLIB
  217. extern void fliload() ;
  218. #endif
  219. #ifdef __THINK__
  220. int dcommand(char ***);
  221. #endif
  222.  
  223. /* Declare the routine to get the current working directory.  */
  224.  
  225. #ifndef IGNORE_CWD
  226. #ifndef HAVE_GETCWD
  227. extern char *getwd (); /* said to be faster than getcwd (SunOS man page) */
  228. #define getcwd(b, len)  getwd(b) /* used here only when b nonnull */
  229. #else
  230. #ifdef ANSI
  231. extern char *getcwd (char *, int);
  232. #else
  233. extern char *getcwd ();
  234. #endif /* not ANSI */
  235. #endif /* not HAVE_GETWD */
  236. #if defined(SYSV) || defined(VMS) || defined(MSDOS) || defined(OS2) || defined(ATARIST) || defined(AMIGA)
  237. #define MAXPATHLEN (256)
  238. #else
  239. #include <sys/param.h>          /* for MAXPATHLEN */
  240. #endif
  241. #endif /* not IGNORE_CWD */
  242.  
  243. static char *helparr[] = {
  244. #ifndef VMCMS
  245. "    Usage: dvips [options] filename[.dvi]",
  246. #else
  247. "    VM/CMS Usage:",
  248. "           dvips fname [ftype [fmode]] [options]",
  249. "or",
  250. "           dvips fname[.ftype[.fmode]] [options]",
  251. #endif
  252. "a*  Conserve memory, not time      y # Multiply by dvi magnification",
  253. "b # Page copies, for posters e.g.  A   Print only odd (TeX) pages",
  254. "c # Uncollated copies              B   Print only even (TeX) pages",
  255. "d # Debugging                      C # Collated copies",
  256. "e # Maxdrift value                 D # Resolution",
  257. "f*  Run as filter                  E*  Try to create EPSF",
  258. "h f Add header file                F*  Send control-D at end",
  259. "i*  Separate file per section      K*  Pull comments from inclusions",
  260. "k*  Print crop marks               M*  Don't make fonts",
  261. "l # Last page                      N*  No structured comments",
  262. "m*  Manual feed                    O c Set/change paper offset",
  263. #if defined(MSDOS) || defined(OS2)
  264. "n # Maximum number of pages        P s Load $s.cfg",
  265. #else
  266. "n # Maximum number of pages        P s Load config.$s",
  267. #endif
  268. "o f Output file                    R   Run securely",
  269. "p # First page                     S # Max section size in pages",
  270. "q*  Run quietly                    T c Specify desired page size",
  271. "r*  Reverse order of pages         U*  Disable string param trick",
  272. "s*  Enclose output in save/restore V*  Send downloadable PS fonts as PK",
  273. "t s Paper format                   X # Horizontal resolution",
  274. "x # Override dvi magnification     Y # Vertical resolution",  
  275. "                                   Z*  Compress bitmap fonts",
  276. /* "-   Interactive query of options", */
  277. "    # = number   f = file   s = string  * = suffix, `0' to turn off",
  278. "    c = comma-separated dimension pair (e.g., 3.2in,-32.1cm)", 0} ;
  279. void help() {
  280.    char **p ;
  281.    for (p=helparr; *p; p++)
  282.       fprintf(stderr, " %s\n", *p) ;
  283. }
  284. /*
  285.  *   This error routine prints an error message; if the first
  286.  *   character is !, it aborts the job.
  287.  */
  288. static char *progname ;
  289. void
  290. error(s)
  291.         char *s ;
  292. {
  293.    extern void exit() ;
  294.  
  295.    if (prettycolumn > 0)
  296.         fprintf(stderr,"\n");
  297.    prettycolumn = 0;
  298.    (void)fprintf(stderr, "%s: %s\n", progname, s) ;
  299.    if (*s=='!') {
  300.       if (bitfile != NULL) {
  301.          cleanprinter() ;
  302.       }
  303.       exit(1) ; /* fatal */
  304.    }
  305. }
  306. /*
  307.  *   This is our malloc that checks the results.  We debug the
  308.  *   allocations but not the frees, since memory fragmentation
  309.  *   might be such that we can never use the free'd memory and
  310.  *   it's wise to be conservative.  The only real place we free
  311.  *   is when repacking *huge* characters anyway.
  312.  */
  313. #ifdef DEBUG
  314. static integer totalalloc = 0 ;
  315. #endif
  316. char *mymalloc(n)
  317. integer n ;
  318. {
  319.    char *p ;
  320.  
  321. #ifdef SMALLMALLOC
  322.    if (n > 65500L)
  323.       error("! can't allocate more than 64K!") ;
  324. #endif
  325.    if (n <= 0) /* catch strange 0 mallocs in flib.c without breaking code */
  326.       n = 1 ;
  327. #ifdef DEBUG
  328.    totalalloc += n ;
  329.    if (dd(D_MEM)) {
  330. #ifdef SHORTINT
  331.       fprintf(stderr, "Alloc %ld\n", n) ;
  332. #else
  333.       fprintf(stderr, "Alloc %d\n", n) ;
  334. #endif
  335.    }
  336. #endif
  337.    p = malloc(n) ;
  338.    if (p == NULL)
  339.       error("! no memory") ;
  340.    return p ;
  341. }
  342. void
  343. morestrings() {
  344.    strings = mymalloc((integer)STRINGSIZE) ;
  345.    nextstring = strings ;
  346.    maxstring = strings + STRINGSIZE - 200 ;
  347.    *nextstring++ = 0 ;
  348. }
  349. void
  350. checkstrings() {
  351.    if (nextstring - strings > STRINGSIZE / 2)
  352.       morestrings() ;
  353. }
  354. /*
  355.  *   Initialize sets up all the globals and data structures.
  356.  */
  357. void
  358. initialize()
  359. {
  360.    int i;
  361.    char *s;
  362.  
  363.    nextfonthd = 0;
  364.    for (i=0; i<256; i++)
  365.       xdig[i] = 0;
  366.    i = 0;
  367.    for (s="0123456789ABCDEF"; *s!=0; s++)
  368.       xdig[(int)*s] = i++;
  369.    i = 10;
  370.    for (s="abcdef"; *s!=0; s++)
  371.       xdig[(int)*s] = i++;
  372.    morestrings() ;
  373.    maxpages = 100000 ;
  374.    numcopies = 1 ;
  375.    iname = fulliname = strings ;
  376.    bitfile = NULL ;
  377.    bytesleft = 0 ;
  378.    swmem = SWMEM ;
  379.    oname = OUTPATH ;
  380.    sendcontrolD = 0 ;
  381.    multiplesects = 0 ;
  382.    disablecomments = 0 ;
  383.    maxdrift = -1 ;
  384.    vmaxdrift = -1 ;
  385. }
  386. /*
  387.  *   This routine copies a string into the string `pool', safely.
  388.  */
  389. char *
  390. newstring(s)
  391.    char *s ;
  392. {
  393.    int l ;
  394.  
  395.    if (s == NULL)
  396.       return(NULL) ;
  397.    l = strlen(s) ;
  398.    if (nextstring + l >= maxstring)
  399.       morestrings() ;
  400.    if (nextstring + l >= maxstring)
  401.       error("! out of string space") ;
  402.    (void)strcpy(nextstring, s) ;
  403.    s = nextstring ;
  404.    nextstring += l + 1 ;
  405.    return(s) ;
  406. }
  407. void newoutname() {
  408.    static int seq = 0 ;
  409.    static char *seqptr = 0 ;
  410.    char *p ;
  411.  
  412.    if (oname == 0 || *oname == 0)
  413.       error("! need an output file name to specify separate files") ;
  414.    if (*oname != '!' && *oname != '|') {
  415.       if (seqptr == 0) {
  416.          oname = newstring(oname) ;
  417.          seqptr = 0 ;
  418.          for (p = oname; *p; p++)
  419.             if (*p == '.')
  420.                seqptr = p + 1 ;
  421.          if (seqptr == 0)
  422.             seqptr = p ;
  423.          nextstring += 5 ; /* make room for the number, up to five digits */
  424.       }
  425.       sprintf(seqptr, "%03d", ++seq) ;
  426.    }
  427. }
  428. /*
  429.  *   This routine reverses a list, where a list is defined to be any
  430.  *   structure whose first element is a pointer to another such structure.
  431.  */
  432. VOID *revlist(p)
  433. VOID *p ;
  434. {
  435.    struct list {
  436.       struct list *next ;
  437.    } *pp = (struct list *)p, *qq = 0, *tt ;
  438.  
  439.    while (pp) {
  440.       tt = pp->next ;
  441.       pp->next = qq ;
  442.       qq = pp ;
  443.       pp = tt ;
  444.    }
  445.    return (VOID *)qq ;
  446. }
  447. /* this asks for a new set of arguments from the command line */
  448. void
  449. queryargs()
  450. {
  451.    fputs("Options: ",stdout);
  452.    fgets(queryline,256,stdin);
  453.    qargc=1;
  454.    if ( (qargv[1] = strtok(queryline," \n")) != (char *)NULL ) {
  455.       qargc=2;
  456.       while ( ((qargv[qargc] = strtok((char *)NULL," \n")) != (char *)NULL)
  457.             && (qargc < 31) )
  458.          qargc++;
  459.    }
  460.    qargv[qargc] = (char *)NULL;
  461. }
  462.  
  463. /*
  464.  *   Finally, our main routine.
  465.  */
  466. extern void handlepapersize() ;
  467. #ifdef VMS
  468. main()
  469. #else
  470. void main(argc, argv)
  471.         int argc ;
  472.         char *argv[] ;
  473. #endif
  474. {
  475.    extern void exit() ;
  476.    int i, lastext = -1 ;
  477. #ifdef MVSXA
  478.    int firstext = -1 ;
  479. #endif
  480.    register sectiontype *sects ;
  481.  
  482. #ifdef __THINK__
  483.    argc = dcommand(&argv) ; /* do I/O stream redirection */
  484. #endif
  485. #ifdef VMS        /* Grab the command-line buffer */
  486.    short len_arg;
  487.    $DESCRIPTOR( verb_dsc, "DVIPS ");    /* assume the verb is always DVIPS */
  488.    struct dsc$descriptor_d temp_dsc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_D, 0};
  489.  
  490.    progname = &thh[0] ;
  491.    strcpy(progname,"DVIPS%ERROR");
  492.  
  493.    lib$get_foreign( &temp_dsc, 0, &len_arg, 0);    /* Get the command line */
  494.    str$prefix(&temp_dsc, &verb_dsc);        /* prepend the VERB     */
  495.    len_arg += verb_dsc.dsc$w_length;        /* update the length    */
  496.    temp_dsc.dsc$a_pointer[len_arg] = '\0';    /* terminate the string */
  497.    gargv = &temp_dsc.dsc$a_pointer;        /* point to the buffer  */
  498.    gargc = 1 ;                    /* only one big argv    */
  499. #else
  500.    progname = argv[0] ;
  501.    gargv = argv ;
  502.    gargc = argc ;
  503. /* we sneak a look at the first arg in case it's debugging */
  504. #ifdef DEBUG
  505.    if (argc > 1 && strncmp(argv[1], "-d", 2)==0) {
  506.       if (argv[1][2]==0) {
  507.          if (sscanf(argv[2], "%d", &debug_flag)==0)
  508.             debug_flag = 0 ;
  509.       } else {
  510.          if (sscanf(argv[1]+2, "%d", &debug_flag)==0)
  511.             debug_flag = 0 ;
  512.       }
  513.    }
  514. #endif
  515. #endif
  516.    initialize() ;
  517.    checkenv(0) ;
  518.    getdefaults(CONFIGFILE) ;
  519.    getdefaults((char *)0) ;
  520. /*
  521.  *   This next whole big section of code is straightforward; we just scan
  522.  *   the options.  An argument can either immediately follow its option letter
  523.  *   or be separated by spaces.  Any argument not preceded by '-' and an
  524.  *   option letter is considered a file name; the program complains if more
  525.  *   than one file name is given, and uses stdin if none is given.
  526.  */
  527. #ifdef VMS
  528. vmscli();
  529. #else
  530.    queryoptions = 0;
  531.    do
  532.    {
  533.       for (i=1; i<argc; i++) {
  534.          if (*argv[i]=='-') {
  535.             char *p=argv[i]+2 ;
  536.             char c=argv[i][1] ;
  537.             switch (c) {
  538. case '-':
  539.                queryoptions = 1;
  540.                break;
  541. case 'a':
  542.                dopprescan = (*p != '0') ;
  543.                break ;
  544. case 'b':
  545.                if (*p == 0 && argv[i+1])
  546.                   p = argv[++i] ;
  547.                if (sscanf(p, "%d", &pagecopies)==0)
  548.                   error("! Bad number of page copies option (-b).") ;
  549.                if (pagecopies < 1 || pagecopies > 1000)
  550.                   error("! can only print one to a thousand page copies") ;
  551.                break ;
  552. case 'c' :
  553.                if (*p == 0 && argv[i+1])
  554.                   p = argv[++i] ;
  555.                if (sscanf(p, "%d", &numcopies)==0)
  556.                   error("! Bad number of copies option (-c).") ;
  557.                break ;
  558. case 'd' :
  559. #ifdef DEBUG
  560.                if (*p == 0 && argv[i+1])
  561.                   p = argv[++i];
  562.                if (sscanf(p, "%d", &debug_flag)==0)
  563.                   error("! Bad debug option (-d).");
  564.                break;
  565. #else
  566.                error("not compiled in debug mode") ;
  567.                break ;
  568. #endif /* DEBUG */
  569. case 'e' :
  570.                if (*p == 0 && argv[i+1])
  571.                   p = argv[++i] ;
  572.                if (sscanf(p, "%d", &maxdrift)==0 || maxdrift<0)
  573.                   error("! Bad maxdrift option (-e).") ;
  574.                vmaxdrift = maxdrift;
  575.                break ;
  576. case 'f' :
  577.                filter = (*p != '0') ;
  578.                if (filter)
  579.                   oname = "" ;
  580.                noenv = 1 ;
  581.                sendcontrolD = 0 ;
  582.                break ;
  583. case 'h' : case 'H' :
  584.                if (*p == 0 && argv[i+1])
  585.                   p = argv[++i] ;
  586.                if (strcmp(p, "-") == 0)
  587.                   headers_off = 1 ;
  588.                else
  589.                   (void)add_header(p) ;
  590.                break ;
  591. case 'i':
  592.                sepfiles = (*p != '0') ;
  593.                break ;
  594. case 'k':
  595.                cropmarks = (*p != '0') ;
  596.                break ;
  597. case 'R':
  598.                secure = 1 ;
  599.                break ;
  600. case 'S':
  601.                if (*p == 0 && argv[i+1])
  602.                   p = argv[++i] ;
  603.                if (sscanf(p, "%d", &maxsecsize)==0)
  604.                   error("! Bad section size arg (-S).") ;
  605.                break ;
  606. case 'm' :
  607.                manualfeed = (*p != '0') ;
  608.                break ;
  609. case 'n' :
  610.                if (*p == 0 && argv[i+1])
  611.                   p = argv[++i] ;
  612. #ifdef SHORTINT
  613.                if (sscanf(p, "%ld", &maxpages)==0)
  614. #else        /* ~SHORTINT */
  615.                if (sscanf(p, "%d", &maxpages)==0)
  616. #endif        /* ~SHORTINT */
  617.                   error("! Bad number of pages option (-n).") ;
  618.                break ;
  619. case 'o' :
  620.                if (*p == 0 && argv[i+1] && *argv[i+1]!='-')
  621.                   p = argv[++i] ;
  622.                oname = p ;
  623.                noenv = 1 ;
  624.                sendcontrolD = 0 ;
  625.                break ;
  626. case 'O' :
  627.                if (*p == 0 && argv[i+1])
  628.                   p = argv[++i] ;
  629.                handlepapersize(p, &hoff, &voff) ;
  630.                break ;
  631. case 'T' :
  632.                if (*p == 0 && argv[i+1])
  633.                   p = argv[++i] ;
  634.                handlepapersize(p, &hpapersize, &vpapersize) ;
  635.                if (landscape) {
  636.                   error(
  637.               "both landscape and papersize specified; ignoring landscape") ;
  638.                   landscape = 0 ;
  639.                }
  640.                break ;
  641. case 'p' :
  642. #if defined(MSDOS) || defined(OS2) || defined(ATARIST)
  643.                /* check for emTeX job file (-pj=filename) */
  644.                if (*p == 'j') {
  645.                  p++;
  646.                  if (*p == '=' || *p == ':')
  647.                    p++;
  648.                  mfjobname = newstring(p);
  649.                  break;
  650.                }
  651.                /* must be page number instead */
  652. #endif
  653.                if (*p == 'p') {  /* a -pp specifier for a page list? */
  654.                   p++ ;
  655.                   if (*p == 0 && argv[i+1])
  656.                      p = argv[++i] ;
  657.                   if (ParsePages(p))
  658.                      error("! Bad page list specifier (-pp).") ;
  659.                   pagelist = 1 ;
  660.                   break ;
  661.                }
  662.                if (*p == 0 && argv[i+1])
  663.                   p = argv[++i] ;
  664.                if (*p == '=') {
  665.                   abspage = 1 ;
  666.                   p++ ;
  667.                }
  668. #ifdef SHORTINT
  669.                switch(sscanf(p, "%ld.%ld", &firstpage, &firstseq)) {
  670. #else        /* ~SHORTINT */
  671.                switch(sscanf(p, "%d.%d", &firstpage, &firstseq)) {
  672. #endif        /* ~SHORTINT */
  673. case 1:           firstseq = 0 ;
  674. case 2:           break ;
  675. default:
  676.                   error("! Bad first page option (-p).") ;
  677.                }
  678.                notfirst = 1 ;
  679.                break ;
  680. case 'l':
  681.                if (*p == 0 && argv[i+1])
  682.                   p = argv[++i] ;
  683.                if (*p == '=') {
  684.                   abspage = 1 ;
  685.                   p++ ;
  686.                }
  687. #ifdef SHORTINT
  688.                switch(sscanf(p, "%ld.%ld", &lastpage, &lastseq)) {
  689. #else        /* ~SHORTINT */
  690.                switch(sscanf(p, "%d.%d", &lastpage, &lastseq)) {
  691. #endif        /* ~SHORTINT */
  692. case 1:           lastseq = 0 ;
  693. case 2:           break ;
  694. default:
  695.                   error("! Bad last page option (-l).") ;
  696.                }
  697.                notlast = 1 ;
  698.                break ;
  699. case 'A':
  700.                oddpages = 1 ;
  701.                break ;
  702. case 'B':
  703.                evenpages = 1 ;
  704.                break ;
  705. case 'q' : case 'Q' :
  706.                quiet = (*p != '0') ;
  707.                break ;
  708. case 'r' :
  709.                reverse = (*p != '0') ;
  710.                break ;
  711. case 't' :
  712.                if (*p == 0 && argv[i+1])
  713.                   p = argv[++i] ;
  714.                if (strcmp(p, "landscape") == 0) {
  715.                   if (hpapersize || vpapersize)
  716.                      error(
  717.              "both landscape and papersize specified; ignoring landscape") ;
  718.                   else
  719.                      landscape = 1 ;
  720.                } else
  721.                   paperfmt = p ;
  722.                break ;
  723. case 'x' : case 'y' :
  724.                if (*p == 0 && argv[i+1])
  725.                   p = argv[++i] ;
  726. #ifndef ATARIST
  727.                if (sscanf(p, "%d", &mag)==0 || mag < 10 ||
  728. #else
  729.                if (sscanf(p, "%ld", &mag)==0 || mag < 10 ||
  730. #endif
  731.                           mag > 100000)
  732.                   error("! Bad magnification parameter (-x).") ;
  733.                overridemag = (c == 'x' ? 1 : -1) ;
  734.                break ;
  735. case 'C' :
  736.                if (*p == 0 && argv[i+1])
  737.                   p = argv[++i] ;
  738.                if (sscanf(p, "%d", &collatedcopies)==0)
  739.                   error("! Bad number of collated copies option (-C).") ;
  740.                break ;
  741. case 'D' :
  742.                if (*p == 0 && argv[i+1])
  743.                   p = argv[++i] ;
  744.                if (sscanf(p, "%d", &actualdpi)==0 || actualdpi < 10 ||
  745.                           actualdpi > 10000)
  746.                   error("! Bad dpi parameter (-D).") ;
  747.                vactualdpi = actualdpi;
  748.                break ;
  749. case 'E' :
  750.                tryepsf = (*p != '0') ;
  751.                break ;
  752. case 'K' :
  753.                removecomments = (*p != '0') ;
  754.                break ;
  755. case 'U' :
  756.                nosmallchars = (*p != '0') ;
  757.                break ;
  758. case 'X' :
  759.                if (*p == 0 && argv[i+1])
  760.                   p = argv[++i] ;
  761.                if (sscanf(p, "%d", &actualdpi)==0 || actualdpi < 10 ||
  762.                           actualdpi > 10000)
  763.                   error("! Bad dpi parameter (-D).") ;
  764.                break ;
  765. case 'Y' :
  766.                if (*p == 0 && argv[i+1])
  767.                   p = argv[++i] ;
  768.                if (sscanf(p, "%d", &vactualdpi)==0 || vactualdpi < 10 ||
  769.                           vactualdpi > 10000)
  770.                   error("! Bad dpi parameter (-D).") ;
  771.                vactualdpi = vactualdpi;
  772.                break ;
  773. case 'F' :
  774.                sendcontrolD = (*p != '0') ;
  775.                break ;
  776. case 'M':
  777.                dontmakefont = (*p != '0') ;
  778.                break ;
  779. case 'N' :
  780.                disablecomments = (*p != '0') ;
  781.                break ;
  782. case 'P' :
  783.                {
  784.                   struct papsiz *opapsiz = papsizes ;
  785.                   struct papsiz *npapsiz ;
  786.                   papsizes = 0 ;
  787.                   if (*p == 0 && argv[i+1])
  788.                      p = argv[++i] ;
  789.                   printer = p ;
  790.                   noenv = 1 ;
  791.                   getdefaults("") ;
  792.           npapsiz = opapsiz ;
  793.                   while (npapsiz && npapsiz->next)
  794.                      npapsiz = npapsiz->next ;
  795.                   if (npapsiz) { printf("Got a new papersize\n") ;
  796.                      npapsiz->next = papsizes ;
  797.                      papsizes = opapsiz ;
  798.                   }
  799.            }
  800.                break ;
  801. case 's' :
  802.                safetyenclose = (*p != '0') ;
  803.                break ;
  804. case 'V':
  805.                downloadpspk = (*p != '0') ;
  806.                break ;
  807. case 'Z' :
  808.                compressed = (*p != '0') ;
  809.                break ;
  810. case '?' :
  811.                (void)fprintf(stderr, banner) ;
  812.                help() ;
  813.                break ;
  814. default:
  815.                error(
  816.               "! Bad option, not one of acdefhiklmnopqrstxCDEFKMNOPSTUXYZ?") ;
  817.             }
  818.          } else {
  819.             if (*iname == 0) {
  820.                register char *p ;
  821.    
  822.                lastext = 0 ;
  823.                iname = nextstring ;
  824.                p = argv[i] ;
  825.                while (*p) {
  826.                   *nextstring = *p++ ;
  827.                   if (*nextstring == '.')
  828.                      lastext = nextstring - iname ;
  829.                   else if (*nextstring == '/' || *nextstring == ':')
  830.                      lastext = 0 ;
  831.                   nextstring++ ;
  832.                }
  833.                *nextstring++ = '.' ;
  834.                *nextstring++ = 'd' ;
  835.                *nextstring++ = 'v' ;
  836.                *nextstring++ = 'i' ;
  837.                *nextstring++ = 0 ;
  838.             } else
  839.                error("! Two input file names specified.") ;
  840.          }
  841.       }
  842.       if (noenv == 0) {
  843.          register char *p ;
  844.          struct papsiz *opapsiz = papsizes ;
  845.          extern char *getenv() ;
  846.          papsizes = 0 ;
  847.      if (0 != (p = getenv("PRINTER"))) {
  848. #if defined(MSDOS) || defined(OS2)
  849.             strcpy(nextstring, p) ;
  850.             strcat(nextstring, ".cfg") ;
  851. #else
  852.             strcpy(nextstring, "config.") ;
  853.             strcat(nextstring, p) ;
  854. #endif
  855.             getdefaults(nextstring) ;
  856.          }
  857.          {
  858.             struct papsiz *npapsiz = opapsiz ;
  859.             while (npapsiz && npapsiz->next)
  860.                npapsiz = npapsiz->next ;
  861.             if (npapsiz) { printf("Got a new papersize\n") ;
  862.                npapsiz->next = papsizes ;
  863.                papsizes = opapsiz ;
  864.             }
  865.          }
  866.       }
  867.       papsizes = (struct papsiz *)revlist((void *)papsizes) ;
  868.       if (queryoptions != 0) {            /* get new options */
  869.          (void)fprintf(stderr, banner) ;
  870.          help() ;
  871.          queryargs();
  872.          if (qargc == 1)
  873.            queryoptions = 0;
  874.          else {
  875.            qargv[0] = argv[0];
  876.            argc=qargc;
  877.            argv=qargv;
  878.          }
  879.       }
  880.    } while (queryoptions != 0) ;
  881. #endif
  882.    checkenv(1) ;
  883. /*
  884.  *   The logic here is a bit convoluted.  Since all `additional'
  885.  *   PostScript font information files are loaded *before* the master
  886.  *   one, and yet they should be able to override the master one, we
  887.  *   have to add the information in the master list to the *ends* of
  888.  *   the hash chain.  We do this by reversing the lists, adding them
  889.  *   to the front, and then reversing them again.
  890.  */
  891.    revpslists() ;
  892.    getpsinfo((char *)NULL) ;
  893.    revpslists() ;
  894.    if (!quiet)
  895.       (void)fprintf(stderr, banner) ;
  896.    if (*iname) {
  897.       dvifile = fopen(iname, READBIN) ;
  898. /*
  899.  *   Allow names like a.b.
  900.  */
  901.       if (dvifile == 0) {
  902.          iname[strlen(iname)-4] = 0 ; /* remove the .dvi suffix */
  903.          dvifile = fopen(iname, READBIN) ;
  904.       }
  905.    }
  906.    if (oname[0] == '-' && oname[1] == 0)
  907.       oname[0] = 0 ;
  908.    if (*oname == 0 && ! filter) {
  909.       oname = nextstring ;
  910. #ifndef VMCMS  /* get stuff before LAST "." */
  911.       lastext = strlen(iname) - 1 ;
  912.       while (iname[lastext] != '.' && lastext > 0)
  913.          lastext-- ;
  914.       if (iname[lastext] != '.')
  915.          lastext = strlen(iname) - 1 ;
  916. #else   /* for VM/CMS we take the stuff before FIRST "." */
  917.       lastext = strchr(iname,'.') - iname ;
  918.       if ( lastext <= 0 )     /* if no '.' in "iname" */
  919.          lastext = strlen(iname) -1 ;
  920. #endif
  921. #ifdef MVSXA /* IBM: MVS/XA */
  922.       if (strchr(iname, '(') != NULL  &&
  923.           strchr(iname, ')') != NULL) {
  924.       firstext = strchr(iname, '(') - iname + 1;
  925.       lastext = strrchr(iname, ')') - iname - 1;
  926.          }
  927.       else {
  928.       if (strrchr(iname, '.') != NULL) {
  929.       lastext = strrchr(iname, '.') - iname - 1;
  930.            }
  931.          else lastext = strlen(iname) - 1 ;
  932.       if (strchr(iname, '\'') != NULL)
  933.          firstext = strchr(iname, '.') - iname + 1;
  934.          else firstext = 0;
  935.       }
  936. #endif  /* IBM: MVS/XA */
  937. #ifdef MVSXA /* IBM: MVS/XA */
  938.       for (i=firstext; i<=lastext; i++)
  939. #else
  940.       for (i=0; i<=lastext; i++)
  941. #endif
  942.          *nextstring++ = iname[i] ;
  943.       if (iname[lastext] != '.')
  944.          *nextstring++ = '.' ;
  945. #ifndef VMCMS
  946.       *nextstring++ = 'p' ;
  947.       *nextstring++ = 's' ;
  948. #else  /* might as well keep things uppercase */
  949.       *nextstring++ = 'P' ;
  950.       *nextstring++ = 'S' ;
  951. #endif
  952.       *nextstring++ = 0 ;
  953. /*
  954.  *   Now we check the name, and `throw away' any prefix information.
  955.  *   This means throwing away anything before (and including) a colon
  956.  *   or slash.
  957.  */
  958.       {
  959.          char *p ;
  960.  
  961.          for (p=oname; *p && p[1]; p++)
  962.             if (*p == ':' || *p == DIRSEP)
  963.                oname = p + 1 ;
  964.       }
  965.    }
  966. #ifdef DEBUG
  967.    if (dd(D_PATHS)) {
  968. #ifdef SHORTINT
  969.         (void)fprintf(stderr,"input file %s output file %s swmem %ld\n",
  970. #else /* ~SHORTINT */
  971.            (void)fprintf(stderr,"input file %s output file %s swmem %d\n",
  972. #endif /* ~SHORTINT */
  973.            iname, oname, swmem) ;
  974.    (void)fprintf(stderr,"tfm path %s\npk path %s\n", tfmpath, pkpath) ;
  975.    (void)fprintf(stderr,"fig path %s\nvf path %s\n", figpath, vfpath) ;
  976.    (void)fprintf(stderr,"config path %s\nheader path %s\n",
  977.                   configpath, headerpath) ;
  978. #ifdef AMIGA
  979.    (void)fprintf(stderr,"pict path %s\n", pictpath);
  980. #endif
  981.  
  982. #ifdef FONTLIB
  983.    (void)fprintf(stderr,"fli path %s\nfli names %s\n", flipath, fliname) ;
  984. #endif
  985.    } /* dd(D_PATHS) */
  986. #endif /* DEBUG */
  987. /*
  988.  *   Now we try to open the dvi file.
  989.  */
  990.    if (warningmsg)
  991.       error(warningmsg) ;
  992.    headersready = 1 ;
  993.    headerfile = (compressed? CHEADERFILE : HEADERFILE) ;
  994.    (void)add_header(headerfile) ;
  995.    if (*iname != 0) {
  996.       fulliname = nextstring ;
  997. #ifndef IGNORE_CWD
  998.       if (*iname != '/') {
  999.         getcwd(nextstring, MAXPATHLEN + 2);
  1000.         while (*nextstring++) ;
  1001. #ifdef VMS        /* VMS doesn't need the '/' character appended */
  1002.         nextstring--;    /* so just back up one byte. */
  1003. #else
  1004. #ifdef AMIGA
  1005.         if (*(nextstring-2) == VOLSEP)
  1006.            nextstring--; /* The Amiga doesn't need the '/' character appended */
  1007.         else             /* after a volume name */
  1008. #endif /* AMIGA */
  1009.         *(nextstring-1) = '/' ;
  1010. #endif
  1011.       }
  1012. #endif
  1013.       strcpy(nextstring,iname) ;
  1014.       while (*nextstring++) ; /* advance nextstring past fulliname */
  1015.    } else if (filter)
  1016.       dvifile = stdin;
  1017.    else {
  1018.       help() ;
  1019.       exit(0) ;
  1020.    }
  1021.    initcolor() ;
  1022.    if (dvifile==NULL) {
  1023.       extern char errbuf[];
  1024.       (void)sprintf(errbuf,"! DVI file <%s> can't be opened.", iname) ;
  1025.       error("! DVI file can't be opened.") ;
  1026.    }
  1027.    if (fseek(dvifile, 0L, 0) < 0)
  1028.       error("! DVI file must not be a pipe.") ;
  1029. #ifdef FONTLIB
  1030.    fliload();    /* read the font libaries */
  1031. #endif
  1032. /*
  1033.  *   Now we do our main work.
  1034.  */
  1035.    swmem += fontmem ;
  1036.    if (maxdrift < 0) {
  1037.       if (actualdpi <= 599)
  1038.          maxdrift = actualdpi / 100 ;
  1039.       else if (actualdpi < 1199)
  1040.          maxdrift = actualdpi / 200 + 3 ;
  1041.       else
  1042.          maxdrift = actualdpi / 400 + 6 ;
  1043.    }
  1044.    if (vmaxdrift < 0) {
  1045.       if (vactualdpi <= 599)
  1046.          vmaxdrift = vactualdpi / 100 ;
  1047.       else if (vactualdpi < 1199)
  1048.          vmaxdrift = vactualdpi / 200 + 3 ;
  1049.       else
  1050.          vmaxdrift = vactualdpi / 400 + 6 ;
  1051.    }
  1052.    if (dopprescan)
  1053.       pprescanpages() ;
  1054.    prescanpages() ;
  1055. #if defined MSDOS || defined OS2 || defined(ATARIST)
  1056.    if (mfjobfile != (FILE*)NULL) {
  1057.      char answer[5];
  1058.      fputs("}\n",mfjobfile);
  1059.      fclose(mfjobfile);
  1060.      fputs("Exit to make missing fonts now (y/n)? ",stdout);
  1061.      fgets(answer,4,stdin);
  1062.      if (*answer=='y' || *answer=='Y')
  1063.        exit(8); /* exit with errorlevel 8 for emTeX dvidrv */
  1064.    }
  1065. #endif
  1066.    if (includesfonts)
  1067.       (void)add_header(IFONTHEADER) ;
  1068.    if (usesPSfonts)
  1069.       (void)add_header(PSFONTHEADER) ;
  1070.    if (usesspecial)
  1071.       (void)add_header(SPECIALHEADER) ;
  1072.    if (usescolor)  /* IBM: color */
  1073.       (void)add_header(COLORHEADER) ;
  1074.    sects = sections ;
  1075.    totalpages *= collatedcopies ;
  1076.    if (sects == NULL || sects->next == NULL) {
  1077.       sectioncopies = collatedcopies ;
  1078.       collatedcopies = 1 ;
  1079.    } else {
  1080.       if (! sepfiles)
  1081.          multiplesects = 1 ;
  1082.    }
  1083.    totalpages *= pagecopies ;
  1084.    if (tryepsf) {
  1085.       if (totalpages != 1 || paperfmt || landscape || manualfeed ||
  1086.           collatedcopies > 1 || numcopies > 1 || cropmarks ||
  1087.           *iname == 0) {
  1088.          error("Can't make it EPSF, sorry") ;
  1089.          tryepsf = 0 ;
  1090.       }
  1091.    }
  1092.    if (! sepfiles) {
  1093.       initprinter(0) ;
  1094.       outbangspecials() ;
  1095.    }
  1096.    for (i=0; i<collatedcopies; i++) {
  1097.       sects = sections ;
  1098.       while (sects != NULL) {
  1099.          if (sepfiles) {
  1100.             newoutname() ;
  1101.             if (! quiet) {
  1102.                if (prettycolumn + strlen(oname) + 6 > STDOUTSIZE) {
  1103.                   fprintf(stderr, "\n") ;
  1104.                   prettycolumn = 0 ;
  1105.                }
  1106.                (void)fprintf(stderr, "(-> %s) ", oname) ;
  1107.                prettycolumn += strlen(oname) + 6 ;
  1108.             }
  1109.             initprinter(sects->numpages) ;
  1110.             outbangspecials() ;
  1111.          } else if (! quiet) {
  1112.             if (prettycolumn > STDOUTSIZE) {
  1113.                fprintf(stderr, "\n") ;
  1114.                prettycolumn = 0 ;
  1115.             }
  1116.             (void)fprintf(stderr, ". ") ;
  1117.             prettycolumn += 2 ;
  1118.          }
  1119.          (void)fflush(stderr) ;
  1120.          dosection(sects, sectioncopies) ;
  1121.          sects = sects->next ;
  1122.          if (sepfiles)
  1123.             cleanprinter() ;
  1124.       }
  1125.    }
  1126.    if (! sepfiles)
  1127.       cleanprinter() ;
  1128.    if (! quiet)
  1129.       (void)fprintf(stderr, "\n") ;
  1130. #ifdef DEBUG
  1131.    if (dd(D_MEM)) {
  1132. #ifdef SHORTINT
  1133.       fprintf(stderr, "Total memory allocated:  %ld\n", totalalloc) ;
  1134. #else
  1135.       fprintf(stderr, "Total memory allocated:  %d\n", totalalloc) ;
  1136. #endif
  1137.    }
  1138. #endif
  1139.    exit(0) ;
  1140.    /*NOTREACHED*/
  1141. }
  1142. #ifdef VMS
  1143. #include "[]vmscli.c"
  1144. #endif
  1145.  
  1146. #ifdef VMCMS  /* IBM: VM/CMS */
  1147. #include "dvipscms.h"
  1148. #endif
  1149.  
  1150. #ifdef MVSXA  /* IBM: MVS/XA */
  1151. #include "dvipsmvs.h"
  1152. #endif
  1153.