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
25 #pragma warning(disable:4115) // kill rpcasync.h complaint
27 #define MYLIBAPI __declspec(dllexport)
32 #pragma warning(disable:4996)
33 #pragma warning(disable:4131) // old style declarator
34 #pragma warning(disable:4135) // conversion between different integral types
35 #pragma warning(disable:4127) // conditional expression is constant
39 #include <direct.h> /* for _getcwd() */
46 #define PATH_SEP_STRING "/"
48 /* openinout.c: open input and output files. */
50 #define BUILDNAMEDIRECT /* avoid malloc for string concat */
52 bool test_read_access (unsigned char *, int); /* in ourpaths.c - bkph */
54 extern char *unixify (char *); /* in pathsrch.c bkph */
56 extern void try_and_open (char *); /* in local.c bkph */
58 extern int shorten_file_name; /* in local.c bkph */
60 #ifdef FUNNY_CORE_DUMP
61 /* This is defined in ./texmf.c. */
62 extern void funny_core_dump();
63 #endif /* FUNNY_CORE_DUMP */
67 #ifdef BUILDNAMEDIRECT
68 /* kpathsea/concat.c */
69 /* kpathsea/concat3.c */
70 /* similar to concat, but AVOIDS using malloc, pass in place to put result */
71 char *xconcat (char *buffer, char *s1, char *s2)
77 { /* treat special case of overlap */
78 memmove (buffer + n1, buffer, n2 + 1); /* trailing null ! */
79 strncpy (buffer, s1, n1);
84 strcat(buffer + n1, s2);
89 /* similar to concat3, but avoids using malloc, pass in place to put result */
90 char *xconcat3 (char *buffer, char *s1, char *s2, char *s3)
97 { /* treat special case of overlap */
98 memmove (buffer + n1 + n2, buffer, n3 + 1); /* trailing null ! */
99 strncpy (buffer, s1, n1);
100 strncpy (buffer + n1, s2, n2);
105 strcat(buffer + n1, s2);
106 strcat(buffer + n1 + n2, s3);
110 #endif /* end of BUILDNAMEDIRECT */
112 #endif /* end of ifdef MSDOS ??? */
115 /* separated out 1996/Jan/20 to make easier to read */
116 /* assumes path does not end in PATH_SEP */
117 void patch_in_path (unsigned char *buffer, unsigned char *name, unsigned char *path)
119 #ifdef BUILDNAMEDIRECT
121 strcpy((char *) buffer, (char *) name);
123 xconcat3((char *) buffer, (char *) path, PATH_SEP_STRING, (char *) name);
126 temp_name = concat3 (path, PATH_SEP_STRING, name);
127 strcpy (buffer, temp_name);
132 int qualified (unsigned char * name)
134 if (strchr((char *) name, PATH_SEP) != NULL ||
135 strchr((char *) name, '\\') != NULL ||
136 strchr((char *) name, ':') != NULL)
143 (ii) name not qualified
146 int prepend_path_if (unsigned char *buffer, unsigned char *name, char *ext, unsigned char *path)
157 if (strstr((char *)name, ext) == NULL)
160 patch_in_path(buffer, name, path);
164 #endif /* end of MSDOS */
166 /* Following works on null-terminated strings */
168 void check_short_name (unsigned char *s)
170 unsigned char *star, *sdot;
173 if ((star = (unsigned char *) strrchr((char *) s, '\\')) != NULL)
175 else if ((star = (unsigned char *) strrchr((char *) s, '/')) != NULL)
177 else if ((star = (unsigned char *) strchr((char *) s, ':')) != NULL)
182 if ((sdot = (unsigned char *) strchr((char *) star, '.')) != NULL)
185 n = strlen((char *) star);
188 strcpy((char *) star + 8, (char *) star + n);
190 if ((sdot = (unsigned char *) strchr((char *) star, '.')) != NULL)
194 n = strlen((char *) star);
201 /* Following works on both null-terminated names */
202 /* reconvert 254 to '~' in file name 95/Sep/26 */
203 /* reconvert 255 to ' ' in file name 95/Sep/26 */
204 /* we do this in tex3.c start_input() -> scan_file_name() now 95/Sep/26 */
205 /* kpathsea/tilde.c */
206 void retwiddle (unsigned char *s)
208 /* assumes null terminated - 97/June/5 */
209 /* while (*s != '\0' && *s != ' ') { */
212 if (*s == (unsigned char) pseudo_tilde)
214 else if (*s == (unsigned char) pseudo_space)
220 /* #endif */ /* ??? */
222 /* Open an input file F, using the path PATHSPEC and passing
223 FOPEN_MODE to fopen. The filename is in `name_of_file', as a Pascal
224 string. We return whether or not the open succeeded. If it did, we
225 also set `name_length' to the length of the full pathname that we
227 /* in lib/openclose.c */
228 bool open_input (FILE **f, path_constant_type path_index, char *fopen_mode)
230 bool openable = false;
232 #if defined (FUNNY_CORE_DUMP) && !defined (BibTeX)
233 if (path_index == TEXINPUTPATH &&
234 strncmp (name_of_file + 1, "HackyInputFileNameForCoreDump.tex", 33) == 0)
236 #endif /* FUNNY_CORE_DUMP and not BibTeX */
241 if (strcmp(fopen_mode, "r") == 0)
242 fopen_mode = "rb"; /* so can catch `return' bkph */
246 name_of_file[name_length + 1] = '\0'; /* null terminate */
248 /* reinsert '~' and ' ' in file names - 95/June/5 */
249 /* done late to prevent problems with null_terminate / space_terminate */
250 if (pseudo_tilde != 0 || pseudo_space != 0)
251 retwiddle(name_of_file + 1);
254 /* 8 + 3 file names on Windows NT 95/Feb/20 */
255 if (shorten_file_name)
257 check_short_name(name_of_file + 1);
263 sprintf(log_line, " Open `%s' for input ", name_of_file + 1); /* Pascal */
264 show_line(log_line, 0);
267 if (test_read_access(name_of_file + 1, path_index))
269 /* if (test_read_access(name_of_file, name_length, path_index)) */
271 /* We can assume `name_of_file' is openable, */
272 /* since `test_read_access' just returned true. */
273 /* *f = xfopen_pas (name_of_file, fopen_mode); */
274 *f = xfopen((char *) name_of_file + 1, fopen_mode);
276 // should we check *f == NULL ??? (should be OK because of test_read_access)
278 /* If we found the file in the current directory, don't leave the
279 `./' at the beginning of `name_of_file', since it looks dumb when
280 TeX says `(./foo.tex ...)', and analogously for Metafont. */
282 if (name_of_file[1] == '.' && /* 1994/Mar/1 */
283 (name_of_file[2] == PATH_SEP || name_of_file[2] == '\\'))
285 if (name_of_file[1] == '.' && name_of_file[2] == PATH_SEP)
289 /* while (name_of_file[i + 2] != ' ') */
290 while (name_of_file[i + 2] != '\0')
292 name_of_file[i] = name_of_file[i + 2];
295 /* name_of_file[i] = ' '; */
296 name_of_file[i] = '\0';
300 /* name_length = strchr(name_of_file + 1, ' ') - (name_of_file + 1); */
301 name_length = strlen((char *) name_of_file + 1);
304 /* If we just opened a TFM file, we have to read the first byte,
305 since TeX wants to look at it. What a kludge. */
306 /* See comments in ctex.ch for why we need this. */
307 if (path_index == TFMFILEPATH)
309 tfm_temp = getc (*f);
314 /* code added 94/June/21 to show 'fmt' file opening in log */
315 if (strstr((char *) name_of_file + 1, ".fmt") != NULL)
317 if (format_file == NULL)
319 format_file = xstrdup((char *) name_of_file + 1);
321 } /* remember full format file name with path */
322 else if (strstr((char *)name_of_file+1, ".poo") != NULL)
324 if (string_file == NULL)
326 string_file = xstrdup((char *) name_of_file + 1);
328 } /* remember full pool file name with path */
329 else if (strstr((char *)name_of_file+1, ".tfm") != NULL)
331 if (show_tfm_flag && log_opened)
334 int old_setting = selector;
335 char *s = name_of_file + 1;
344 selector = old_setting;
347 n = strlen((char *) name_of_file + 1);
349 if (file_offset + n > max_print_line)
351 putc('\n', log_file);
353 } /* somewhat risky ? */
357 fprintf(log_file, "(%s)", name_of_file + 1);
359 /* space_terminate (name_of_file + 1); */
360 #endif /* end of WRAPLINES */
363 /* code added 98/Sep/29 to catch first file input */
364 /* is there a problem if this file bombs ? */
365 else if (source_direct == NULL) /* 98/Sep/29 */
369 source_direct = xstrdup((char *) name_of_file + 1);
373 sprintf(log_line, "Methinks the source %s is `%s'\n", "file", source_direct);
374 show_line(log_line, 0);
377 if ((s = strrchr(source_direct, '/')) == NULL)
378 *source_direct = '\0';
384 sprintf(log_line, "Methinks the source %s is `%s'\n", "directory", source_direct);
385 show_line(log_line, 0);
388 #endif /* end of MSDOS */
391 /* space_terminate (name_of_file + 1); */
393 unsigned temp_length = strlen((char *) name_of_file + 1);
394 name_of_file[temp_length + 1] = ' '; /* space terminate */
395 /* set up name_length ??? */
401 /* Call the external program PROGRAM, passing it `name_of_file'. */
402 /* This nonsense probably only works for Unix anyway. bkph */
403 /* For one thing, MakeTeXTFM etc is more than 8 characters ! */
411 char *get_env_shroud (char *); /* defined in texmf.c */
413 /* char outputdirectory[PATH_MAX]; */ /* defined in local.c */
415 extern char * dvi_directory; /* defined in local.c */
416 extern char * log_directory; /* defined in local.c */
417 extern char * aux_directory; /* defined in local.c */
418 extern char * fmt_directory; /* defined in local.c */
419 extern char * pdf_directory; /* defined in local.c */
421 /* At least check for I/O error (such as disk full) when closing */
422 /* Would be better to check while writing - but this is better than nothing */
423 /* This is used for both input and output files, but never mind ... */
425 /* now a_close returns -1 on error --- which could be used by caller */
426 /* probably want to ignore on input files ... */
428 void perrormod (char *s); /* in local.c */
430 // check_fclose not used by anything
431 /* 1993/Nov/20 - bkph */
432 int check_fclose (FILE * f)
435 return 0; // sanity check
437 if (ferror(f) || fclose (f))
439 perrormod("\n! I/O Error");
446 /* open_output moved down here to avoid potential pragma problem */
448 bool open_output (FILE **f, char *fopen_mode)
450 unsigned temp_length;
452 name_of_file[name_length + 1] = '\0'; /* null terminate */
454 if (pseudo_tilde != 0 || pseudo_space != 0)
456 retwiddle(name_of_file + 1);
460 /* 8 + 3 file names on Windows NT 95/Feb/20 */
461 if (shorten_file_name)
463 check_short_name(name_of_file + 1);
469 if (prepend_path_if (name_of_file + 1, name_of_file + 1, ".dvi", (unsigned char *) dvi_directory) ||
470 prepend_path_if (name_of_file + 1, name_of_file + 1, ".log", (unsigned char *) log_directory) ||
471 prepend_path_if (name_of_file + 1, name_of_file + 1, ".aux", (unsigned char *) aux_directory) ||
472 prepend_path_if (name_of_file + 1, name_of_file + 1, ".fmt", (unsigned char *) fmt_directory) ||
473 prepend_path_if (name_of_file + 1, name_of_file + 1, ".pdf", (unsigned char *) pdf_directory))
477 sprintf(log_line, "After prepend %s\n", name_of_file+1);
478 show_line(log_line, 0);
485 sprintf(log_line, " Open `%s' for output ", name_of_file + 1);
486 show_line(log_line, 0);
489 /* Is the filename openable as given? */
491 /* if share_flag is non-zero and we are opening for reading use fsopen */
492 /* but we can assume this is opening here for *output* */
493 *f = fopen((char *) name_of_file + 1, fopen_mode);
495 /* Can't open as given. Try the envvar. */
498 string temp_dir = get_env_shroud ("UFYNGPVU");
500 /* if (deslash) unixify(temp_dir); */ /* deslashify 93/Dec/28 */
502 if (temp_dir != NULL)
504 #ifdef BUILDNAMEDIRECT
505 unsigned char temp_name[PATH_MAX];
506 xconcat3((char *) temp_name, temp_dir, PATH_SEP_STRING, (char *) name_of_file + 1);
508 /* string temp_name = concat3 (temp_dir, "/", name_of_file + 1); */
509 string temp_name = concat3 (temp_dir, PATH_SEP_STRING, name_of_file + 1);
512 unixify((char *) temp_name); /* deslashify 93/Dec/28 */
513 /* If share_flag is non-zero and we are opening for reading use fsopen */
514 /* but we can assume this is opening here for *output* */
515 *f = fopen((char*)temp_name, fopen_mode);
516 /* If this succeeded, change name_of_file accordingly. */
518 strcpy((char*) name_of_file + 1, (char *) temp_name);
519 #ifndef BUILDNAMEDIRECT
525 if (strstr((char *) name_of_file + 1, ".dvi") != NULL)
527 if (qualified(name_of_file + 1))
531 (void) _getcwd(log_line, sizeof(log_line));
532 strcat(log_line, PATH_SEP_STRING);
535 strcat(log_line, (char*) name_of_file + 1);
537 dvi_file_name = xstrdup(log_line);
539 else if (strstr((char *)name_of_file + 1, ".log") != NULL)
541 if (qualified(name_of_file + 1))
545 (void) _getcwd(log_line, sizeof(log_line));
546 strcat(log_line, PATH_SEP_STRING);
549 strcat(log_line, (char *) name_of_file + 1);
551 log_file_name = xstrdup(log_line);
554 temp_length = strlen ((char *)name_of_file + 1);
555 name_of_file[temp_length+1] = ' ';
558 name_length = temp_length;