1 /* Copyright 1992 Karl Berry
2 Copyright 2007 TeX Users Group
3 Copyright 2014 Clerk Ma
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.
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.
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
21 #include <direct.h> /* for _getcwd() */
31 #define PATH_SEP_STRING "/"
33 /* openinout.c: open input and output files. */
35 #define BUILDNAMEDIRECT /* avoid malloc for string concat */
37 extern char *unixify (char *); /* in pathsrch.c bkph */
39 extern int shorten_file_name; /* in local.c bkph */
41 #ifdef FUNNY_CORE_DUMP
42 extern void funny_core_dump();
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)
56 memmove (buffer + n1, buffer, n2 + 1);
57 strncpy (buffer, s1, n1);
62 strcat(buffer + n1, s2);
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)
76 memmove (buffer + n1 + n2, buffer, n3 + 1);
77 strncpy (buffer, s1, n1);
78 strncpy (buffer + n1, s2, n2);
83 strcat(buffer + n1, s2);
84 strcat(buffer + n1 + n2, s3);
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)
98 #ifdef BUILDNAMEDIRECT
100 strcpy((char *) buffer, (char *) name);
102 xconcat3((char *) buffer, (char *) path, PATH_SEP_STRING, (char *) name);
105 temp_name = concat3(path, PATH_SEP_STRING, name);
106 strcpy (buffer, temp_name);
111 int qualified (unsigned char * name)
113 if (strchr((char *) name, PATH_SEP) != NULL ||
114 strchr((char *) name, '\\') != NULL ||
115 strchr((char *) name, ':') != NULL)
122 (ii) name not qualified
125 int prepend_path_if (unsigned char *buffer, unsigned char *name, char *ext, unsigned char *path)
136 if (strstr((char *)name, ext) == NULL)
139 patch_in_path(buffer, name, path);
143 #endif /* end of MSDOS */
145 // Following works on null-terminated strings
146 void check_short_name (unsigned char *s)
148 unsigned char *star, *sdot;
151 if ((star = (unsigned char *) strrchr((char *) s, '\\')) != NULL)
153 else if ((star = (unsigned char *) strrchr((char *) s, '/')) != NULL)
155 else if ((star = (unsigned char *) strchr((char *) s, ':')) != NULL)
160 if ((sdot = (unsigned char *) strchr((char *) star, '.')) != NULL)
163 n = strlen((char *) star);
166 strcpy((char *) star + 8, (char *) star + n);
168 if ((sdot = (unsigned char *) strchr((char *) star, '.')) != NULL)
172 n = strlen((char *) star);
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)
186 /* assumes null terminated - 97/June/5 */
187 /* while (*s != '\0' && *s != ' ') { */
190 if (*s == (unsigned char) pseudo_tilde)
192 else if (*s == (unsigned char) pseudo_space)
198 /* in lib/openclose.c */
199 bool open_input (FILE **f, path_constant_type path_index, char *fopen_mode)
201 bool openable = false;
202 char * file_name = NULL;
204 #if defined (FUNNY_CORE_DUMP) && !defined (BibTeX)
205 if (path_index == TEXINPUTPATH &&
206 strncmp (name_of_file + 1, "HackyInputFileNameForCoreDump.tex", 33) == 0)
208 #endif /* FUNNY_CORE_DUMP and not BibTeX */
213 if (strcmp(fopen_mode, "r") == 0)
214 fopen_mode = "rb"; /* so can catch `return' bkph */
218 name_of_file[name_length + 1] = '\0'; /* null terminate */
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);
226 /* 8 + 3 file names on Windows NT 95/Feb/20 */
227 if (shorten_file_name)
229 check_short_name(name_of_file + 1);
235 sprintf(log_line, " Open `%s' for input ", name_of_file + 1); /* Pascal */
236 show_line(log_line, 0);
242 file_name = kpse_find_file((const_string)name_of_file + 1, kpse_tex_format, 0);
245 file_name = kpse_find_file((const_string)name_of_file + 1, kpse_fmt_format, 0);
248 file_name = kpse_find_file((const_string)name_of_file + 1, kpse_tfm_format, 0);
252 if (file_name != NULL)
254 strcpy ((char *)name_of_file + 1, file_name);
255 *f = xfopen((char *) file_name, fopen_mode);
258 if (name_of_file[1] == '.' && (name_of_file[2] == PATH_SEP || name_of_file[2] == '\\'))
260 if (name_of_file[1] == '.' && name_of_file[2] == PATH_SEP)
265 while (name_of_file[i + 2] != '\0')
267 name_of_file[i] = name_of_file[i + 2];
271 name_of_file[i] = '\0';
275 name_length = strlen((char *) name_of_file + 1);
277 if (path_index == TFMFILEPATH)
279 tfm_temp = getc (*f);
280 //ungetc(tfm_temp, *f);
284 if (strstr((char *) name_of_file + 1, ".fmt") != NULL)
286 if (format_file == NULL)
288 format_file = xstrdup((char *) name_of_file + 1);
291 else if (strstr((char *)name_of_file+1, ".tfm") != NULL)
293 if (show_tfm_flag && log_opened)
296 int old_setting = selector;
297 char *s = name_of_file + 1;
306 selector = old_setting;
309 n = strlen((char *) name_of_file + 1);
311 if (file_offset + n > max_print_line)
313 putc('\n', log_file);
319 fprintf(log_file, "(%s)", name_of_file + 1);
321 #endif /* end of WRAPLINES */
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 */
330 source_direct = xstrdup((char *) name_of_file + 1);
334 sprintf(log_line, "Methinks the source %s is `%s'\n", "file", source_direct);
335 show_line(log_line, 0);
338 if ((s = strrchr(source_direct, '/')) == NULL)
339 *source_direct = '\0';
345 sprintf(log_line, "Methinks the source %s is `%s'\n", "directory", source_direct);
346 show_line(log_line, 0);
349 #endif /* end of MSDOS */
354 unsigned temp_length = strlen((char *) name_of_file + 1);
355 name_of_file[temp_length + 1] = ' '; /* space terminate */
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 ! */
371 char *get_env_shroud (char *); /* defined in texmf.c */
373 /* char outputdirectory[PATH_MAX]; */ /* defined in local.c */
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 */
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 ... */
385 /* now a_close returns -1 on error --- which could be used by caller */
386 /* probably want to ignore on input files ... */
388 void perrormod (char *s); /* in local.c */
390 // check_fclose not used by anything
391 /* 1993/Nov/20 - bkph */
392 int check_fclose (FILE * f)
395 return 0; // sanity check
397 if (ferror(f) || fclose (f))
399 perrormod("\n! I/O Error");
406 /* open_output moved down here to avoid potential pragma problem */
408 bool open_output (FILE **f, char *fopen_mode)
410 unsigned temp_length;
412 name_of_file[name_length + 1] = '\0';
414 if (pseudo_tilde != 0 || pseudo_space != 0)
416 retwiddle(name_of_file + 1);
420 /* 8 + 3 file names on Windows NT 95/Feb/20 */
421 if (shorten_file_name)
423 check_short_name(name_of_file + 1);
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))
436 sprintf(log_line, "After prepend %s\n", name_of_file + 1);
437 show_line(log_line, 0);
444 sprintf(log_line, " Open `%s' for output ", name_of_file + 1);
445 show_line(log_line, 0);
448 /* Is the filename openable as given? */
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);
454 /* Can't open as given. Try the envvar. */
457 string temp_dir = get_env_shroud ("UFYNGPVU");
459 /* if (deslash) unixify(temp_dir); */ /* deslashify 93/Dec/28 */
461 if (temp_dir != NULL)
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);
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);
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. */
477 strcpy((char*) name_of_file + 1, (char *) temp_name);
478 #ifndef BUILDNAMEDIRECT
484 if (strstr((char *) name_of_file + 1, ".dvi") != NULL)
486 if (qualified(name_of_file + 1))
491 (void) _getcwd(log_line, sizeof(log_line));
493 (void) getcwd(log_line, sizeof(log_line));
495 strcat(log_line, PATH_SEP_STRING);
498 strcat(log_line, (char*) name_of_file + 1);
500 dvi_file_name = xstrdup(log_line);
502 else if (strstr((char *) name_of_file + 1, ".pdf") != NULL)
504 if (qualified(name_of_file + 1))
509 (void) _getcwd(log_line, sizeof(log_line));
511 (void) getcwd(log_line, sizeof(log_line));
513 strcat(log_line, PATH_SEP_STRING);
516 strcat(log_line, (char*) name_of_file + 1);
518 pdf_file_name = xstrdup(log_line);
520 else if (strstr((char *)name_of_file + 1, ".log") != NULL)
522 if (qualified(name_of_file + 1))
527 (void) _getcwd(log_line, sizeof(log_line));
529 (void) getcwd(log_line, sizeof(log_line));
531 strcat(log_line, PATH_SEP_STRING);
534 strcat(log_line, (char *) name_of_file + 1);
536 log_file_name = xstrdup(log_line);
539 temp_length = strlen ((char *)name_of_file + 1);
540 name_of_file[temp_length+1] = ' ';
543 name_length = temp_length;