OSDN Git Service

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