home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / t / tex / !dvips / Documents / Fonts / Source / c / resident < prev    next >
Encoding:
Text File  |  1994-10-24  |  27.2 KB  |  1,055 lines

  1. /*   For use with emTeX set FONTPATH to "TEXTFM"
  2.  */
  3. #ifndef FONTPATH
  4. #define FONTPATH "TEXFONTS"
  5. #endif
  6.  
  7. /*
  8.  *   This code reads in and handles the defaults for the program from the
  9.  *   file config.sw.  This entire file is a bit kludgy, sorry.
  10.  */
  11. #include "dvips.h" /* The copyright notice in that file is included too! */
  12. #include "paths.h"
  13. /*
  14.  *   This is the structure definition for resident fonts.  We use
  15.  *   a small and simple hash table to handle these.  We don't need
  16.  *   a big hash table.
  17.  */
  18. struct resfont *reshash[RESHASHPRIME] ;
  19. /*
  20.  *   These are the external routines we use.
  21.  */
  22. extern void error() ;
  23. extern integer scalewidth() ;
  24. extern int tfmload() ;
  25. extern FILE *search() ;
  26. extern shalfword pkbyte() ;
  27. extern integer pkquad() ;
  28. extern integer pktrio() ;
  29. extern Boolean pkopen() ;
  30. extern char *getenv() ;
  31. extern char *newstring() ;
  32. extern int add_header() ;
  33. extern int add_name() ;
  34. extern char *get_name() ;
  35. extern int system() ;
  36. extern void handlepapersize() ;
  37. extern void checkstrings() ;
  38. void getpsinfo() ;
  39. extern void *revlist() ;
  40. /*
  41.  *   These are the external variables we use.
  42.  */
  43. #ifdef DEBUG
  44. extern integer debug_flag;
  45. #endif  /* DEBUG */
  46. extern integer pagecopies ;
  47. extern int overridemag ;
  48. extern long bytesleft ;
  49. extern quarterword *raster ;
  50. extern FILE *pkfile ;
  51. extern char *oname ;
  52. extern integer swmem, fontmem ;
  53. extern char *tfmpath, *pictpath ;
  54. extern char *pkpath ;
  55. extern char *vfpath ;
  56. extern char *figpath ;
  57. extern char *configpath ;
  58. extern Boolean noenv ;
  59. extern Boolean downloadpspk ;
  60. #ifdef SEARCH_SUBDIRECTORIES
  61. extern char *fontsubdirpath ;
  62. #endif
  63. #ifdef FONTLIB
  64. extern char *flipath, *fliname ;
  65. #endif
  66. extern char *headerpath ;
  67. extern char *paperfmt ;
  68. extern char *nextstring ;
  69. extern char *maxstring ;
  70. extern char *warningmsg ;
  71. extern Boolean disablecomments ;
  72. extern Boolean compressed ;
  73. extern int quiet ;
  74. extern int filter ;
  75. extern Boolean reverse ;
  76. extern Boolean usesPSfonts ;
  77. extern Boolean nosmallchars ;
  78. extern Boolean removecomments ;
  79. extern Boolean safetyenclose ;
  80. extern Boolean dopprescan ;
  81. extern integer maxsecsize ;
  82. extern integer mag ;
  83. extern Boolean sepfiles ;
  84. extern int actualdpi ;
  85. extern int vactualdpi ;
  86. extern int maxdrift ;
  87. extern int vmaxdrift ;
  88. extern char *printer ;
  89. extern char *mfmode ;
  90. extern Boolean sendcontrolD ;
  91. extern int lastresortsizes[] ;
  92. extern integer hoff, voff ;
  93. extern struct papsiz *papsizes ;
  94. extern Boolean secure ;
  95. extern integer hpapersize, vpapersize ;
  96. extern int landscape ;
  97. /*
  98.  *   To maintain a list of document fonts, we use the following
  99.  *   pointer.
  100.  */
  101. struct header_list *ps_fonts_used ;
  102. /*
  103.  *   Our hash routine.
  104.  */
  105. int
  106. hash(s)
  107.    char *s ;
  108. {
  109.    int h = 12 ;
  110.  
  111.    while (*s != 0)
  112.       h = (h + h + *s++) % RESHASHPRIME ;
  113.    return(h) ;
  114. }
  115. /*
  116.  *   Reverse the hash chains.
  117.  */
  118. void
  119. revpslists() {
  120.    register int i ;
  121.    for (i=0; i<RESHASHPRIME; i++)
  122.       reshash[i] = (struct resfont *)revlist(reshash[i]) ;
  123. }
  124. /*
  125.  *   cleanres() marks all resident fonts as not being yet sent.
  126.  */
  127. void
  128. cleanres() {
  129.    register int i ;
  130.    register struct resfont *p ;
  131.    for (i=0; i<RESHASHPRIME; i++)
  132.       for (p=reshash[i]; p; p=p->next)
  133.          p->sent = 0 ;
  134. }
  135. /*
  136.  *   The routine that looks up a font name.
  137.  */
  138. struct resfont *
  139. lookup(name)
  140.    char *name ;
  141. {
  142.    struct resfont *p ;
  143.  
  144.    for (p=reshash[hash(name)]; p!=NULL; p=p->next)
  145.       if (strcmp(p->Keyname, name)==0)
  146.          return(p) ;
  147.    return(NULL) ;
  148. }
  149. /*
  150.  *   This routine adds an entry.
  151.  */
  152. void
  153. add_entry(TeXname, PSname, specinfo, downloadinfo)
  154.    char *TeXname, *PSname, *specinfo, *downloadinfo ;
  155. {
  156.    struct resfont *p ;
  157.    int h ;
  158.  
  159.    if (PSname == NULL)
  160.       PSname = TeXname ;
  161.    p = (struct resfont *)mymalloc((integer)sizeof(struct resfont)) ;
  162.    p->Keyname = TeXname ;
  163.    p->PSname = PSname ;
  164.    p->TeXname = TeXname ;
  165.    p->specialinstructions = specinfo ;
  166.    if (downloadinfo && *downloadinfo)
  167.       p->downloadheader = downloadinfo ;
  168.    else
  169.       p->downloadheader = 0 ;
  170.    h = hash(TeXname) ;
  171.    p->next = reshash[h] ;
  172.    p->sent = 0 ;
  173.    reshash[h] = p ;
  174. }
  175. /*
  176.  *   Now our residentfont routine.  Returns the number of characters in
  177.  *   this font, based on the TFM file.
  178.  */
  179. extern char *infont ;
  180. int
  181. residentfont(curfnt)
  182.         register fontdesctype *curfnt ;
  183. {
  184.    register shalfword i ;
  185.    struct resfont *p ;
  186.  
  187. /*
  188.  *   First we determine if we can find this font in the resident list.
  189.  */
  190.    if (*curfnt->area)
  191.       return 0 ; /* resident fonts never have a nonstandard font area */
  192.    if ((p=lookup(curfnt->name))==NULL)
  193.       return 0 ;
  194. /*
  195.  *   This is not yet the correct way to do things, but it is useful as it
  196.  *   is so we leave it in.  The problem:  if resident Times-Roman is
  197.  *   re-encoded, then it will be downloaded as bitmaps; this is not
  198.  *   right.  The solution will be to introduce two types of `<'
  199.  *   directives, one that downloads fonts and one that downloads
  200.  *   short headers that are innocuous.
  201.  */
  202.    if (p->downloadheader && downloadpspk) {
  203. #ifdef DEBUG
  204.       if (dd(D_FONTS))
  205.          (void)fprintf(stderr,"Using PK font %s for <%s>.\n",
  206.                                      curfnt->name, p->PSname) ;
  207. #endif  /* DEBUG */
  208.       return 0 ;
  209.    }
  210. /*
  211.  *   We clear out some pointers:
  212.  */
  213. #ifdef DEBUG
  214.    if (dd(D_FONTS))
  215.         (void)fprintf(stderr,"Font %s <%s> is resident.\n",
  216.                                      curfnt->name, p->PSname) ;
  217. #endif  /* DEBUG */
  218.    curfnt->resfont = p ;
  219.    curfnt->name = p->TeXname ;
  220.    for (i=0; i<256; i++) {
  221.       curfnt->chardesc[i].TFMwidth = 0 ;
  222.       curfnt->chardesc[i].packptr = NULL ;
  223.       curfnt->chardesc[i].pixelwidth = 0 ;
  224.       curfnt->chardesc[i].flags = 0 ;
  225.    }
  226.    add_name(p->PSname, &ps_fonts_used) ;
  227. /*
  228.  *   We include the font here.  But we only should need to include the
  229.  *   font if we have a stupid spooler; smart spoolers should be able
  230.  *   to supply it automatically.
  231.  */
  232.    if (p->downloadheader) {
  233.       char *cp = p->downloadheader ;
  234.       char *q ;
  235.  
  236.       infont = p->PSname ;
  237.       while (1) {
  238.          q = cp ;
  239.          while (*cp && *cp != ' ')
  240.             cp++ ;
  241.          if (*cp) {
  242.             *cp = 0 ;
  243.             add_header(q) ;
  244.             *cp++ = ' ' ;
  245.          } else {
  246.             add_header(q) ;
  247.             break ;
  248.          }
  249.          infont = 0 ;
  250.       }
  251.       infont = 0 ;
  252.    }
  253.    i = tfmload(curfnt) ;
  254.    if (i < 0)
  255.       i = 1 ;
  256.    usesPSfonts = 1 ;
  257.    return(i) ;
  258. }
  259. #define INLINE_SIZE (500)
  260. static char was_inline[INLINE_SIZE] ;
  261. void
  262. bad_config() {
  263.    extern void exit() ;
  264.  
  265.    error("Error in config file:") ;
  266.    (void)fprintf(stderr, "%s\n", was_inline) ;
  267.    exit(1) ;
  268. }
  269. /*
  270.  *   Get environment variables! These override entries in ./config.h.
  271.  *   We substitute everything of the form ::, ^: or :$ with default,
  272.  *   so a user can easily build on to the existing paths.
  273.  */
  274.  
  275. /*   In the case of RISC OS, to remain consistent with MJK's armTeX,
  276.  *   the environment variables replace rather than augment the
  277.  *   defaults.
  278.  */
  279. #ifdef RISCOS
  280. static char *replacepath(who, what)
  281. char *who, *what ;
  282. {
  283.    if (who) {
  284.       char *pp = nextstring ;
  285.  
  286.       strcpy (nextstring, who) ;
  287.       nextstring += strlen (who) + 1 ;
  288.  
  289.       return pp ;
  290.    } else
  291.       return what ;
  292. }
  293. static char *getpath(who, what)
  294. char *who, *what ;
  295. {
  296.    if (who) {
  297.       char *pp = nextstring ;
  298.  
  299.       strcpy (nextstring, who) ;
  300.       nextstring += strlen (who) ;
  301.       *nextstring++ = ',' ;
  302.       strcpy (nextstring, what) ;
  303.       nextstring += strlen (what) + 1 ;
  304.  
  305.       return pp ;
  306.    } else
  307.       return what ;
  308. }
  309. #else
  310. static char *getpath(who, what)
  311. char *who, *what ;
  312. {
  313.    if (who) {
  314.       register char *pp, *qq ;
  315.       int lastsep = 1 ;
  316.  
  317.       for (pp=nextstring, qq=who; *qq;) {
  318.          if (*qq == PATHSEP) {
  319.             if (lastsep) {
  320.                strcpy(pp, what) ;
  321.                pp = pp + strlen(pp) ;
  322.             }
  323.             lastsep = 1 ;
  324.          } else
  325.             lastsep = 0 ;
  326.          *pp++ = *qq++ ;
  327.       }
  328.       if (lastsep) {
  329.          strcpy(pp, what) ;
  330.          pp = pp + strlen(pp) ;
  331.       }
  332.       *pp = 0 ;
  333.       qq = nextstring ;
  334.       nextstring = pp + 1 ;
  335.       return qq ;
  336.    } else
  337.       return what ;
  338. }
  339. #endif
  340. /*
  341.  *   We use this function so we can support strings delimited by
  342.  *   double quotes with spaces in them.  We also accept strings
  343.  *   with spaces in them, but kill off any spaces at the end.
  344.  */
  345. char *configstring(s, nullok)
  346. char *s ;
  347. int nullok ;
  348. {
  349.    char tstr[300] ;
  350.    char *p = tstr ;
  351.  
  352.    while (*s && *s <= ' ')
  353.       s++ ;
  354.    if (*s == '"') {
  355.       s++ ;
  356.       while (*s != 10 && *s != 0 && *s != '"' && p < tstr+290)
  357.          *p++ = *s++ ;
  358.    } else {
  359.       while (*s && p < tstr+290)
  360.          *p++ = *s++ ;
  361.       while (*(p-1) <= ' ' && p > tstr)
  362.          p-- ;
  363.    }
  364.    *p = 0 ;
  365.    if (p == tstr && ! nullok)
  366.       bad_config() ;
  367.    return newstring(tstr) ;
  368. }
  369. /*
  370.  *   Now we have the getdefaults routine.
  371.  */
  372. static char *psmapfile = PSMAPFILE ;
  373. void
  374. getdefaults(s)
  375. char *s ;
  376. {
  377.    FILE *deffile ;
  378.    char PSname[300] ;
  379.    register char *p ;
  380.    int i, j ;
  381.    integer hsiz, vsiz ;
  382.    char *d = configpath ;
  383.    int canaddtopaper = 0 ;
  384.  
  385.    if (printer == NULL) {
  386.       if (s) {
  387.          strcpy(PSname, s) ;
  388.       } else {
  389. #ifndef VMCMS  /* IBM: VM/CMS - don't have home directory on VMCMS */
  390. #ifndef MVSXA
  391. #ifdef RISCOS  /* RISC OS has the symbol '&' for a user's root directory */
  392.          d = "&" ;
  393. #else
  394.          d = "~" ;
  395. #endif
  396. #endif
  397. #endif  /* IBM: VM/CMS */
  398.          strcpy(PSname, DVIPSRC) ;
  399.       }
  400.    } else {
  401. #if defined(MSDOS) || defined(OS2)
  402.       strcpy(PSname, printer) ;
  403.       strcat(PSname, ".cfg") ;
  404. #else
  405.       strcpy(PSname, "config.") ;
  406.       strcat(PSname, printer) ;
  407. #endif
  408.    }
  409.    if ((deffile=search(d,PSname,READ))!=NULL) {
  410.       while (fgets(was_inline, INLINE_SIZE, deffile)!=NULL) {
  411. /*
  412.  *   We need to get rid of the newline.
  413.  */
  414.        for (p=was_inline; *p; p++) ;
  415.        if (p > was_inline) *(p-1) = 0 ;
  416.        if (was_inline[0] != '@')
  417.           canaddtopaper = 0 ;
  418.        switch (was_inline[0]) {
  419. /*
  420.  *   Handling paper size information:
  421.  *
  422.  *      If line is empty, then we clear out the paper size information
  423.  *      we have so far.
  424.  *
  425.  *      If it is `@+', then we add to the current paper size info.
  426.  *
  427.  *      If it is `name hsize vsize', then we start a new definition.
  428.  */
  429. case '@' :
  430.          p = was_inline + 1 ;
  431.          while (*p && *p <= ' ') p++ ;
  432.          if (*p == 0) {
  433.             papsizes = 0 ; /* throw away memory */
  434.          } else if (*p == '+') {
  435.             if (canaddtopaper == 0)
  436.                error(
  437.       "can't have @+ in config file not immediately following a non-@ line") ;
  438.             else {
  439.                *(nextstring-1) = '\n' ;/* IBM: VM/CMS - changed 10 to "\n" */
  440.                p++ ;
  441.                while (*p && *p == ' ') p++ ;
  442.                strcpy(nextstring, p) ;
  443.                nextstring += strlen(p) + 1 ;
  444.             }
  445.          } else {
  446.             struct papsiz *ps ;
  447.  
  448.             ps = (struct papsiz *)mymalloc((integer)sizeof(struct papsiz)) ;
  449.             ps->next = papsizes ;
  450.             papsizes = ps ;
  451.             ps->name = p ;
  452.             while (*p && *p > ' ')
  453.                p++ ;
  454.             *p++ = 0 ;
  455.             ps->name = newstring(ps->name) ;
  456.             while (*p && *p <= ' ') p++ ;
  457.             handlepapersize(p, &hsiz, &vsiz) ;
  458.             ps->xsize = hsiz ;
  459.             ps->ysize = vsiz ;
  460.             ps->specdat = nextstring++ ;
  461.             canaddtopaper = 1 ;
  462.          }
  463.          break ;
  464. case 'a' :
  465.          dopprescan = (was_inline[1] != '0') ;
  466.          break ;
  467. case 'b':
  468. #ifdef SHORTINT
  469.          if (sscanf(was_inline+1, "%ld", &pagecopies) != 1) bad_config() ;
  470. #else
  471.          if (sscanf(was_inline+1, "%d", &pagecopies) != 1) bad_config() ;
  472. #endif
  473.          if (pagecopies < 1 || pagecopies > 1000)
  474.             bad_config() ;
  475.          break ;
  476. case 'm' :
  477. #ifdef SHORTINT
  478.          if (sscanf(was_inline+1, "%ld", &swmem) != 1) bad_config() ;
  479. #else   /* ~SHORTINT */
  480.          if (sscanf(was_inline+1, "%d", &swmem) != 1) bad_config() ;
  481. #endif  /* ~SHORTINT */
  482.          swmem += fontmem ; /* grab headers we've seen already */
  483.          break ;
  484. case 'M' :
  485.          mfmode = configstring(was_inline+1, 0) ;
  486.          break ;
  487. case 'o' :
  488.          oname = configstring(was_inline+1, 1) ;
  489.          if (*oname && oname[strlen(oname)-1] == ':')
  490.             sendcontrolD = 1 ; /* if we send to a device, *we* are spooler */
  491.          break ;
  492. case 'O' :
  493.          p = was_inline + 1 ;
  494.          handlepapersize(p, &hoff, &voff) ;
  495.          break ;
  496. #ifdef FONTLIB
  497. case 'L' :
  498.          {
  499.             char tempname[300] ;
  500.             extern char *fliparse() ;
  501.             if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
  502.             else {
  503.                flipath = getpath(fliparse(PSname,tempname), flipath);
  504.                fliname = newstring(tempname) ;
  505.             }
  506.      }
  507.          break ;
  508. #endif
  509. case 'T' :
  510.          if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
  511.          else tfmpath = getpath(PSname, tfmpath) ;
  512.          break ;
  513. case 'P' :
  514.          if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
  515.          else pkpath = getpath(PSname, pkpath) ;
  516.          break ;
  517. case 'p' :
  518.          p = was_inline + 1 ;
  519.          while (*p && *p <= ' ')
  520.             p++ ;
  521.          if (*p == '+') {
  522.             if (sscanf(p+1, "%s", PSname) != 1) bad_config() ;
  523.             getpsinfo(PSname) ;
  524.          } else {
  525.             psmapfile = configstring(was_inline+1, 0) ;
  526.          }
  527.          break ;
  528. case 'v' : case 'V' :
  529.          if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
  530.          else vfpath = getpath(PSname, vfpath) ;
  531.          break ;
  532. case 'S' :
  533.          if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
  534.          else figpath = getpath(PSname, figpath) ;
  535.          break ;
  536. case 's':
  537.          safetyenclose = 1 ;
  538.          break ;
  539. case 'H' :
  540.          if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
  541.          else headerpath = getpath(PSname, headerpath) ;
  542.          break ;
  543. case '%': case ' ' : case '*' : case '#' : case ';' :
  544. case '=' : case 0 : case '\n' :
  545.          break ;
  546. case 'r' :
  547.          reverse = (was_inline[1] != '0') ;
  548.          break ;
  549. /*
  550.  *   This case is for last resort font scaling; I hate this, but enough
  551.  *   people have in no uncertain terms demanded it that I'll go ahead and
  552.  *   add it.
  553.  *
  554.  *   This line must have numbers on it, resolutions, to search for the
  555.  *   font as a last resort, and then the font will be scaled.  These
  556.  *   resolutions should be in increasing order.
  557.  *
  558.  *   For most machines, just `300' is sufficient here; on the NeXT,
  559.  *   `300 400' may be more appropriate.
  560.  */
  561. case 'R':
  562.          i = 0 ;
  563.          p = was_inline + 1 ;
  564.          while (*p) {
  565.             while (*p && *p <= ' ')
  566.                p++ ;
  567.             if ('0' <= *p && *p <= '9') {
  568.                j = 0 ;
  569.                while ('0' <= *p && *p <= '9')
  570.                   j = 10 * j + (*p++ - '0') ;
  571.                if (i > 0)
  572.                   if (lastresortsizes[i-1] > j) {
  573.                      error("last resort sizes (R) must be sorted") ;
  574.                      bad_config() ;
  575.                   }
  576.                lastresortsizes[i++] = j ;
  577.             } else {
  578.                if (*p == 0)
  579.                   break ;
  580.                error("! only numbers expected on `R' line in config!") ;
  581.             }
  582.          }
  583.          lastresortsizes[i] = 32000 ;
  584.          break ;
  585. case 'D' :
  586.          if (sscanf(was_inline+1, "%d", &actualdpi) != 1) bad_config() ;
  587.          if (actualdpi < 10 || actualdpi > 10000) bad_config() ;
  588.      vactualdpi = actualdpi;
  589.          break ;
  590. /*
  591.  *   Execute a command.  This can be dangerous, but can also be very useful.
  592.  */
  593. case 'E' :
  594. #ifdef SECURE
  595.          error("dvips was compiled with SECURE, which disables E in config") ;
  596. #else
  597.          if (secure) {
  598.             error("dvips -R option used, which disables E in config") ;
  599.             break ;
  600.          }
  601.          (void)system(was_inline+1) ;
  602. #endif
  603.          break ;
  604. case 'K':
  605.          removecomments = (was_inline[1] != '0') ;
  606.          break ;
  607. case 'U':
  608.          nosmallchars = (was_inline[1] != '0') ;
  609.          break ;
  610. case 'W':
  611.          for (p=was_inline+1; *p && *p <= ' '; p++) ;
  612.          if (*p)
  613.             warningmsg = newstring(p) ;
  614.          else
  615.             warningmsg = 0 ;
  616.          break ;
  617. case 'X' :
  618.          if (sscanf(was_inline+1, "%d", &actualdpi) != 1) bad_config() ;
  619.          if (actualdpi < 10 || actualdpi > 10000) bad_config() ;
  620.          break ;
  621. case 'Y' :
  622.          if (sscanf(was_inline+1, "%d", &vactualdpi) != 1) bad_config() ;
  623.          if (vactualdpi < 10 || vactualdpi > 10000) bad_config() ;
  624.          break ;
  625. case 'x': case 'y':
  626.          if (sscanf(was_inline+1, "%d", &mag) != 1) bad_config() ;
  627.          overridemag = (was_inline[0] == 'x') ? 1 : -1 ;
  628.          break ;
  629. case 'e' :
  630.          if (sscanf(was_inline+1, "%d", &maxdrift) != 1) bad_config() ;
  631.          if (maxdrift < 0) bad_config() ;
  632.      vmaxdrift = maxdrift;
  633.          break ;
  634. case 'q' : case 'Q' :
  635.          quiet = (was_inline[1] != '0') ;
  636.          break ;
  637. case 'f' : case 'F' :
  638.          filter = (was_inline[1] != '0') ;
  639.          break ;
  640. case 'h' :
  641.          if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
  642.          else (void)add_header(PSname) ;
  643.          break ;
  644. case 'i' :
  645.          if (sscanf(was_inline+1, "%d", &maxsecsize) != 1)
  646.             maxsecsize = 0 ;
  647.          sepfiles = 1 ;
  648.          break ;
  649. case 'I':
  650.          noenv = (was_inline[1] != '0') ;
  651.          break ;
  652. case 'N' :
  653.          disablecomments = (was_inline[1] != '0') ;
  654.          break ;
  655. case 'Z' :
  656.          compressed = (was_inline[1] != '0') ;
  657.          break ;
  658. case 't' :
  659.          if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config() ;
  660.          else {
  661.            if (strcmp(PSname, "landscape") == 0) {
  662.                if (hpapersize || vpapersize)
  663.                   error(
  664.             "both landscape and papersize specified; ignoring landscape") ;
  665.                else
  666.                   landscape = 1 ;
  667.             } else
  668.                paperfmt = newstring(PSname) ;
  669.          }
  670.          break ;
  671. default:
  672.          bad_config() ;
  673.       }
  674.      }
  675.      (void)fclose(deffile) ;
  676.    } else {
  677.       if (printer)
  678.          error("! no such printer (can't find corresponding config file)") ;
  679.    }
  680. }
  681.  
  682. /*
  683.  *   If a character pointer is passed in, use that name; else, use the
  684.  *   default (possibly set) name.
  685.  */
  686. void getpsinfo(name)
  687. char *name ;
  688. {
  689.    FILE *deffile ;
  690.    register char *p ;
  691.    char *specinfo, *downloadinfo ;
  692.    char downbuf[200] ;
  693.  
  694.    if (name == 0)
  695.       name = psmapfile ;
  696.    if ((deffile=search(configpath, name, READ))!=NULL) {
  697.       while (fgets(was_inline, INLINE_SIZE, deffile)!=NULL) {
  698.          p = was_inline ;
  699.          if (*p > ' ' && *p != '*' && *p != '#' && *p != ';' && *p != '%') {
  700.             char *TeXname = NULL ;
  701.             char *PSname = NULL ;
  702.             specinfo = NULL ;
  703.             downloadinfo = NULL ;
  704.             downbuf[0] = 0 ;
  705.             while (*p) {
  706.                while (*p && *p <= ' ')
  707.                   p++ ;
  708.                if (*p) {
  709.                   if (*p == '"')
  710.                      specinfo = p + 1 ;
  711.                   else if (*p == '<') {
  712.                      if (downloadinfo) {
  713.                         strcat(downbuf, downloadinfo) ;
  714.                         strcat(downbuf, " ") ;
  715.                      }
  716.                      downloadinfo = p + 1 ;
  717.                   } else if (TeXname)
  718.                      PSname = p ;
  719.                   else
  720.                      TeXname = p ;
  721.                   if (*p == '"') {
  722.                      p++ ;
  723.                      while (*p != '"' && *p)
  724.                         p++ ;
  725.                   } else
  726.                      while (*p > ' ')
  727.                         p++ ;
  728.                   if (*p)
  729.                      *p++ = 0 ;
  730.                }
  731.             }
  732.             if (downloadinfo)
  733.                strcat(downbuf, downloadinfo) ;
  734.             if (TeXname) {
  735.                TeXname = newstring(TeXname) ;
  736.                specinfo = newstring(specinfo) ;
  737.                PSname = newstring(PSname) ;
  738.                downloadinfo = newstring(downbuf) ;
  739.                add_entry(TeXname, PSname, specinfo, downloadinfo) ;
  740.             }
  741.         }
  742.       }
  743.       (void)fclose(deffile) ;
  744.    }
  745.    checkstrings() ;
  746. }
  747. /*
  748.  *   Get environment variables! These override entries in ./config.h.
  749.  *   We substitute everything of the form ::, ^: or :$ with default,
  750.  *   so a user can easily build on to the existing paths.
  751.  */
  752. static char *getenvup(who, what)
  753. char *who, *what ;
  754. {
  755. #ifdef RISCOS
  756.    return replacepath(getenv(who), what) ;
  757. #else
  758.    return getpath(getenv(who), what) ;
  759. #endif
  760. }
  761. #ifdef SEARCH_SUBDIRECTORIES
  762. static char *concat3();
  763. #endif
  764.  
  765. /*   In the case of RISC OS, to remain consistent with MJK's armTeX,
  766.  *   the environment variables replace rather than augment the
  767.  *   defaults.
  768.  */
  769. #ifdef RISCOS
  770. void checkenv(which)
  771. int which ;
  772. {
  773.    if (which) {
  774.       tfmpath = getpath(getenv("dvipsFonts$Path"),
  775.                       getenvup("TeXFonts$Path", tfmpath)) ;
  776.       vfpath = tfmpath ;
  777.       pictpath = getenvup("TeXPicts$Path", pictpath) ;
  778.       figpath = getenvup("TeXInputs$Path", figpath) ;
  779.       headerpath = getenvup("dvipsHeader$Path", headerpath) ;
  780.       pkpath =  tfmpath ;
  781. #ifdef SEARCH_SUBDIRECTORIES
  782.       else if (getenv("TexFonts$Path"))
  783.          pkpath = getenvup("TexFonts$Path", pkpath) ;
  784.       if (getenv ("TexFonts$SubDir"))
  785.          fontsubdirpath = getenvup ("TexFonts$SubDir", fontsubdirpath);
  786.       {
  787.          char pathsep[2] ;
  788.          char *do_subdir_path();
  789.          char *dirs = do_subdir_path (fontsubdirpath);
  790.  
  791.          pathsep[0] = PATHSEP ;
  792.          pathsep[1] = '\0' ;
  793.          tfmpath = concat3 (tfmpath, pathsep, dirs);
  794.          pkpath = concat3 (pkpath, pathsep, dirs);
  795.       }
  796. #endif
  797.    } else
  798.       configpath = getenvup("dvips$Path", configpath) ;
  799. }
  800. #else
  801. void checkenv(which)
  802. int which ;
  803. {
  804.    if (which) {
  805.       tfmpath = getenvup(FONTPATH, tfmpath) ;
  806.       vfpath = getenvup("VFFONTS", vfpath) ;
  807.       pictpath = getenvup("TEXPICTS", pictpath) ;
  808.       figpath = getenvup("TEXINPUTS", figpath) ;
  809.       headerpath = getenvup("DVIPSHEADERS", headerpath) ;
  810.       if (getenv("TEXPKS"))
  811.          pkpath = getenvup("TEXPKS", pkpath) ;
  812.       else if (getenv("TEXPACKED"))
  813.          pkpath = getenvup("TEXPACKED", pkpath) ;
  814.       else if (getenv("PKFONTS"))
  815.          pkpath = getenvup("PKFONTS", pkpath) ;
  816. #ifdef SEARCH_SUBDIRECTORIES
  817.       else if (getenv(FONTPATH))
  818.          pkpath = getenvup(FONTPATH, pkpath) ;
  819.       if (getenv ("TEXFONTS_SUBDIR"))
  820.          fontsubdirpath = getenvup ("TEXFONTS_SUBDIR", fontsubdirpath);
  821.       {
  822.          char pathsep[2] ;
  823.          char *do_subdir_path();
  824.          char *dirs = do_subdir_path (fontsubdirpath);
  825.  
  826.          pathsep[0] = PATHSEP ;
  827.          pathsep[1] = '\0' ;
  828.          tfmpath = concat3 (tfmpath, pathsep, dirs);
  829.          pkpath = concat3 (pkpath, pathsep, dirs);
  830.       }
  831. #endif
  832.    } else
  833.       configpath = getenvup("TEXCONFIG", configpath) ;
  834. }
  835. #endif
  836.  
  837. #ifdef SEARCH_SUBDIRECTORIES
  838.  
  839. #include <sys/types.h>
  840. #include <sys/stat.h>
  841. #include <errno.h>
  842.  
  843. #ifdef SYSV
  844. #include <dirent.h>
  845. typedef struct dirent *directory_entry_type;
  846. #else
  847. #include <sys/dir.h>
  848. typedef struct direct *directory_entry_type;
  849. #endif
  850.  
  851. /* Declare the routine to get the current working directory.  */
  852.  
  853. #ifndef HAVE_GETCWD
  854. extern char *getwd ();
  855. #define getcwd(b, len)  ((b) ? getwd (b) : getwd (xmalloc (len)))
  856. #else
  857. #ifdef ANSI
  858. extern char *getcwd (char *, int);
  859. #else
  860. extern char *getcwd ();
  861. #endif /* not ANSI */
  862. #endif /* not HAVE_GETWD */
  863.  
  864. #if defined(SYSV) || defined(VMS) || defined(MSDOS) || defined(OS2)
  865. #define MAXPATHLEN (256)
  866. #else   /* ~SYSV */
  867. #include <sys/param.h>          /* for MAXPATHLEN */
  868. #endif
  869.  
  870. extern void exit() ;
  871. extern int chdir() ;
  872.  
  873. /* Memory operations: variants of malloc(3) and realloc(3) that just
  874.    give up the ghost when they fail.  */
  875.  
  876. extern char *realloc ();
  877.  
  878. char *
  879. xmalloc (size)
  880.   unsigned size;
  881. {
  882.   char *mem = malloc (size);
  883.  
  884.   if (mem == NULL)
  885.     {
  886.       fprintf (stderr, "! Cannot allocate %u bytes.\n", size);
  887.       exit (10);
  888.     }
  889.  
  890.   return mem;
  891. }
  892.  
  893.  
  894. char *
  895. xrealloc (ptr, size)
  896.   char *ptr;
  897.   unsigned size;
  898. {
  899.   char *mem = realloc (ptr, size);
  900.  
  901.   if (mem == NULL)
  902.     {
  903.       fprintf (stderr, "! Cannot reallocate %u bytes at %x.\n", size, ptr);
  904.       exit (10);
  905.     }
  906.  
  907.   return mem;
  908. }
  909.  
  910.  
  911. /* Return, in NAME, the next component of PATH, i.e., the characters up
  912.    to the next PATHSEP.  */
  913.  
  914. static void
  915. next_component (name, path)
  916.   char name[];
  917.   char **path;
  918. {
  919.   unsigned count = 0;
  920.  
  921.   while (**path != 0 && **path != PATHSEP)
  922.     {
  923.       name[count++] = **path;
  924.       (*path)++; /* Move further along, even between calls.  */
  925.     }
  926.  
  927.   name[count] = 0;
  928.   if (**path == PATHSEP)
  929.     (*path)++; /* Move past the delimiter.  */
  930. }
  931.  
  932.  
  933. #ifndef _POSIX_SOURCE
  934. #define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
  935. #endif
  936.  
  937. /* Return true if FN is a directory or a symlink to a directory,
  938.    false if not. */
  939.  
  940. int
  941. is_dir (fn)
  942.   char *fn;
  943. {
  944.   struct stat stats;
  945.  
  946.   return stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode);
  947. }
  948.  
  949.  
  950. static char *
  951. concat3 (s1, s2, s3)
  952.   char *s1, *s2, *s3;
  953. {
  954.   char *r = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
  955.   strcpy (r, s1);
  956.   strcat (r, s2);
  957.   strcat (r, s3);
  958.   return r;
  959. }
  960.  
  961.  
  962. /* DIR_LIST is the default list of directories (colon-separated) to
  963.    search.  We want to add all the subdirectories directly below each of
  964.    the directories in the path.
  965.  
  966.    We return the list of directories found.  */
  967.  
  968. char *
  969. do_subdir_path (dir_list)
  970.   char *dir_list;
  971. {
  972.   char *cwd;
  973.   unsigned len;
  974.   char *result = xmalloc ((unsigned)1);
  975.   char *temp = dir_list;
  976.   char dirsep[2] ;
  977.  
  978.   dirsep[0] = DIRSEP ;
  979.   dirsep[1] = '\0' ;
  980.  
  981.   /* Make a copy in writable memory.  */
  982.   dir_list = xmalloc (strlen (temp) + 1);
  983.   strcpy (dir_list, temp);
  984.  
  985.   *result = 0;
  986.  
  987.   /* Unfortunately, we can't look in the environment for the current
  988.      directory, because if we are running under a program (let's say
  989.      Emacs), the PWD variable might have been set by Emacs' parent
  990.      to the current directory at the time Emacs was invoked.  This
  991.      is not necessarily the same directory the user expects to be
  992.      in.  So, we must always call getcwd(3) or getwd(3), even though
  993.      they are slow and prone to hang in networked installations.  */
  994.   cwd = getcwd (NULL, MAXPATHLEN + 2);
  995.   if (cwd == NULL)
  996.     {
  997.       perror ("getcwd");
  998.       exit (errno);
  999.     }
  1000.  
  1001.   do
  1002.     {
  1003.       DIR *dir;
  1004.       directory_entry_type e;
  1005.       char dirname[MAXPATHLEN];
  1006.  
  1007.       next_component (dirname, &dir_list);
  1008.  
  1009.       /* All the `::'s should be gone by now, but we may as well make
  1010.          sure `chdir' doesn't crash.  */
  1011.       if (*dirname == 0) continue;
  1012.  
  1013.       /* By changing directories, we save a bunch of string
  1014.          concatenations (and make the pathnames the kernel looks up
  1015.          shorter).  */
  1016.       if (chdir (dirname) != 0) continue;
  1017.  
  1018.       dir = opendir (".");
  1019.       if (dir == NULL) continue;
  1020.  
  1021.       while ((e = readdir (dir)) != NULL)
  1022.         {
  1023.           if (is_dir (e->d_name) && strcmp (e->d_name, ".") != 0
  1024.               && strcmp (e->d_name, "..") != 0)
  1025.             {
  1026.               char *found = concat3 (dirname, dirsep, e->d_name);
  1027.  
  1028.               result = xrealloc (result, strlen (result) + strlen (found) + 2);
  1029.  
  1030.               len = strlen (result);
  1031.               if (len > 0)
  1032.                 {
  1033.                   result[len] = PATHSEP;
  1034.                   result[len + 1] = 0;
  1035.                 }
  1036.               strcat (result, found);
  1037.               free (found);
  1038.             }
  1039.         }
  1040.       closedir (dir);
  1041.  
  1042.       /* Change back to the current directory, in case the path
  1043.          contains relative directory names.  */
  1044.       if (chdir (cwd) != 0)
  1045.         {
  1046.           perror (cwd);
  1047.           exit (errno);
  1048.         }
  1049.     }
  1050.   while (*dir_list != 0);
  1051.  
  1052.   return result;
  1053. }
  1054. #endif /* SEARCH_SUBDIRECTORIES */
  1055.