OSDN Git Service

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