beta-0.89.2
[luatex.git] / source / texk / web2c / lib / openclose.c
blobc5e1414ab3e577e8f4e4d4c8b9276e61ed8f3872
1 /* openclose.c: open and close files for TeX, Metafont, and BibTeX.
3 Written 1995 Karl Berry. Public domain. */
5 #include <w2c/config.h>
6 #include "lib.h"
7 #include <kpathsea/c-pathch.h>
8 #include <kpathsea/tex-file.h>
9 #include <kpathsea/variable.h>
10 #include <kpathsea/absolute.h>
11 #ifdef PTEX
12 #include <ptexenc/ptexenc.h>
13 #endif
15 #ifdef WIN32
16 #undef fopen
17 #undef xfopen
18 #define fopen fsyscp_fopen
19 #define xfopen fsyscp_xfopen
20 #endif
22 /* The globals we use to communicate. */
23 extern string nameoffile;
24 extern unsigned namelength;
26 /* Define some variables. */
27 /* For "file:line:error" style error messages. */
28 string fullnameoffile; /* Defaults to NULL. */
29 static string recorder_name; /* Defaults to NULL. */
30 static FILE *recorder_file; /* Defaults to NULL. */
31 /* For the filename recorder. */
32 boolean recorder_enabled; /* Defaults to false. */
33 /* For the output-dir option. */
34 string output_directory; /* Defaults to NULL. */
36 /* For TeX and MetaPost. See below. Always defined so we don't have to
37 #ifdef, and thus this file can be compiled once and go in lib.a. */
38 int tfmtemp;
39 int ocptemp;
40 int texinputtype;
42 /* Helpers for the filename recorder... */
43 /* Start the recorder */
44 static void
45 recorder_start(void)
47 /* Alas, while we'd like to use mkstemp it is not portable,
48 and doing the autoconfiscation (and providing fallbacks) is more
49 than we want to cope with. So we have to be content with using a
50 default name. Throw in the pid so at least parallel builds might
51 work (Debian bug 575731). */
52 string cwd;
53 char pid_str[MAX_INT_LENGTH];
55 /* Windows (MSVC) seems to have no pid_t, so instead of storing the
56 value returned by getpid() we immediately consume it. */
57 sprintf (pid_str, "%ld", (long) getpid());
58 recorder_name = concat3(kpse_program_name, pid_str, ".fls");
60 /* If an output directory was specified, use it instead of cwd. */
61 if (output_directory) {
62 string temp = concat3(output_directory, DIR_SEP_STRING, recorder_name);
63 free(recorder_name);
64 recorder_name = temp;
67 recorder_file = xfopen(recorder_name, FOPEN_W_MODE);
69 cwd = xgetcwd();
70 fprintf(recorder_file, "PWD %s\n", cwd);
71 free(cwd);
74 /* Change the name of the recorder file after we know the log file to
75 the usual thing -- no pid integer and the document file name instead
76 of the program name. Unfortunately, we have to explicitly take
77 -output-directory into account (again), since the NEW_NAME we are
78 called with does not; it is just the log file name with .log replaced
79 by .fls. */
81 void
82 recorder_change_filename (string new_name)
84 string temp = NULL;
86 if (!recorder_file)
87 return;
89 /* On windows, an opened file cannot be renamed. */
90 #if defined(WIN32)
91 fclose (recorder_file);
92 #endif
94 /* If an output directory was specified, use it. */
95 if (output_directory) {
96 temp = concat3(output_directory, DIR_SEP_STRING, new_name);
97 new_name = temp;
100 /* On windows, renaming fails if a file with new_name exists. */
101 #if defined(WIN32)
102 remove (new_name);
103 #endif
105 rename(recorder_name, new_name);
106 free(recorder_name);
107 recorder_name = xstrdup(new_name);
109 /* reopen the recorder file by FOPEN_A_MODE. */
110 #if defined(WIN32)
111 recorder_file = fsyscp_xfopen (recorder_name, FOPEN_A_MODE);
112 #endif
114 if (temp)
115 free (temp);
118 /* helper for recorder_record_* */
119 static void
120 recorder_record_name (const_string prefix, const_string name)
122 if (recorder_enabled) {
123 if (!recorder_file)
124 recorder_start();
125 fprintf(recorder_file, "%s %s\n", prefix, name);
126 fflush(recorder_file);
130 /* record an input file name */
131 void
132 recorder_record_input (const_string name)
134 recorder_record_name ("INPUT", name);
137 /* record an output file name */
138 void
139 recorder_record_output (const_string name)
141 recorder_record_name ("OUTPUT", name);
144 /* Open an input file F, using the kpathsea format FILEFMT and passing
145 FOPEN_MODE to fopen. The filename is in `nameoffile+1'. We return
146 whether or not the open succeeded. If it did, `nameoffile' is set to
147 the full filename opened, and `namelength' to its length. */
149 boolean
150 open_input (FILE **f_ptr, int filefmt, const_string fopen_mode)
152 string fname = NULL;
153 #ifdef FUNNY_CORE_DUMP
154 /* This only applies if a preloaded TeX/Metafont is being made;
155 it allows automatic creation of the core dump (typing ^\ loses
156 since that requires manual intervention). */
157 if ((filefmt == kpse_tex_format || filefmt == kpse_mf_format
158 || filefmt == kpse_mp_format)
159 && STREQ (nameoffile + 1, "HackyInputFileNameForCoreDump.tex"))
160 funny_core_dump ();
161 #endif
163 /* We havent found anything yet. */
164 *f_ptr = NULL;
165 if (fullnameoffile)
166 free(fullnameoffile);
167 fullnameoffile = NULL;
169 /* Look in -output-directory first, if the filename is not
170 absolute. This is because .aux and other such files will get
171 written to the output directory, and we have to be able to read
172 them from there. We only look for the name as-is. */
173 if (output_directory && !kpse_absolute_p (nameoffile+1, false)) {
174 fname = concat3 (output_directory, DIR_SEP_STRING, nameoffile + 1);
175 *f_ptr = fopen (fname, fopen_mode);
176 if (*f_ptr) {
177 free (nameoffile);
178 namelength = strlen (fname);
179 nameoffile = xmalloc (namelength + 2);
180 strcpy (nameoffile + 1, fname);
181 fullnameoffile = fname;
182 } else {
183 free (fname);
187 /* No file means do the normal search. */
188 if (*f_ptr == NULL) {
189 /* A negative FILEFMT means don't use a path. */
190 if (filefmt < 0) {
191 /* no_file_path, for BibTeX .aux files and MetaPost things. */
192 *f_ptr = fopen(nameoffile + 1, fopen_mode);
193 /* FIXME... fullnameoffile = xstrdup(nameoffile + 1); */
194 } else {
195 /* The only exception to `must_exist' being true is \openin, for
196 which we set `tex_input_type' to 0 in the change file. */
197 /* According to the pdfTeX people, pounding the disk for .vf files
198 is overkill as well. A more general solution would be nice. */
199 boolean must_exist = (filefmt != kpse_tex_format || texinputtype)
200 && (filefmt != kpse_vf_format);
201 fname = kpse_find_file (nameoffile + 1,
202 (kpse_file_format_type)filefmt,
203 must_exist);
204 if (fname) {
205 fullnameoffile = xstrdup(fname);
206 /* If we found the file in the current directory, don't leave
207 the `./' at the beginning of `nameoffile', since it looks
208 dumb when `tex foo' says `(./foo.tex ... )'. On the other
209 hand, if the user said `tex ./foo', and that's what we
210 opened, then keep it -- the user specified it, so we
211 shouldn't remove it. */
212 if (fname[0] == '.' && IS_DIR_SEP (fname[1])
213 && (nameoffile[1] != '.' || !IS_DIR_SEP (nameoffile[2])))
215 unsigned i = 0;
216 while (fname[i + 2] != 0) {
217 fname[i] = fname[i + 2];
218 i++;
220 fname[i] = 0;
223 /* kpse_find_file always returns a new string. */
224 free (nameoffile);
225 namelength = strlen (fname);
226 nameoffile = xmalloc (namelength + 2);
227 strcpy (nameoffile + 1, fname);
228 free (fname);
230 /* This fopen is not allowed to fail. */
231 #if defined(PTEX) && !defined(WIN32)
232 if (filefmt == kpse_tex_format ||
233 filefmt == kpse_bib_format) {
234 *f_ptr = nkf_open (nameoffile + 1, fopen_mode);
235 } else
236 #endif
237 *f_ptr = xfopen (nameoffile + 1, fopen_mode);
242 if (*f_ptr) {
243 recorder_record_input (nameoffile + 1);
245 /* If we just opened a TFM file, we have to read the first
246 byte, to pretend we're Pascal. See tex.ch and mp.ch.
247 Ditto for the ocp/ofm Omega file formats. */
248 if (filefmt == kpse_tfm_format) {
249 tfmtemp = getc (*f_ptr);
250 /* We intentionally do not check for EOF here, i.e., an
251 empty TFM file. TeX will see the 255 byte and complain
252 about a bad TFM file, which is what we want. */
253 } else if (filefmt == kpse_ocp_format) {
254 ocptemp = getc (*f_ptr);
255 } else if (filefmt == kpse_ofm_format) {
256 tfmtemp = getc (*f_ptr);
260 return *f_ptr != NULL;
263 /* Open an output file F either in the current directory or in
264 $TEXMFOUTPUT/F, if the environment variable `TEXMFOUTPUT' exists.
265 (Actually, this also applies to the BibTeX and MetaPost output files,
266 but `TEXMFMPBIBOUTPUT' was just too long.) The filename is in the
267 global `nameoffile' + 1. We return whether or not the open
268 succeeded. If it did, `nameoffile' is reset to the name opened if
269 necessary, and `namelength' to its length. */
271 boolean
272 open_output (FILE **f_ptr, const_string fopen_mode)
274 string fname;
275 boolean absolute = kpse_absolute_p(nameoffile+1, false);
277 /* If we have an explicit output directory, use it. */
278 if (output_directory && !absolute) {
279 fname = concat3(output_directory, DIR_SEP_STRING, nameoffile + 1);
280 } else {
281 fname = nameoffile + 1;
284 /* Is the filename openable as given? */
285 *f_ptr = fopen (fname, fopen_mode);
287 if (!*f_ptr) {
288 /* Can't open as given. Try the envvar. */
289 string texmfoutput = kpse_var_value("TEXMFOUTPUT");
291 if (texmfoutput && *texmfoutput && !absolute) {
292 if (fname != nameoffile + 1)
293 free(fname);
294 fname = concat3(texmfoutput, DIR_SEP_STRING, nameoffile+1);
295 *f_ptr = fopen(fname, fopen_mode);
298 /* If this succeeded, change nameoffile accordingly. */
299 if (*f_ptr) {
300 if (fname != nameoffile + 1) {
301 free (nameoffile);
302 namelength = strlen (fname);
303 nameoffile = xmalloc (namelength + 2);
304 strcpy (nameoffile + 1, fname);
306 recorder_record_output (fname);
308 if (fname != nameoffile +1)
309 free(fname);
310 return *f_ptr != NULL;
313 /* Close F. */
315 void
316 close_file (FILE *f)
318 /* If F is null, just return. bad_pool might close a file that has
319 never been opened. */
320 if (!f)
321 return;
323 #ifdef PTEX
324 #ifdef WIN32
325 clear_infile_enc (f);
326 if (fclose (f) == EOF) {
327 #else
328 if (nkf_close (f) == EOF) {
329 #endif
330 #else
331 if (fclose (f) == EOF) {
332 #endif
333 /* It's not always nameoffile, we might have opened something else
334 in the meantime. And it's not easy to extract the filenames out
335 of the pool array. So just punt on the filename. Sigh. This
336 probably doesn't need to be a fatal error. */
337 perror ("fclose");