OSDN Git Service

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