OSDN Git Service

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