OSDN Git Service

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