OSDN Git Service

get rid of tex.pool.
[putex/putex.git] / src / texsourc / openinou.c
1 /* Copyright 1992 Karl Berry
2    Copyright 2007 TeX Users Group
3    Copyright 2014 Clerk Ma
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301 USA.  */
19
20 #ifdef _WINDOWS
21   #define NOCOMM
22   #define NOSOUND
23   #define NODRIVERS
24   #define STRICT
25   #pragma warning(disable:4115) // kill rpcasync.h complaint
26   #include <windows.h>
27   #define MYLIBAPI __declspec(dllexport)
28 #endif
29
30 #include "texwin.h"
31
32 #pragma warning(disable:4996)
33 #pragma warning(disable:4131) // old style declarator
34 #pragma warning(disable:4135) // conversion between different integral types 
35 #pragma warning(disable:4127) // conditional expression is constant
36
37 #include <setjmp.h>
38
39 #include <direct.h>           /* for _getcwd() */
40
41 #define EXTERN extern
42
43 #include "texd.h"
44
45 #define PATH_SEP        '/'
46 #define PATH_SEP_STRING "/"
47
48 /* openinout.c: open input and output files.  These routines used by
49    TeX, Metafont, and BibTeX.  */
50
51 /* #include <sys\stat.h> */       /* debugging 94/Mar/2 */
52 /* #include <sys\types.h> */      /* debugging 94/Mar/2 */
53 /* #include <conio.h> */        /* for getch */
54
55 // #include "config.h"
56 // #include "c-namemx.h"
57 // #include "c-pathch.h"
58
59 #define BUILDNAMEDIRECT         /* avoid malloc for string concat */
60
61 bool test_read_access (unsigned char *, int);   /* in ourpaths.c - bkph */
62 /* bool test_read_access (char *, int, int); */ /* in ourpaths.c - bkph */
63
64 extern char *unixify (char *);      /* in pathsrch.c bkph */
65
66 extern void try_and_open (char *);    /* in local.c bkph */
67
68 extern int shorten_file_name;       /* in local.c bkph */
69
70 #ifdef FUNNY_CORE_DUMP
71 /* This is defined in ./texmf.c.  */
72 extern void funny_core_dump();
73 #endif /* FUNNY_CORE_DUMP */
74
75 #ifdef MSDOS
76
77 #ifdef BUILDNAMEDIRECT
78 /* kpathsea/concat.c */
79 /* kpathsea/concat3.c */
80 /* similar to concat, but AVOIDS using malloc, pass in place to put result */
81 char *xconcat (char *buffer, char *s1, char *s2)
82 {
83   int n1 = strlen(s1);
84   int n2 = strlen(s2);
85   if (buffer == s2)
86   {     /* treat special case of overlap */
87     memmove (buffer + n1, buffer, n2 + 1); /* trailing null ! */
88     strncpy (buffer, s1, n1);
89   }
90   else
91   {
92     strcpy(buffer, s1);
93     strcat(buffer + n1, s2);
94   }
95   return buffer;
96 }
97 /* similar to concat3, but avoids using malloc, pass in place to put result */
98 char *xconcat3 (char *buffer, char *s1, char *s2, char *s3)
99 {
100   int n1 = strlen(s1);
101   int n2 = strlen(s2);
102   int n3 = strlen(s3);
103   if (buffer == s3)
104   {     /* treat special case of overlap */
105     memmove (buffer + n1 + n2, buffer, n3 + 1); /* trailing null ! */
106     strncpy (buffer, s1, n1);
107     strncpy (buffer + n1, s2, n2);
108   }
109   else
110   {
111     strcpy(buffer, s1);
112     strcat(buffer + n1, s2);
113     strcat(buffer + n1 + n2, s3);
114   }
115   return buffer;
116 }
117 #endif /* end of BUILDNAMEDIRECT  */
118
119 #endif  /* end of ifdef MSDOS ??? */
120
121 #ifdef MSDOS
122 /* separated out 1996/Jan/20 to make easier to read */
123 /* assumes path does not end in PATH_SEP */
124 void patch_in_path (unsigned char *buffer, unsigned char *name, unsigned char *path)
125 {
126 #ifdef BUILDNAMEDIRECT
127   if (*path == '\0')
128     strcpy((char *) buffer, (char *) name);
129   else
130     xconcat3((char *) buffer, (char *) path, PATH_SEP_STRING, (char *) name);
131 #else
132   string temp_name;
133   temp_name = concat3 (path, PATH_SEP_STRING, name);
134   strcpy (buffer, temp_name);
135   free (temp_name);
136 #endif
137 }
138 int qualified (unsigned char * name)
139 {
140   if (strchr((char *) name, PATH_SEP) != NULL ||
141       strchr((char *) name, '\\') != NULL ||
142       strchr((char *) name, ':') != NULL)
143     return 1;
144   else
145     return 0;
146 }
147 /* patch path if (i) path not empty (ii) name not qualified (iii) ext match */
148 int prepend_path_if (unsigned char *buffer, unsigned char *name, char *ext, unsigned char *path)
149 {
150   if (path == NULL)
151     return 0;
152   if (*path == '\0')
153     return 0;
154   if (qualified(name))
155     return 0;
156   if (strstr((char *)name, ext) == NULL)
157     return 0;
158   patch_in_path(buffer, name, path);
159   return 1;
160 }
161 #endif      /* end of MSDOS */
162
163 /*  Following works on null-terminated strings */
164
165 /* void check_short_name(void) { */       /* 1995/Feb/20 */
166 void check_short_name (unsigned char *s)
167 {         /* 1995/Sep/26 */
168   unsigned char *star, *sdot;
169   int n;
170
171 /*  if ((star = strrchr(name_of_file+1, '\\')) != NULL) star++;
172   else if ((star = strrchr(name_of_file+1, '/')) != NULL) star++;
173   else if ((star = strchr(name_of_file+1, ':')) != NULL) star++;
174   else star = name_of_file+1; */        /* 1995/Sep/26 */
175   if ((star = (unsigned char *) strrchr((char *) s, '\\')) != NULL)
176     star++;
177   else if ((star = (unsigned char *) strrchr((char *) s, '/')) != NULL)
178     star++;
179   else if ((star = (unsigned char *) strchr((char *) s, ':')) != NULL)
180     star++;
181   else
182     star = s;
183   if ((sdot = (unsigned char *) strchr((char *) star, '.')) != NULL)
184     n = sdot - star;
185   else
186     n = strlen((char *) star);
187   if (n > 8)
188     strcpy((char *) star + 8, (char *) star + n);
189   if ((sdot = (unsigned char *) strchr((char *) star, '.')) != NULL)
190   {
191     star = sdot + 1;
192     n = strlen((char *) star);
193     if (n > 3)
194       *(star + 3) = '\0';
195   }
196 }
197
198 /* Following works on both null-terminated names */
199 /* reconvert 254 to '~' in file name 95/Sep/26 */
200 /* reconvert 255 to ' ' in file name 95/Sep/26 */
201 /* we do this in tex3.c start_input() -> scan_file_name() now 95/Sep/26 */
202
203 void retwiddle (unsigned char *s)
204 { /* assumes null terminated - 97/June/5 */
205 /*  while (*s != '\0' && *s != ' ') { */
206   while (*s != '\0')
207   {
208     if (*s == (unsigned char) pseudo_tilde)
209       *s = '~';
210     else if (*s == (unsigned char) pseudo_space)
211       *s = ' ';
212     s++;
213   }
214 }
215
216 /* #endif */ /* ??? */
217
218 /* Open an input file F, using the path PATHSPEC and passing
219    FOPEN_MODE to fopen.  The filename is in `name_of_file', as a Pascal
220    string. We return whether or not the open succeeded.  If it did, we
221    also set `name_length' to the length of the full pathname that we
222    opened.  */
223 /* in lib/openclose.c */
224 bool open_input (FILE **f, path_constant_type path_index, char *fopen_mode)
225 {
226   bool openable = false;
227
228 #if defined (FUNNY_CORE_DUMP) && !defined (BibTeX)
229 /*  This only applies if a preloaded TeX (or Metafont) is being made;
230   it allows for automatic creation of the core dump (typing ^\
231   requires manual intervention).  */
232   if (path_index == TEXINPUTPATH &&
233       strncmp (name_of_file + 1, "HackyInputFileNameForCoreDump.tex", 33) == 0)
234     funny_core_dump();
235 #endif /* FUNNY_CORE_DUMP and not BibTeX */
236
237 #ifdef MSDOS
238   if (return_flag)
239   {
240     if (strcmp(fopen_mode, "r") == 0)
241       fopen_mode = "rb";    /* so can catch `return' bkph */
242   }
243 #endif /* MSDOS */
244
245   name_of_file[name_length + 1] = '\0'; /* null terminate */
246
247 /* reinsert '~' and ' ' in file names -  95/June/5 */
248 /* done late to prevent problems with  null_terminate / space_terminate */  
249   if (pseudo_tilde != 0 || pseudo_space != 0)
250     retwiddle(name_of_file + 1);
251
252 #ifdef MSDOS
253 /* 8 + 3 file names on Windows NT 95/Feb/20 */
254   if (shorten_file_name)
255   {
256     check_short_name(name_of_file + 1);           /* 95/Sep/26 */
257 /*    space_terminate (name_of_file + 1); */
258   }
259 #endif  /* MSDOS */
260
261 #ifdef BibTeX
262   if (path_index == NO_FILE_PATH)
263   {
264     unsigned temp_length;
265
266 /*      null_terminate (name_of_file + 1); */
267 /*  if share_flag is non-zero and we are opening for reading use fsopen */
268 /*  but we can assume here that we are opening for *input* */
269 /*      *f = fopen (name_of_file + 1, fopen_mode); */
270     if (share_flag == 0)
271       *f = fopen (name_of_file + 1, fopen_mode);
272     else
273       *f = _fsopen (name_of_file + 1, fopen_mode, share_flag);
274     temp_length = strlen (name_of_file + 1);
275 /*      space_terminate (name_of_file + 1); */
276
277     if (*f != NULL)
278     {
279       name_length = temp_length;
280       openable = true;
281     }
282   }
283
284   else
285 #endif /* BibTeX */
286   
287   if (open_trace_flag)
288   {
289     sprintf(log_line, " Open `%s' for input ", name_of_file + 1); /* Pascal */
290     show_line(log_line, 0);
291   }
292
293   if (test_read_access(name_of_file + 1, path_index))
294   {
295 /*  if (test_read_access(name_of_file, name_length, path_index)) */
296
297 /*    We can assume `name_of_file' is openable, */
298 /*    since `test_read_access' just returned true.  */
299 /*    *f = xfopen_pas (name_of_file, fopen_mode); */
300     *f = xfopen((char *) name_of_file + 1, fopen_mode);
301
302 //    should we check *f == NULL ??? (should be OK because of test_read_access)
303
304 /*    If we found the file in the current directory, don't leave the
305         `./' at the beginning of `name_of_file', since it looks dumb when
306         TeX says `(./foo.tex ...)', and analogously for Metafont.  */
307 #ifdef MSDOS
308     if (name_of_file[1] == '.' &&         /* 1994/Mar/1 */
309       (name_of_file[2] == PATH_SEP || name_of_file[2] == '\\'))
310 #else
311     if (name_of_file[1] == '.' && name_of_file[2] == PATH_SEP) 
312 #endif
313     {
314       unsigned i = 1;
315 /*        while (name_of_file[i + 2] != ' ') */
316       while (name_of_file[i + 2] != '\0')
317       {
318         name_of_file[i] = name_of_file[i + 2];
319         i++;
320       }
321 /*      name_of_file[i] = ' '; */
322       name_of_file[i] = '\0';
323       name_length = i - 1;
324     }
325     else
326 /*      name_length = strchr(name_of_file + 1, ' ') - (name_of_file + 1); */
327       name_length = strlen((char *) name_of_file + 1);
328       
329 #ifdef TeX
330 /*    If we just opened a TFM file, we have to read the first byte,
331         since TeX wants to look at it.  What a kludge.  */
332     if (path_index == TFMFILEPATH)
333     { /* See comments in ctex.ch for why we need this.  */
334 /*          extern integer tfm_temp; */ /* see texd.h for definition */
335       tfm_temp = getc (*f);
336     }
337 #endif /* TeX */  
338
339 #ifdef MSDOS
340 /*    code added 94/June/21 to show 'fmt' file opening in log */
341     if (strstr((char *) name_of_file + 1, ".fmt") != NULL)
342     {
343       if (format_file == NULL)
344       {
345         format_file = xstrdup((char *) name_of_file + 1);
346       }
347     } /* remember full format file name with path */
348     else if (strstr((char *)name_of_file+1, ".poo") != NULL)
349     {
350       if (string_file == NULL)
351       {
352         string_file = xstrdup((char *) name_of_file + 1);
353       }
354     } /* remember full pool file name with path */
355     else if (strstr((char *)name_of_file+1, ".tfm") != NULL)
356     {
357       if (show_tfm_flag && log_opened)
358       {
359 #ifdef WRAPLINES
360         int old_setting = selector;
361         char *s = name_of_file + 1;
362         selector = log_only;
363         print_char(' ');
364         print_char('(');
365         while (*s != '\0')
366           print_char (*s++);
367         print_char(')');
368         selector = old_setting;
369 #else
370         int n; 
371         n = strlen((char *) name_of_file + 1);
372         if (file_offset + n > max_print_line)
373         {
374           putc('\n', log_file);
375           file_offset = 0;
376         } /* somewhat risky ? */
377         else
378           putc(' ', log_file);
379         fprintf(log_file, "(%s)", name_of_file + 1);
380         file_offset += n+3;
381 /*        space_terminate (name_of_file + 1);  */
382 #endif  /*  end of WRAPLINES */
383       }
384     }
385 /*    code added 98/Sep/29 to catch first file input */
386 /*    is there a problem if this file bombs ? */
387     else if (source_direct == NULL) /* 98/Sep/29 */
388     {
389       char *s;
390       source_direct = xstrdup((char *) name_of_file + 1);
391       if (trace_flag)
392       {
393         sprintf(log_line, "Methinks the source %s is `%s'\n", "file", source_direct);
394         show_line(log_line, 0);
395       }
396
397       if ((s = strrchr(source_direct, '/')) == NULL)
398         *source_direct='\0';
399       else
400         *(s+1) = '\0';
401
402       if (trace_flag)
403       {
404         sprintf(log_line, "Methinks the source %s is `%s'\n", "directory", source_direct);
405         show_line(log_line, 0);
406       }
407     }
408 #endif  /* end of MSDOS */
409     openable = true;
410   }
411 /*  space_terminate (name_of_file + 1); */
412   {
413     unsigned temp_length = strlen((char *) name_of_file + 1);
414     name_of_file[temp_length + 1] = ' ';  /* space terminate */
415 /*    set up name_length ??? */
416   }
417   return openable;
418 }
419
420 /* Call the external program PROGRAM, passing it `name_of_file'.  */
421 /* This nonsense probably only works for Unix anyway. bkph */
422 /* For one thing, MakeTeXTFM etc is more than 8 characters ! */
423
424 #ifdef MSDOS
425   #define NO_MAKETEX
426 #endif
427
428 /* the string program is unreferenced in DOS NO_MAKETEX */
429
430 static bool
431 make_tex_file (string program)
432 {
433 #ifdef NO_MAKETEX
434   return 0;
435 #else
436   char cmd[NAME_MAX + 1 + PATH_MAX + 1];
437   unsigned cmd_len;
438   int ret;
439   unsigned i = 1; /* For copying from `name_of_file'.  */
440
441   /* Wrap another sh around the invocation of the MakeTeX program, so we
442      can avoid `sh: MakeTeXTFM: not found' errors confusing the user.
443      We don't use fork/exec ourselves, since we'd have to call sh anyway
444      to interpret the script.  */
445 #ifdef MSDOS
446   strcpy (cmd, "command.com ");
447 #else
448   strcpy (cmd, "sh -c ");
449 #endif
450   
451 /*  strcat (cmd, program); */ /* shrouded 93/Nov/20 */
452   strcat (cmd, "Make");
453 #ifndef MSDOS
454   strcat (cmd, "TeX");
455 #endif
456   strcat (cmd, program);
457   cmd_len = strlen (cmd);
458   cmd[cmd_len++] = ' ';
459
460   while (name_of_file[i] != ' ')
461     cmd[cmd_len++] = name_of_file[i++];
462
463   /* Add terminating null.  */
464   cmd[cmd_len] = 0;
465
466   /* Don't show any output.  */
467 #ifdef MSDOS
468   strcat (cmd, "> nul");  /* ? 93/Nov/20 */
469 #else
470   strcat (cmd, ">/dev/null 2>&1");
471 #endif
472
473 /* Run the command, and return whether or not it succeeded.  */
474   ret = system (cmd);
475   return ret == EXIT_SUCCESS_CODE;
476 #endif /* not NO_MAKE_TEX */
477 }
478
479 #define TEXONLY
480
481 /* This is called by TeX if an \input resp. TFM file can't be opened.  */
482
483 bool maketextex (void)          /* called in tex3.c and tex8.c */
484 {
485 /*  return make_tex_file ("MakeTeXTeX"); */
486   return make_tex_file ("TeX"); 
487 }
488
489 bool maketextfm (void)          /* called in tex3.c */
490 {
491 /*  return make_tex_file ("MakeTeXTFM"); */
492   return make_tex_file ("TFM");
493 }
494
495 #ifndef TEXONLY
496 bool maketexmf (void)
497 {
498 /*  return make_tex_file ("MakeTeXMF"); */
499   return make_tex_file ("MF");
500 }
501 #endif /* ifndef TEXONLY */
502
503 char *get_env_shroud (char *);    /* defined in texmf.c */
504
505 /* char outputdirectory[PATH_MAX]; */       /* defined in local.c */
506
507 extern char *dvi_directory;       /* defined in local.c */
508 extern char *log_directory;       /* defined in local.c */
509 extern char *aux_directory;       /* defined in local.c */
510
511 #ifdef IGNORED
512 /* Try and figure out if can write to current directory */
513 bool isitsafe (char *name)
514 {
515 /*  struct stat statbuf; */         /* debugging 94/Mar/2 */
516 /*  Can't test access on file, since fails if not exist */
517 /*  Can't test access on `nul', since always fails */ 
518 /*  Can   test access on `.', but its true on locked diskette! */
519 /*  stat on directory always says read an write permission */
520   return true;        /* for now */
521 }
522 #endif
523
524 /* open_output moved to end to avoid pragma problems 96/Sep/15 */
525
526 /* used only in start_input in tex3.c, and in open_or_close_in in tex8.c */
527 /* modified 97/June/5 to take null terminated (C) string */
528
529 #ifdef IGNORED
530 bool extensionirrelevantaux (char *base, char *suffix)
531
532   bool ret;
533 /*  make_c_string (&base);  */
534 /*  base[nlen+1] = '\0'; */     /* null terminate */
535 #ifdef MSDOS
536 /*  In DOS, an extension is irrelevant if there already is an extension ! */
537 /*  MAY NEED TO REVISE IN WIN32 where we can have foo.bar.chomp.tex ??? */
538   {               /* simplification 1996/Jan/20 ??? */
539     char *s, *t;
540     if ((s = strrchr (base, '.')) == NULL)
541       ret = 0; /* no extension */
542     else
543     {
544       if ((t = strrchr (base, PATH_SEP)) != NULL ||
545           (t = strrchr (base, '\\')) != NULL ||
546           (t = strrchr (base, ':')) != NULL)
547       {
548         if (t > s)
549           ret = 0; /* last dot occurs in path - no extension */
550         else
551           ret = 1;     /* last dot occurs in file name itself */
552       }
553       else
554         ret = 1;       /* name not qualified and has dot */
555     }
556   }
557 #else /*  not MSDOS */
558   {
559     char temp[PATH_MAX];
560     strcpy (temp, base);
561     strcat (temp, ".");
562     strcat (temp, suffix);
563     ret = same_file_p (base, temp);
564   }
565 #endif /* end of not MSDOS */
566 /*  make_pascal_string (&base); */
567 /*  base[nlen+1] = ' '; */      /* space terminate */
568   return ret;
569 }
570 #endif /* IGNORED */
571
572 /* Test if the Pascal string BASE concatenated with the extension
573    `.SUFFIX' is the same file as just BASE.  SUFFIX is a C string.  */
574
575 /* used in `start_input' (tex3.c) and open_or_close_in (tex8.c) */
576 /* used to always return true, since in DOS can have only one extension */
577 /* modified 98/Feb/7 to always return false */
578
579 bool extensionirrelevantp (unsigned char *base, int nlen, char *suffix)
580
581 #ifdef IGNORED
582   bool ret;
583   base[nlen+1] = '\0';      /* null terminate */
584   ret = extensionirrelevantaux(base+1, suffix);
585   base[nlen+1] = ' ';     /* space terminate */
586   return ret;
587 #endif
588   return false;
589 }
590
591 /* #define a_close(f) if (f) { if (ferror (f)) {perror(""); exit(1);} } if (f) (void) fclose (f) */
592 /* #define a_close(f) if (f) (void) check_fclose (f) */
593
594 /* At least check for I/O error (such as disk full) when closing */
595 /* Would be better to check while writing - but this is better than nothing */
596 /* This is used for both input and output files, but never mind ... */
597
598 /* now a_close returns -1 on error --- which could be used by caller */
599 /* probably want to ignore on input files ... */
600
601 void perrormod (char *s);       /* in local.c */
602
603 // check_fclose not used by anything
604 /* 1993/Nov/20 - bkph */
605 int check_fclose (FILE *f)
606 {
607   if (f == NULL)
608     return 0;      // sanity check
609   if (ferror(f) || fclose (f))
610   {
611     perrormod("\n! I/O Error");
612     uexit (1);    // ???
613   }
614   return 0;
615 }
616
617 /* open_output moved down here to avoid potential pragma problem */
618
619 /* #pragma optimize ("g", off) *//* try and avoid compiler bug here */
620
621 /* Open an output file F either in the current directory or in
622    $TEXMFOUTPUT/F, if the environment variable `TEXMFOUTPUT' exists.
623    (Actually, this applies to the BibTeX output files, also, but
624    `TEXMFBIBOUTPUT' was just too long.)  The filename is in the global
625    `name_of_file', as a Pascal string.  We return whether or not the open
626    succeeded.  If it did, the global `name_length' is set to the length
627    of the actual filename.  */
628
629 bool open_output (FILE **f, char *fopen_mode)
630 {
631   unsigned temp_length;
632
633 /*  null_terminate (name_of_file + 1);  */  /* moved here 95/Sep/26  */
634   name_of_file[name_length + 1] = '\0'; /* null terminate */
635
636 /* reinsert '~' and ' ' in file names -  95/June/5 */
637 /* done late to prevent problems with  null_terminate / space_terminate */  
638   if (pseudo_tilde != 0 || pseudo_space !=  0)
639   {
640     retwiddle(name_of_file + 1);
641   }
642
643 #ifdef MSDOS
644 /* 8 + 3 file names on Windows NT 95/Feb/20 */
645   if (shorten_file_name)
646   {
647     check_short_name(name_of_file + 1);         /* 95/Sep/26 */
648   }
649 #endif
650
651 /*  null_terminate (name_of_file + 1); */ /* Make the filename into a C string.  */
652
653 /*  if (debug_flag) try_and_open(name_of_file+1); */  /* debugging 94/Mar/20 */
654
655 #ifdef MSDOS
656 /* write into user specified output directory if given on command line */
657 /* following code added 1993/Dec/12 */ /* separated 1996/Jan/20 */
658   if (prepend_path_if (name_of_file+1, name_of_file+1, ".dvi", (unsigned char *) dvi_directory) ||
659       prepend_path_if (name_of_file+1, name_of_file+1, ".log", (unsigned char *) log_directory) ||
660       prepend_path_if (name_of_file+1, name_of_file+1, ".aux", (unsigned char *) aux_directory))
661   {
662     if (open_trace_flag)
663     {
664       sprintf(log_line, "After prepend %s\n", name_of_file+1);
665       show_line(log_line, 0);
666     }
667   }
668 #endif
669
670 /* name_length recomputed below so don't need to do it yet */
671
672   if (open_trace_flag)
673   {
674     sprintf(log_line, " Open `%s' for output ", name_of_file + 1); /* C string */
675     show_line(log_line, 0);
676   }   // debugging only
677
678 /* Is the filename openable as given?  */
679
680 /*  if share_flag is non-zero and we are opening for reading use fsopen */
681 /*  but we can assume this is opening here for *output* */
682   *f = fopen((char *) name_of_file + 1, fopen_mode);
683
684 /* Can't open as given.  Try the envvar.  */
685   if (*f == NULL)
686   {
687 /*    string temp_dir = getenv ("TEXMFOUTPUT"); */  /* 93/Nov/20 */
688 /*    string temp_dir = getenv ("TEXMFOUT"); */ /* 93/Nov/20 */
689 /*      string temp_dir = get_env_shroud ("UFYNGPVUQVU"); */
690     string temp_dir = get_env_shroud ("UFYNGPVU");
691
692 /*    if (deslash) unixify(temp_dir); */    /* deslashify 93/Dec/28 */
693
694     if (temp_dir != NULL)
695     {
696 #ifdef BUILDNAMEDIRECT
697       unsigned char temp_name[PATH_MAX];
698       xconcat3((char *) temp_name, temp_dir, PATH_SEP_STRING, (char *)name_of_file + 1);
699 #else
700 /*          string temp_name = concat3 (temp_dir, "/", name_of_file + 1); */
701       string temp_name = concat3 (temp_dir, PATH_SEP_STRING, name_of_file + 1);
702 #endif
703       if (deslash) unixify((char *) temp_name);     /* deslashify 93/Dec/28 */
704 /*  If share_flag is non-zero and we are opening for reading use fsopen */
705 /*  but we can assume this is opening here for *output* */
706       *f = fopen((char*)temp_name, fopen_mode);
707 /*  If this succeeded, change name_of_file accordingly.  */
708       if (*f) strcpy((char*) name_of_file + 1, (char *) temp_name);
709 #ifndef BUILDNAMEDIRECT
710       free (temp_name);
711 #endif
712     }
713   }
714
715 //  show_line(name_of_file+1, 1);   // debugging only
716 //  New code to remember complete dvi_file name and log_file_name
717 //  To remember for output at the end 2000 June 18
718   if (strstr((char *)name_of_file + 1, ".dvi") != NULL)
719   {
720     if (qualified(name_of_file+1))
721       *log_line = '\0';
722     else
723     {
724       (void) _getcwd(log_line, sizeof(log_line));
725       strcat(log_line, PATH_SEP_STRING);
726     }
727     strcat(log_line, (char*) name_of_file+1);
728     unixify(log_line);
729     dvi_file_name = xstrdup(log_line);
730 //    show_line(dvi_file_name, 1);  // debugging only
731   }
732   else if (strstr((char *)name_of_file + 1, ".log") != NULL)
733   {
734     if (qualified(name_of_file+1))
735       *log_line = '\0';
736     else
737     {
738       (void) _getcwd(log_line, sizeof(log_line));
739       strcat(log_line, PATH_SEP_STRING);
740     }
741     strcat(log_line, (char *) name_of_file + 1);
742     unixify(log_line);
743     log_file_name = xstrdup(log_line);
744 //    show_line(log_file_name, 1);  // debugging only
745   }
746 /* Back into a Pascal string, but first get its length.  */
747   temp_length = strlen ((char *)name_of_file + 1);
748 /*  space_terminate (name_of_file + 1); */
749   name_of_file[temp_length+1] = ' ';  /* space terminate */
750
751 /* Only set `name_length' if we succeeded.  I'm not sure why.  */
752   if (*f)               /* TEST ? 94/MAR/2 */
753     name_length = temp_length;
754   
755   return *f != NULL;
756 }
757
758 /* #pragma optimize ("g",)*/  /* try and avoid compiler bug here */
759 /* #pragma optimize ("", on) */   /* try and avoid compiler bug here */