OSDN Git Service

replace some header files.
[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 #pragma warning(disable:4996)
31 #pragma warning(disable:4131) // old style declarator
32 #pragma warning(disable:4135) // conversion between different integral types
33 #pragma warning(disable:4127) // conditional expression is constant
34
35 #include <setjmp.h>
36
37 #include <direct.h>           /* for _getcwd() */
38
39 #define EXTERN extern
40
41 #include "texd.h"
42
43 #define PATH_SEP        '/'
44 #define PATH_SEP_STRING "/"
45
46 /* openinout.c: open input and output files. */
47
48 #define BUILDNAMEDIRECT         /* avoid malloc for string concat */
49
50 bool test_read_access (unsigned char *, int);   /* in ourpaths.c - bkph */
51
52 extern char *unixify (char *);      /* in pathsrch.c bkph */
53
54 extern void try_and_open (char *);    /* in local.c bkph */
55
56 extern int shorten_file_name;       /* in local.c bkph */
57
58 #ifdef FUNNY_CORE_DUMP
59 /* This is defined in ./texmf.c.  */
60 extern void funny_core_dump();
61 #endif /* FUNNY_CORE_DUMP */
62
63 #ifdef MSDOS
64
65 #ifdef BUILDNAMEDIRECT
66 /* kpathsea/concat.c */
67 /* kpathsea/concat3.c */
68 /* similar to concat, but AVOIDS using malloc, pass in place to put result */
69 char *xconcat (char *buffer, char *s1, char *s2)
70 {
71   int n1 = strlen(s1);
72   int n2 = strlen(s2);
73
74   if (buffer == s2)
75   {     /* treat special case of overlap */
76     memmove (buffer + n1, buffer, n2 + 1); /* trailing null ! */
77     strncpy (buffer, s1, n1);
78   }
79   else
80   {
81     strcpy(buffer, s1);
82     strcat(buffer + n1, s2);
83   }
84
85   return buffer;
86 }
87 /* similar to concat3, but avoids using malloc, pass in place to put result */
88 char *xconcat3 (char *buffer, char *s1, char *s2, char *s3)
89 {
90   int n1 = strlen(s1);
91   int n2 = strlen(s2);
92   int n3 = strlen(s3);
93
94   if (buffer == s3)
95   {     /* treat special case of overlap */
96     memmove (buffer + n1 + n2, buffer, n3 + 1); /* trailing null ! */
97     strncpy (buffer, s1, n1);
98     strncpy (buffer + n1, s2, n2);
99   }
100   else
101   {
102     strcpy(buffer, s1);
103     strcat(buffer + n1, s2);
104     strcat(buffer + n1 + n2, s3);
105   }
106   return buffer;
107 }
108 #endif /* end of BUILDNAMEDIRECT  */
109
110 #endif  /* end of ifdef MSDOS ??? */
111
112 #ifdef MSDOS
113 /* separated out 1996/Jan/20 to make easier to read */
114 /* assumes path does not end in PATH_SEP */
115 void patch_in_path (unsigned char *buffer, unsigned char *name, unsigned char *path)
116 {
117 #ifdef BUILDNAMEDIRECT
118   if (*path == '\0')
119     strcpy((char *) buffer, (char *) name);
120   else
121     xconcat3((char *) buffer, (char *) path, PATH_SEP_STRING, (char *) name);
122 #else
123   string temp_name;
124   temp_name = concat3 (path, PATH_SEP_STRING, name);
125   strcpy (buffer, temp_name);
126   free (temp_name);
127 #endif
128 }
129
130 int qualified (unsigned char * name)
131 {
132   if (strchr((char *) name, PATH_SEP) != NULL ||
133       strchr((char *) name, '\\') != NULL ||
134       strchr((char *) name, ':') != NULL)
135     return 1;
136   else
137     return 0;
138 }
139 /* patch path if 
140     (i)   path not empty
141     (ii)  name not qualified
142     (iii) ext match
143 */
144 int prepend_path_if (unsigned char *buffer, unsigned char *name, char *ext, unsigned char *path)
145 {
146   if (path == NULL)
147     return 0;
148
149   if (*path == '\0')
150     return 0;
151
152   if (qualified(name))
153     return 0;
154
155   if (strstr((char *)name, ext) == NULL)
156     return 0;
157
158   patch_in_path(buffer, name, path);
159
160   return 1;
161 }
162 #endif      /* end of MSDOS */
163
164 /*  Following works on null-terminated strings */
165
166 void check_short_name (unsigned char *s)
167 {
168   unsigned char *star, *sdot;
169   int n;
170
171   if ((star = (unsigned char *) strrchr((char *) s, '\\')) != NULL)
172     star++;
173   else if ((star = (unsigned char *) strrchr((char *) s, '/')) != NULL)
174     star++;
175   else if ((star = (unsigned char *) strchr((char *) s, ':')) != NULL)
176     star++;
177   else
178     star = s;
179
180   if ((sdot = (unsigned char *) strchr((char *) star, '.')) != NULL)
181     n = sdot - star;
182   else
183     n = strlen((char *) star);
184
185   if (n > 8)
186     strcpy((char *) star + 8, (char *) star + n);
187
188   if ((sdot = (unsigned char *) strchr((char *) star, '.')) != NULL)
189   {
190     star = sdot + 1;
191
192     n = strlen((char *) star);
193
194     if (n > 3)
195       *(star + 3) = '\0';
196   }
197 }
198
199 /* Following works on both null-terminated names */
200 /* reconvert 254 to '~' in file name 95/Sep/26 */
201 /* reconvert 255 to ' ' in file name 95/Sep/26 */
202 /* we do this in tex3.c start_input() -> scan_file_name() now 95/Sep/26 */
203 /* kpathsea/tilde.c */
204 void retwiddle (unsigned char *s)
205 {
206 /* assumes null terminated - 97/June/5 */
207 /*  while (*s != '\0' && *s != ' ') { */
208   while (*s != '\0')
209   {
210     if (*s == (unsigned char) pseudo_tilde)
211       *s = '~';
212     else if (*s == (unsigned char) pseudo_space)
213       *s = ' ';
214     s++;
215   }
216 }
217
218 /* in lib/openclose.c */
219 bool open_input (FILE **f, path_constant_type path_index, char *fopen_mode)
220 {
221   bool openable = false;
222
223 #if defined (FUNNY_CORE_DUMP) && !defined (BibTeX)
224   if (path_index == TEXINPUTPATH &&
225       strncmp (name_of_file + 1, "HackyInputFileNameForCoreDump.tex", 33) == 0)
226     funny_core_dump();
227 #endif /* FUNNY_CORE_DUMP and not BibTeX */
228
229 #ifdef MSDOS
230   if (return_flag)
231   {
232     if (strcmp(fopen_mode, "r") == 0)
233       fopen_mode = "rb";    /* so can catch `return' bkph */
234   }
235 #endif /* MSDOS */
236
237   name_of_file[name_length + 1] = '\0'; /* null terminate */
238
239 /* reinsert '~' and ' ' in file names -  95/June/5 */
240 /* done late to prevent problems with  null_terminate / space_terminate */  
241   if (pseudo_tilde != 0 || pseudo_space != 0)
242     retwiddle(name_of_file + 1);
243
244 #ifdef MSDOS
245 /* 8 + 3 file names on Windows NT 95/Feb/20 */
246   if (shorten_file_name)
247   {
248     check_short_name(name_of_file + 1);
249   }
250 #endif  /* MSDOS */
251   
252   if (open_trace_flag)
253   {
254     sprintf(log_line, " Open `%s' for input ", name_of_file + 1); /* Pascal */
255     show_line(log_line, 0);
256   }
257
258   if (test_read_access(name_of_file + 1, path_index))
259   {
260     *f = xfopen((char *) name_of_file + 1, fopen_mode);
261
262 #ifdef MSDOS
263     if (name_of_file[1] == '.' && (name_of_file[2] == PATH_SEP || name_of_file[2] == '\\'))
264 #else
265     if (name_of_file[1] == '.' && name_of_file[2] == PATH_SEP)
266 #endif
267     {
268       unsigned i = 1;
269
270       while (name_of_file[i + 2] != '\0')
271       {
272         name_of_file[i] = name_of_file[i + 2];
273         i++;
274       }
275
276       name_of_file[i] = '\0';
277       name_length = i - 1;
278     }
279     else
280       name_length = strlen((char *) name_of_file + 1);
281       
282 #ifdef TeX
283     if (path_index == TFMFILEPATH)
284     {
285       tfm_temp = getc (*f);
286     }
287 #endif /* TeX */  
288
289 #ifdef MSDOS
290     if (strstr((char *) name_of_file + 1, ".fmt") != NULL)
291     {
292       if (format_file == NULL)
293       {
294         format_file = xstrdup((char *) name_of_file + 1);
295       }
296     }
297     else if (strstr((char *)name_of_file + 1, ".poo") != NULL)
298     {
299       if (string_file == NULL)
300       {
301         string_file = xstrdup((char *) name_of_file + 1);
302       }
303     }
304     else if (strstr((char *)name_of_file+1, ".tfm") != NULL)
305     {
306       if (show_tfm_flag && log_opened)
307       {
308 #ifdef WRAPLINES
309         int old_setting = selector;
310         char *s = name_of_file + 1;
311         selector = log_only;
312         print_char(' ');
313         print_char('(');
314
315         while (*s != '\0')
316           print_char (*s++);
317
318         print_char(')');
319         selector = old_setting;
320 #else
321         int n; 
322         n = strlen((char *) name_of_file + 1);
323
324         if (file_offset + n > max_print_line)
325         {
326           putc('\n', log_file);
327           file_offset = 0;
328         }
329         else
330           putc(' ', log_file);
331
332         fprintf(log_file, "(%s)", name_of_file + 1);
333         file_offset += n+3;
334 /*        space_terminate (name_of_file + 1);  */
335 #endif  /*  end of WRAPLINES */
336       }
337     }
338 /*    code added 98/Sep/29 to catch first file input */
339 /*    is there a problem if this file bombs ? */
340     else if (source_direct == NULL) /* 98/Sep/29 */
341     {
342       char *s;
343
344       source_direct = xstrdup((char *) name_of_file + 1);
345
346       if (trace_flag)
347       {
348         sprintf(log_line, "Methinks the source %s is `%s'\n", "file", source_direct);
349         show_line(log_line, 0);
350       }
351
352       if ((s = strrchr(source_direct, '/')) == NULL)
353         *source_direct = '\0';
354       else
355         *(s+1) = '\0';
356
357       if (trace_flag)
358       {
359         sprintf(log_line, "Methinks the source %s is `%s'\n", "directory", source_direct);
360         show_line(log_line, 0);
361       }
362     }
363 #endif  /* end of MSDOS */
364     openable = true;
365   }
366 /*  space_terminate (name_of_file + 1); */
367   {
368     unsigned temp_length = strlen((char *) name_of_file + 1);
369     name_of_file[temp_length + 1] = ' ';  /* space terminate */
370 /*    set up name_length ??? */
371   }
372
373   return openable;
374 }
375
376 /* Call the external program PROGRAM, passing it `name_of_file'.  */
377 /* This nonsense probably only works for Unix anyway. bkph */
378 /* For one thing, MakeTeXTFM etc is more than 8 characters ! */
379
380 #ifdef MSDOS
381   #define NO_MAKETEX
382 #endif
383
384 #define TEXONLY
385
386 char *get_env_shroud (char *);    /* defined in texmf.c */
387
388 /* char outputdirectory[PATH_MAX]; */       /* defined in local.c */
389
390 extern char * dvi_directory; /* defined in local.c */
391 extern char * log_directory; /* defined in local.c */
392 extern char * aux_directory; /* defined in local.c */
393 extern char * fmt_directory; /* defined in local.c */
394 extern char * pdf_directory; /* defined in local.c */
395
396 /* At least check for I/O error (such as disk full) when closing */
397 /* Would be better to check while writing - but this is better than nothing */
398 /* This is used for both input and output files, but never mind ... */
399
400 /* now a_close returns -1 on error --- which could be used by caller */
401 /* probably want to ignore on input files ... */
402
403 void perrormod (char *s);       /* in local.c */
404
405 // check_fclose not used by anything
406 /* 1993/Nov/20 - bkph */
407 int check_fclose (FILE * f)
408 {
409   if (f == NULL)
410     return 0;      // sanity check
411
412   if (ferror(f) || fclose (f))
413   {
414     perrormod("\n! I/O Error");
415     uexit (1);    // ???
416   }
417
418   return 0;
419 }
420
421 /* open_output moved down here to avoid potential pragma problem */
422
423 bool open_output (FILE **f, char *fopen_mode)
424 {
425   unsigned temp_length;
426
427   name_of_file[name_length + 1] = '\0'; /* null terminate */
428
429   if (pseudo_tilde != 0 || pseudo_space !=  0)
430   {
431     retwiddle(name_of_file + 1);
432   }
433
434 #ifdef MSDOS
435 /* 8 + 3 file names on Windows NT 95/Feb/20 */
436   if (shorten_file_name)
437   {
438     check_short_name(name_of_file + 1);
439   }
440 #endif
441
442 #ifdef MSDOS
443
444   if (prepend_path_if (name_of_file + 1, name_of_file + 1, ".dvi", (unsigned char *) dvi_directory) ||
445       prepend_path_if (name_of_file + 1, name_of_file + 1, ".log", (unsigned char *) log_directory) ||
446       prepend_path_if (name_of_file + 1, name_of_file + 1, ".aux", (unsigned char *) aux_directory) ||
447       prepend_path_if (name_of_file + 1, name_of_file + 1, ".fmt", (unsigned char *) fmt_directory) ||
448       prepend_path_if (name_of_file + 1, name_of_file + 1, ".pdf", (unsigned char *) pdf_directory))
449   {
450     if (open_trace_flag)
451     {
452       sprintf(log_line, "After prepend %s\n", name_of_file+1);
453       show_line(log_line, 0);
454     }
455   }
456 #endif
457
458   if (open_trace_flag)
459   {
460     sprintf(log_line, " Open `%s' for output ", name_of_file + 1);
461     show_line(log_line, 0);
462   }
463
464 /* Is the filename openable as given?  */
465
466 /*  if share_flag is non-zero and we are opening for reading use fsopen */
467 /*  but we can assume this is opening here for *output* */
468   *f = fopen((char *) name_of_file + 1, fopen_mode);
469
470 /* Can't open as given.  Try the envvar.  */
471   if (*f == NULL)
472   {
473     string temp_dir = get_env_shroud ("UFYNGPVU");
474
475 /*    if (deslash) unixify(temp_dir); */    /* deslashify 93/Dec/28 */
476
477     if (temp_dir != NULL)
478     {
479 #ifdef BUILDNAMEDIRECT
480       unsigned char temp_name[PATH_MAX];
481       xconcat3((char *) temp_name, temp_dir, PATH_SEP_STRING, (char *) name_of_file + 1);
482 #else
483 /*    string temp_name = concat3 (temp_dir, "/", name_of_file + 1); */
484       string temp_name = concat3 (temp_dir, PATH_SEP_STRING, name_of_file + 1);
485 #endif
486       if (deslash)
487         unixify((char *) temp_name);     /* deslashify 93/Dec/28 */
488 /*  If share_flag is non-zero and we are opening for reading use fsopen */
489 /*  but we can assume this is opening here for *output* */
490       *f = fopen((char*)temp_name, fopen_mode);
491 /*  If this succeeded, change name_of_file accordingly.  */
492       if (*f)
493         strcpy((char*) name_of_file + 1, (char *) temp_name);
494 #ifndef BUILDNAMEDIRECT
495       free (temp_name);
496 #endif
497     }
498   }
499
500   if (strstr((char *) name_of_file + 1, ".dvi") != NULL)
501   {
502     if (qualified(name_of_file + 1))
503       *log_line = '\0';
504     else
505     {
506       (void) _getcwd(log_line, sizeof(log_line));
507       strcat(log_line, PATH_SEP_STRING);
508     }
509
510     strcat(log_line, (char*) name_of_file + 1);
511     unixify(log_line);
512     dvi_file_name = xstrdup(log_line);
513   }
514   else if (strstr((char *)name_of_file + 1, ".log") != NULL)
515   {
516     if (qualified(name_of_file + 1))
517       *log_line = '\0';
518     else
519     {
520       (void) _getcwd(log_line, sizeof(log_line));
521       strcat(log_line, PATH_SEP_STRING);
522     }
523
524     strcat(log_line, (char *) name_of_file + 1);
525     unixify(log_line);
526     log_file_name = xstrdup(log_line);
527   }
528
529   temp_length = strlen ((char *)name_of_file + 1);
530   name_of_file[temp_length+1] = ' ';
531
532   if (*f)
533     name_length = temp_length;
534   
535   return *f != NULL;
536 }