home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / texmf / source / TeX / common / extra.c < prev    next >
C/C++ Source or Header  |  1994-11-12  |  22KB  |  981 lines

  1. /* External procedures for these programs.  */
  2.  
  3.  
  4. /* This includes <stdio.h> and "site.h".  */
  5. #include "extra.h"
  6.  
  7. #include "config.h"
  8.  
  9. #ifdef EVPATH
  10. #include "EVPaths.h"
  11. #endif
  12.  
  13.  
  14. #ifdef TeX
  15. extern integer namelength;
  16. #endif
  17.  
  18. extern unsigned char xord[], xchr[];
  19.  
  20. static char *concat (char *s1, char *s2);
  21. static char *string_copy (char *s);
  22. static char *expand_colon (char *dir_list, char *default_value);
  23. static void next_component (char name[], char **path);
  24.  
  25.  
  26. /*----------*/
  27.  
  28. /* Round R to the nearest whole number.  */
  29. #if !defined(atarist) && !defined(AMIGA)
  30. integer
  31. zround (r)
  32.   double r;
  33. {
  34.   return r >= 0.0 ? (r + 0.5) : (r - 0.5);
  35. }
  36. #endif
  37.  
  38.  
  39. /*----------*/
  40.  
  41. /* File operations.  */
  42.  
  43. #ifndef TeX
  44.  
  45. /* Open a file; don't return if any error occurs.  NAME is a Pascal
  46.    string, but is changed to a C string and not changed back.  */ 
  47.  
  48. FILE *
  49. checked_fopen (name, mode)
  50.   char *name;
  51.   char *mode;
  52. {
  53.   FILE *result;
  54.  
  55.   end_with_null (name + 1);
  56. #ifdef atarist
  57.   replace_slash(name+1);
  58. #endif  
  59.   result = fopen (name + 1, mode);
  60.   if (result != NULL)
  61.     return result;
  62.     
  63.   perror (name + 1);
  64.   exit (1);
  65.   /*NOTREACHED*/
  66. }
  67.  
  68. #endif
  69.  
  70.  
  71. #if 0        /* (br) not required */
  72.  
  73. /* Return true if we're at the end of FILE, else false.  This implements
  74.    Pascal's `eof' builtin.  */
  75.  
  76. boolean
  77. test_eof (file)
  78.   FILE *file;
  79. {
  80.   register int c;
  81.  
  82.   /* Maybe we're already at the end?  */
  83.   if (feof (file))
  84.     return true;
  85.  
  86.   if ((c = getc (file)) == EOF)
  87.     return true;
  88.  
  89.   /* Whoops, we weren't at the end.  Back up.  */
  90.   (void) ungetc (c, file);
  91.  
  92.   return false;
  93. }
  94.  
  95.  
  96. /* Return true on end-of-line in FILE or at the end of FILE, else false.  */
  97.  
  98. boolean
  99. eoln (file)
  100.   FILE *file;
  101. {
  102.   register int c;
  103.  
  104.   if (feof (file))
  105.     return true;
  106.   
  107.   c = getc (file);
  108.   
  109.   if (c != EOF)
  110.     (void) ungetc (c, file);
  111.     
  112.   return (boolean) (c == '\n' || c == EOF);
  113. }
  114.  
  115. #endif
  116.  
  117.  
  118. #ifndef TeX
  119. /* Print real number R in the Pascal format N:M on the file F.  */
  120.  
  121. void
  122. fprintreal (f, r, n, m)
  123.   FILE *f;
  124.   double r;
  125.   int n, m;
  126. {
  127.   char fmt[50];  /* Surely enough, since N and M won't be more than 25
  128.                     digits each!  */
  129.  
  130.   (void) sprintf (fmt, "%%%d.%dlf", n, m);
  131.   (void) fprintf (f, fmt, r);
  132. }
  133.  
  134.  
  135. /* Print S, a Pascal string, on the file F.  It starts at index 1 and is
  136.    terminated by a space.  */
  137.  
  138. static void
  139. fprint_pascal_string (s, f)
  140.   char *s;
  141.   FILE *f;
  142. {
  143.   s++;
  144.   while (*s != ' ') putc (*s++, f);
  145. }
  146.  
  147. /* Print S, a Pascal string, on stdout.  */
  148.  
  149. void
  150. printpascalstring (s)
  151.   char *s;
  152. {
  153.   fprint_pascal_string (s, stdout);
  154. }
  155.  
  156. /* Ditto, for stderr.  */
  157.  
  158. void
  159. errprintpascalstring (s)
  160.   char *s;
  161. {
  162.   fprint_pascal_string (s, stderr);
  163. }
  164.  
  165. /* Read an integer from the file F, reading past the subsequent end of
  166.    line.  */
  167.  
  168. integer
  169. inputint (f)
  170.   FILE *f;
  171. {
  172.   char buffer[50]; /* Long enough for anything reasonable.  */
  173.  
  174.   return
  175.     fgets (buffer, sizeof (buffer), f)
  176.     ? atoi (buffer)
  177.     : 0;
  178. }
  179.  
  180. /* Read three integers from stdin.  */
  181.  
  182. void
  183. zinput3ints (a,b,c)
  184.   integer *a, *b, *c;
  185. {
  186.   while (scanf ("%ld %ld %ld\n", a, b, c) != 3)
  187.     (void) fprintf (stderr, "Please enter three integers.\n");
  188. }
  189.  
  190.  
  191. /*----------*/
  192.  
  193. /* String operations.  */
  194.  
  195. /* Change the suffix of BASE (a Pascal string) to be SUFFIX (another
  196.    Pascal string).  We have to change them to C strings to do the work,
  197.    then convert them back to Pascal strings.  */
  198.  
  199. void
  200. makesuffix (base, suffix)
  201.   char *base;
  202.   char *suffix;
  203. {
  204.   char *last_dot, *last_slash;
  205.   make_c_string (&base);
  206.   
  207.   last_dot = rindex (base, '.');
  208.   last_slash = rindex (base, '/');
  209.   
  210.   if (last_dot == NULL || last_dot < last_slash) /* Add the suffix?  */
  211.     {
  212.       make_c_string (&suffix);
  213.       strcat (base, suffix);
  214.       make_pascal_string (&suffix);
  215.     }
  216.     
  217.   make_pascal_string (&base);
  218. }
  219. #endif    /* not TeX */
  220.  
  221.    
  222. /* Deal with C and Pascal strings.  */
  223.  
  224. /* for Atari ST & TOS we have to make sure, that all '/' are translated */
  225. #ifdef atarist
  226. void
  227. replace_slash(char *s)
  228. {
  229.   /* with UNIXMODE '/dev/X' is the same as 'X:', don't replace */
  230.   if( !strcmp(s, "/dev/") )
  231.     s += 5;
  232.  
  233.   while( *s != '\0' ) {
  234.     if( *s == '/' )
  235.       *s = '\\';
  236.     s++;
  237.   }
  238. }
  239.  
  240. /* for Atari ST & TOS we have to make sure, that all '\\' are translated */
  241. void
  242. replace_backslash(char *s)
  243. {
  244.   while( *s != '\0' ) {
  245.     if( *s == '\\' )
  246.       *s = '/';
  247.     s++;
  248.   }
  249. }
  250. #endif
  251.  
  252.  
  253. /* Replace the first space we come to with a null.  */
  254.  
  255. void
  256. end_with_null (char *s)
  257. {
  258. #ifdef TeX
  259.   *(s + namelength) = '\0';
  260. #endif
  261.  
  262. #if 0
  263.   for ( ; *s && *s != ' ' ; s++ )
  264. #ifdef NONASCII
  265.     *s = xchr[*s]
  266. #endif
  267.     ;
  268.   *s = 0;
  269. #endif
  270. }
  271.  
  272.  
  273.  
  274. /* Replace the first null we come to with a space.  */
  275.  
  276. void
  277. end_with_space (char *s)
  278. {
  279. #ifdef TeX
  280.   *(s + namelength) = ' ';
  281. #endif
  282.  
  283. #if 0
  284.   for ( ; *s != 0; s++)
  285. #ifdef NONASCII
  286.     *s = xord[*s]    /* xchr[*s]   BUG !*/
  287. #endif
  288.     ;
  289.   *s = ' ';
  290. #endif
  291. }
  292.  
  293.  
  294. static char *
  295. concat (char *s1, char *s2)
  296. {
  297.   char *r = xmalloc (strlen (s1) + strlen (s2) + 1);
  298.   strcpy (r, s1);
  299.   strcat (r, s2);
  300.   return r;
  301. }
  302.  
  303.  
  304. static char *
  305. string_copy (char *s)
  306. {
  307.   char *new_string = xmalloc (strlen (s) + 1);
  308.  
  309.   strcpy (new_string, s);
  310.  
  311.   return new_string;
  312. }
  313.  
  314.  
  315.  
  316. /* Memory operations: variants of malloc(3) and realloc(3) that just
  317.    give up the ghost when they fail.  */
  318.  
  319. #if !defined(atarist) && !defined(AMIGA)
  320. extern char *malloc (), *realloc ();
  321. #endif
  322.  
  323. char *
  324. xmalloc (size)
  325.   unsigned long size;
  326. {
  327.   char *mem = malloc (size);
  328.   
  329.   if (mem == NULL) {
  330.     fprintf (stderr, "! Cannot allocate %lu bytes.\n", size);
  331.     exit (10);
  332.   }
  333.   return mem;
  334. }
  335.  
  336.  
  337. char *
  338. xrealloc (ptr, size)
  339.   char *ptr;
  340.   unsigned long size;
  341. {
  342.   char *mem = realloc (ptr, size);
  343.   
  344.   if (mem == NULL) {
  345.     fprintf (stderr, "! Cannot reallocate %lu bytes at %x.\n", size, ptr);
  346.     exit (10);
  347.   }
  348.  
  349.   return mem;
  350. }
  351.  
  352.  
  353. /*----------*/
  354.  
  355. /* Path searching.  */
  356.  
  357. #ifdef TEXCONFIG
  358. #define NUMBER_OF_PATHS 12
  359. #else
  360. #define NUMBER_OF_PATHS 11
  361. #endif
  362.  
  363. static char *path[NUMBER_OF_PATHS];
  364. static char *env_var_names[NUMBER_OF_PATHS]
  365.   = { "BIBINPUTS",
  366.       "GFFONTS",
  367.       "MFBASES", "MFINPUTS", "MFPOOL",
  368.       "PKFONTS",
  369.       "TEXFORMATS", "TEXINPUTS", "TEXPOOL", "TEXFONTS", 
  370.       "VFFONTS"
  371. #ifdef TEXCONFIG
  372.     , "TEXCONFIG"
  373. #endif
  374.     };
  375.  
  376. #if defined(EVPATH)
  377. static struct EnvVarPath * evpath[NUMBER_OF_PATHS];
  378.  
  379. void _STI_5555_InitEVpath(void)
  380. {
  381.   int i;
  382.   for (i=0; i<NUMBER_OF_PATHS; i++) evpath[i] = NULL;
  383. }
  384. void _STD_5555_FreeEVpath(void)
  385. {
  386.   int i;
  387.   for (i=0; i<NUMBER_OF_PATHS; i++) {
  388.     if (evpath[i]) {
  389.       Free_EnvVarPath(evpath[i]);
  390.       evpath[i] = NULL;
  391.     }
  392.   }
  393. }
  394. #endif
  395.  
  396.  
  397. #if defined(atarist) || defined(AMIGA)
  398. int
  399. get_env_var_index(char *name)
  400. {  int i;
  401.  
  402.    for( i = 0; i < NUMBER_OF_PATHS; i++ )
  403. #ifdef AMIGA
  404.      if( !stricmp(name, env_var_names[i]) )
  405. #else
  406.      if( !strcmp(name, env_var_names[i]) )
  407. #endif
  408.     return(i);
  409.    return(-1);
  410. }
  411. #endif
  412.  
  413.  
  414. #define READ_ACCESS 4       /* Used in access(2) call.  */
  415.  
  416. /* What separates elements of the path variables.  */
  417. /* PATH_SEPS... Strings with path separating chars */
  418. /* PATH_DELIMITER... Char used when building paths in do_subdir... */
  419.  
  420. #if defined(MS_DOS) || defined(atarist)
  421. # define PATH_DELIMITER ';'
  422. # define PATH_SEPS    ";,"
  423. #else
  424. # ifdef AMIGA
  425. #  define PATH_DELIMITER ','
  426. #  define PATH_SEPS    ";,"
  427. # else    /* Unix */
  428. #  define PATH_DELIMITER ':'
  429. #  define PATH_SEPS    ":;,"
  430. # endif
  431. #endif
  432.  
  433. /* We will need some system include files to deal with directories, even
  434.    when SEARCH_SUBDIRECTORIES is undefined.  (We also make sure we don't
  435.    open a directory as an input file.  */
  436. #ifndef AMIGA
  437. #include <sys/types.h>
  438. #include <sys/stat.h>
  439. #endif
  440.  
  441. /* And if we're actually going to search subdirectorys, we need still
  442.    more include files.  */
  443. #ifdef SEARCH_SUBDIRECTORIES
  444.  
  445. #ifndef BSD
  446. #include <dirent.h>
  447. typedef struct dirent *directory_entry_type;
  448. #else /* BSD */
  449. #include <sys/dir.h>
  450. typedef struct direct *directory_entry_type;
  451. #endif /* BSD */
  452.  
  453. /* Declare the routine to get the current working directory.  */
  454.  
  455. #ifdef HAVE_GETWD
  456. extern char *getwd ();
  457. #define getcwd(b, len)  ((b) ? getwd (b) : getwd (xmalloc (len)))
  458. #else
  459. #ifdef ANSI
  460. extern char *getcwd (char *, int);
  461. #else
  462. extern char *getcwd ();
  463. #endif /* not ANSI */
  464. #endif /* not HAVE_GETWD */
  465.  
  466. extern int errno;
  467.  
  468. #endif /* SEARCH_SUBDIRECTORIES */
  469.  
  470.  
  471. /* Subroutines.  */
  472. /* static void next_component (); */
  473. extern int is_dir ();
  474.  
  475. /* Says whether NAME is ok to open for reading.  */
  476. #define READABLE_FILE(name) access (name, READ_ACCESS) == 0 && !is_dir (name)
  477.  
  478.  
  479. /* Replace a leading or trailing `:' (or `,', `;' ... )
  480.    in DIR_LIST with DEFAULT_VALUE. 
  481.    The result is always dynamically allocated.  */
  482.  
  483. static char *
  484. expand_colon (char *dir_list, char *default_value)
  485. {
  486.   char *expansion = xmalloc (strlen (dir_list) + 1);
  487.   strcpy (expansion, dir_list);
  488.  
  489.   if ( index(PATH_SEPS, *expansion) != NULL ) {
  490.       char *temp = expansion;
  491.       expansion = concat (default_value, expansion);
  492.       free (temp);
  493.   }
  494.   if ( index(PATH_SEPS, *(expansion + strlen (expansion) - 1)) != NULL ) {
  495.       char *temp = expansion;
  496.       expansion = concat (expansion, default_value);
  497.       free (temp);
  498.   }
  499.   
  500.   return expansion;
  501. }
  502.  
  503.  
  504. /* This routine initializes `path[PATH_INDEX]'.  If the environment
  505.    variable `env_var_names[PATH_INDEX]' is not set, we simply use 
  506.    DEFAULT_VALUE.  Otherwise, we use the value of the environment
  507.    variable, and then replace a leading or trailing colon with
  508.    DEFAULT_VALUE.  The result is always dynamically allocated.
  509.  
  510.    For example, if DEFAULT_VALUE is `foo', and the environment variable
  511.    value is `:bar:baz:', the final result will be `foo:bar:baz:foo'.
  512.    (Of course, it is pointless to have more than one extra `:' in
  513.    practice.)  */
  514.    
  515. /* static */    /* (br) deleted for TEXCONFIG */
  516. void
  517. do_path (unsigned path_index, char *default_value)
  518. {
  519.   char *temp = NULL;
  520.  
  521.   if( path_index > 0x7f )    /* (br) added to force setting default */
  522.     path_index &= 0x7f;
  523.  
  524.   temp = getenv (env_var_names[path_index]);
  525.  
  526.   if( path[path_index] == NULL ) {    /* (br) added for ST */
  527.     path[path_index] = (temp == NULL)
  528.                      ? string_copy (default_value)
  529.                      : expand_colon (temp, default_value); 
  530.   }
  531.  
  532. #if 0 /* EVPATH */
  533.   /* weg mit diesem Block; wird erst in testreadacc() gemacht! */
  534.   evpath[path_index] = Alloc_EnvVarPath(env_var_names[path_index], EVPBUF);
  535.   Init_EnvVarPath(evpath[path_index], path[path_index], ENVPATH_DEFSTR);
  536. #endif
  537.  
  538. #if 0
  539.   printf("Debug: do_path(%s,%s) =>%s<\n",
  540.     env_var_names[path_index], default_value, path[path_index]);
  541. #endif
  542. }
  543.  
  544.  
  545. #ifdef SEARCH_SUBDIRECTORIES
  546. static char *
  547. concat3 (s1, s2, s3)
  548.   char *s1, *s2, *s3;
  549. {
  550.   char *r = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
  551.   strcpy (r, s1);
  552.   strcat (r, s2);
  553.   strcat (r, s3);
  554.   return r;
  555. }
  556.  
  557.  
  558. /* DIR_LIST is the default list of directories (colon-separated) to
  559.    search.  If the environment variable
  560.    "`env_var_names[PATH_INDEX]'_SUBDIR" exists, we use that instead.  We
  561.    want to add all the subdirectories directly below each of the
  562.    directories in the path.
  563.      
  564.    We return the list of directories found.
  565.    
  566.    By doing this all at the beginning of the program, we make the
  567.    programs that look for only one file somewhat less efficient but this
  568.    is more efficient when we look up many files using the same path.  */
  569.  
  570. static char *
  571. do_subdir_path (path_index, dir_list)
  572.   unsigned path_index;
  573.   char *dir_list;
  574. {
  575.   char *cwd;
  576.   unsigned len;
  577.   char *result = xmalloc (1);
  578.   char *env_var = concat (env_var_names[path_index], "_SUBDIR");
  579.   char *temp = getenv (env_var);
  580.  
  581.   free (env_var);
  582.   
  583.   if (temp == NULL)
  584.     {
  585.       temp = dir_list;
  586.       /* Make a copy in writable memory.  */
  587.       dir_list = xmalloc (strlen (temp) + 1);
  588.       strcpy (dir_list, temp);
  589.     }
  590.   else
  591.     dir_list = expand_colon (temp, dir_list);
  592.  
  593.   *result = 0;
  594.  
  595.   /* Unfortunately, we can't look in the environment for the current
  596.      directory, because if we are running under a program (let's say
  597.      Emacs), the PWD variable might have been set by Emacs' parent
  598.      to the current directory at the time Emacs was invoked.  This
  599.      is not necessarily the same directory the user expects to be
  600.      in.  So, we must always call getcwd(3) or getwd(3), even though
  601.      they are slow and prone to hang in networked installations.  */
  602.   cwd = getcwd (NULL, FILENAMESIZE + 2);
  603.   if (cwd == NULL)
  604.     {
  605.       perror ("getcwd");
  606.       exit (errno);
  607.     }
  608.  
  609.   do
  610.     {
  611.       DIR *dir;
  612.       directory_entry_type e;
  613.       char dirname[FILENAMESIZE];
  614.  
  615.       next_component (dirname, &dir_list);
  616.  
  617.       /* All the `::'s should be gone by now, but we may as well make
  618.          sure `chdir' doesn't crash.  */
  619.       if (*dirname == 0) continue;
  620.  
  621.       /* By changing directories, we save a bunch of string
  622.          concatenations (and make the pathnames the kernel looks up
  623.          shorter).  */
  624.       if (chdir (dirname) != 0) continue;
  625.  
  626.       dir = opendir (".");
  627.       if (dir == NULL) continue;
  628.  
  629.       while ((e = readdir (dir)) != NULL)
  630.         {
  631.           if (is_dir (e->d_name) && strcmp (e->d_name, ".") != 0
  632.               && strcmp (e->d_name, "..") != 0)
  633.             {
  634.               char *found = concat3 (dirname, "/", e->d_name);
  635.  
  636.               result = xrealloc (result, strlen (result) + strlen (found) + 2);
  637.  
  638.               len = strlen (result);
  639.               if (len > 0)
  640.                 {
  641.                   result[len] = PATH_DELIMITER;
  642.                   result[len + 1] = 0;
  643.                 }
  644.               strcat (result, found);
  645.               free (found);
  646.             }
  647.         }
  648.       closedir (dir);
  649.  
  650.       /* Change back to the current directory, in case the path
  651.          contains relative directory names.  */
  652.       if (chdir (cwd) != 0)
  653.         {
  654.           perror (cwd);
  655.           exit (errno);
  656.         }
  657.     }
  658.   while (*dir_list != 0);
  659.   
  660.   len = strlen (path[path_index]);
  661.   path[path_index] = xrealloc (path[path_index], len + strlen (result) + 2);
  662.   *(path[path_index] + len) = PATH_DELIMITER;
  663.   *(path[path_index] + len + 1) = 0;
  664.   strcat (path[path_index], result);
  665.   
  666.   return result;
  667. }
  668. #endif /* SEARCH_SUBDIRECTORIES */
  669.  
  670.  
  671. /* This sets up the paths, by either copying from an environment variable
  672.    or using the default path, which is defined as a preprocessor symbol
  673.    (with the same name as the environment variable) in `site.h'.  The
  674.    parameter PATH_BITS is a logical or of the paths we need to set.  */
  675.  
  676. extern void
  677. setpaths (int path_bits)
  678. {
  679. #if defined(SEARCH_SUBDIRECTORIES) && defined(TEXFONTS_SUBDIR)
  680.   char *font_subdirs;
  681. #endif
  682.  
  683.   /* We must assign to the TFM file path before doing any of the other
  684.      font paths, since it is used as a default.  */
  685.   if (path_bits
  686.       & (TFMFILEPATHBIT | GFFILEPATHBIT | PKFILEPATHBIT | VFFILEPATHBIT))
  687.     {
  688.       do_path (TFMFILEPATH, TEXFONTS);
  689. #if defined(SEARCH_SUBDIRECTORIES) && defined(TEXFONTS_SUBDIR)
  690.       font_subdirs = do_subdir_path (TFMFILEPATH, TEXFONTS_SUBDIR);
  691. #endif
  692.     }
  693.  
  694. #ifndef TeX        /* (br) added */
  695.   if (path_bits & BIBINPUTPATHBIT)
  696.     do_path (BIBINPUTPATH, BIBINPUTS);
  697.  
  698.   if (path_bits & GFFILEPATHBIT) {
  699.       do_path (GFFILEPATH, path[TFMFILEPATH]);
  700. #if defined(SEARCH_SUBDIRECTORIES) && defined(TEXFONTS_SUBDIR)
  701.       path[GFFILEPATH] = concat3 (path[GFFILEPATH], ":", font_subdirs);
  702. #endif
  703.   }
  704.  
  705.   if (path_bits & MFBASEPATHBIT)
  706.     do_path (MFBASEPATH, MFBASES);
  707.  
  708.   if (path_bits & MFINPUTPATHBIT) {
  709.       do_path (MFINPUTPATH, MFINPUTS);
  710. #if defined(SEARCH_SUBDIRECTORIES) && defined(MFINPUTS_SUBDIR)
  711.       (void) do_subdir_path (MFINPUTPATH, MFINPUTS_SUBDIR);
  712. #endif
  713.   }
  714.  
  715.   if (path_bits & MFPOOLPATHBIT)
  716.     do_path (MFPOOLPATH, MFPOOL);
  717.  
  718.   if (path_bits & PKFILEPATHBIT) {
  719.       do_path (PKFILEPATH, path[TFMFILEPATH]);
  720. #if defined(SEARCH_SUBDIRECTORIES) && defined(TEXFONTS_SUBDIR)
  721.       path[PKFILEPATH] = concat3 (path[PKFILEPATH], ":", font_subdirs);
  722. #endif
  723.   }
  724. #endif    /* not TeX */
  725.  
  726.   if (path_bits & TEXFORMATPATHBIT)
  727.     do_path (TEXFORMATPATH, TEXFORMATS);
  728.  
  729.   if (path_bits & TEXINPUTPATHBIT) {
  730.       do_path (TEXINPUTPATH, TEXINPUTS);
  731. #if defined(SEARCH_SUBDIRECTORIES) && defined(TEXINPUTS_SUBDIR)
  732.       (void) do_subdir_path (TEXINPUTPATH, TEXINPUTS_SUBDIR);
  733. #endif
  734.   }
  735.  
  736.   if (path_bits & TEXPOOLPATHBIT)
  737.     do_path (TEXPOOLPATH, TEXPOOL);
  738.  
  739. #ifndef TeX        /* (br) added */
  740.   /* Some sites want to have a system default for VFFONTS, and others
  741.      don't.  */
  742.   if (path_bits & VFFILEPATHBIT) {
  743. #ifdef VFFONTS
  744.       do_path (VFFILEPATH, VFFONTS);
  745. #else
  746.       do_path (VFFILEPATH, path[TFMFILEPATH]);
  747. #endif
  748. #if defined(SEARCH_SUBDIRECTORIES) && defined(TEXFONTS_SUBDIR)
  749.       path[VFFILEPATH] = concat3 (path[VFFILEPATH], ":", font_subdirs);
  750. #endif
  751.   }
  752. #endif    /* not TeX */
  753.  
  754. #if 0        /* not used, do_path is called directly */
  755.   if (path_bits & TEXCONFIGPATHBIT)
  756.     do_path (TEXCONFIGPATH, TEXCONFIG);
  757. #endif
  758. }
  759.  
  760.  
  761. /* Look for NAME, a Pascal string, in a colon-separated list of
  762.    directories.  The path to use is given (indirectly) by PATH_INDEX.
  763.    If the search is successful, leave the full pathname in NAME (which
  764.    therefore must have enough room for such a pathname), padded with
  765.    blanks.  Otherwise, or if NAME is an absolute or relative pathname,
  766.    just leave it alone.  */
  767.  
  768. #ifdef AMIGA
  769.  
  770. # if defined(BIG)
  771. #  define NRBUFFERSFMT    80
  772. # else
  773. #  define NRBUFFERSFMT    50
  774. # endif
  775. # define  NRBUFFERSTEX    2
  776.  
  777.  
  778. FILE *
  779. testreadaccess (name, path_index)
  780.   char *name;
  781.   int path_index;
  782. {
  783.   FILE *okfp = NULL;
  784.  
  785. #ifdef EVPATH
  786.   char buf[FILENAMESIZE];
  787.  
  788.   end_with_null(name);    /* convert from internal to external charset */
  789.  
  790.   if (!evpath[path_index]) {
  791.     evpath[path_index] = Alloc_EnvVarPath(env_var_names[path_index], ((path_index == TEXINPUTPATH) ? 8192 : 1024));
  792.     Init_EnvVarPath(evpath[path_index], path[path_index], ENVPATH_DEFSTR);
  793. #ifdef EVPATH_DEBUG
  794.     { int i = 0;
  795.  
  796.       printf("The environment variable `%s' has length %ld\n", env_var_names[path_index], GetVarLength(env_var_names[path_index]));
  797.       while (evpath[path_index]->storage.strings[i])
  798.         printf("%ld -> `%s'\n", i, evpath[path_index]->storage.strings[i++]);
  799.     }
  800. #endif
  801.   }
  802.  
  803.   if (!evpath[path_index]) return NULL;
  804.  
  805.   if (EVP_FileSearch(name, evpath[path_index], buf, sizeof(buf)-1)) {
  806.     if (okfp = fopen(buf, "r")) {
  807.       strcpy(name, buf);
  808.       if (path_index == TEXFORMATPATH) {
  809.         setvbuf(okfp, xmalloc(NRBUFFERSFMT*512), _IOFBF, NRBUFFERSFMT*512);
  810.       }
  811.       if (path_index == TEXINPUTPATH) {
  812.         setvbuf(okfp, xmalloc(NRBUFFERSTEX*512), _IOFBF, NRBUFFERSTEX*512);
  813.       }
  814.     }
  815.   }
  816.  
  817. #else
  818.   register char *ptr;
  819.   char Path[FILENAMESIZE];
  820.   char potential[FILENAMESIZE];
  821.   short len;
  822.  
  823.   end_with_null(name);    /* convert from internal to external charset */
  824.  
  825.   strncpy(Path, path[path_index], FILENAMESIZE-2); /* -2 for add. '/' */
  826.   Path[FILENAMESIZE-2] = '\0';
  827.  
  828.   ptr = strtok(Path, ",;");
  829.   do {
  830.     ptr = strcpy(potential, ptr);
  831.     len = strlen(ptr);
  832.     if (ptr[len-1] != ':' && ptr[len-1] != '/') {
  833.       ptr[len] = '/';
  834.       ptr[len+1] = '\0';
  835.     }
  836.     if (strcmp(ptr, "./") == 0) *ptr = '\0';    /* ./ is actual directory */
  837.     if (strlen(ptr) + strlen(name) + 1 < FILENAMESIZE) {
  838.       strcat(ptr, name);
  839.       okfp = fopen(ptr, "r");
  840.     } else
  841.       okfp = NULL;    /* oder besser: Fehlermeldung o.ae. */
  842.   } while (okfp == NULL && (ptr = strtok(NULL, ",;")) != NULL);
  843.  
  844.   if (okfp != NULL) {
  845.     strcpy (name, potential);    /* If we found it, leave the answer in NAME.  */
  846.     if (path_index == TEXFORMATPATH) {
  847.       char *buffer = xmalloc(NRBUFFERSFMT*512);
  848.       setvbuf(okfp, buffer, _IOFBF, NRBUFFERSFMT*512);
  849.       /* printf("set buffer of file \"%s\" to %d\n", name, NRBUFFERSFMT*512); */
  850.     }
  851.     if (path_index == TEXINPUTPATH) {
  852.       char *buffer = xmalloc(NRBUFFERSTEX*512);
  853.       setvbuf(okfp, buffer, _IOFBF, NRBUFFERSTEX*512);
  854.       /* printf("set buffer of file \"%s\" to %d\n", name, NRBUFFERSTEX*512); */
  855.     }
  856.   }
  857. #endif
  858.  
  859.   namelength = strlen(name);  /* WICHTIG !! */
  860.  
  861.   end_with_space(name);  /* convert from external to internal charset */
  862.   
  863.   return okfp;
  864. }
  865.  
  866. #else
  867.  
  868. FILE *
  869. testreadaccess (name, path_index)
  870.   char *name;
  871.   int path_index;
  872. {
  873.   char potential[FILENAMESIZE];
  874.   FILE *okfp = NULL;
  875.   char *the_path = path[path_index];
  876.   /* char *saved_path = the_path; */ /* not used */
  877.  
  878.   end_with_null(name);    /* convert from internal to external charset */
  879.  
  880.   if ( *name == '/'
  881. #ifdef atarist
  882.     || ((*name & 0x40) == 0x40 && *(name + 1) == ':')
  883. #endif
  884.     || (*name == '.' && *(name + 1) == '/')
  885.     || (*name == '.' && *(name + 1) == '.' && *(name + 2) == '/')
  886.         ) {
  887.     /* if( READABLE_FILE (name) ) */
  888. #ifdef atarist
  889.     replace_slash(name);  
  890. #endif
  891.     okfp = fopen (name, "r");
  892. #ifdef atarist
  893.     replace_backslash(name);  
  894. #endif
  895.   } else {
  896.     do {
  897.     next_component (potential, &the_path);
  898.  
  899.     if ( (*potential != 0)
  900.          && (strlen(potential) + strlen(name) + 2 < FILENAMESIZE) ) {
  901.        strcat (potential, "/");
  902.        strcat (potential, name);
  903.  
  904.        /* if( READABLE_FILE (potential) ) */
  905. #ifdef atarist
  906.        replace_slash(potential);
  907. #endif
  908.        okfp = fopen (potential, "r");
  909.     }
  910. #if 0
  911.   printf("DEBUG: testreadaccess(%s)  potential >%s< ==> %d\n", 
  912.     name, potential, okfp);
  913. #endif
  914.      } while (okfp == NULL && *the_path != 0);
  915.  
  916.      /* If we found it, leave the answer in NAME.  */
  917.      if (okfp != NULL) {
  918. #ifdef atarist
  919.     replace_backslash(potential);
  920. #endif
  921.         strcpy (name, potential);
  922.      }
  923.   }
  924.  
  925. #if 0
  926.   printf("DEBUG: testreadaccess() ==>%s<\n", name);
  927. #endif
  928.  
  929.   namelength = strlen(name);  /* WICHTIG !! */
  930.  
  931.   end_with_space(name);  /* convert from external to internal charset */
  932.  
  933.   return okfp;
  934. }
  935.  
  936.  
  937. #endif /* AMIGA */
  938.  
  939.  
  940. /* Return, in NAME, the next component of PATH, i.e., the characters up
  941.    to the next PATH_DELIMITER.  */
  942.    
  943. static void
  944. next_component (char name[], char **path)
  945. {
  946.   unsigned count = 0;
  947.   
  948.   while (**path != 0 && index(PATH_SEPS, **path) == NULL) {
  949.       name[count++] = **path;
  950.       (*path)++; /* Move further along, even between calls.  */
  951.   }
  952.   
  953.   name[count] = 0;
  954.   if ( index(PATH_SEPS, **path) != NULL )
  955.     (*path)++; /* Move past the delimiter.  */
  956. }
  957.  
  958.  
  959. #ifdef SEARCH_SUBDIRECTORIES
  960.  
  961. #error File was changed a lot. Please check, if this works correct.
  962.  
  963. #if !defined(S_ISDIR)
  964. #define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
  965. #endif
  966.  
  967. /* Return true if FN is a directory or a symlink to a directory,
  968.    false if not. */
  969.  
  970. int
  971. is_dir (fn)
  972.   char *fn;
  973. {
  974.   struct stat stats;
  975.  
  976.   return stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode);
  977. }
  978. #endif
  979.  
  980. /* -- end -- */
  981.