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