OSDN Git Service

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