diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/web2c/lib/openclose.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/lib/openclose.c')
-rw-r--r-- | Build/source/texk/web2c/lib/openclose.c | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/lib/openclose.c b/Build/source/texk/web2c/lib/openclose.c new file mode 100644 index 00000000000..6e542d247fa --- /dev/null +++ b/Build/source/texk/web2c/lib/openclose.c @@ -0,0 +1,251 @@ +/* openclose.c: open and close files for TeX, Metafont, and BibTeX. + + Written 1995, 96 Karl Berry. Public domain. */ + +#include "config.h" +#include <kpathsea/c-pathch.h> +#include <kpathsea/tex-file.h> +#include <kpathsea/variable.h> +#include <kpathsea/absolute.h> + +/* The globals we use to communicate. */ +extern string nameoffile; +extern unsigned namelength; +/* For "file:line:error style error messages. */ +extern string fullnameoffile; +/* For the filename recorder. */ +extern boolean recorder_enabled; +/* For the output-dir option. */ +extern string output_directory; + +/* Define some variables. */ +string fullnameoffile; /* Defaults to NULL. */ +static string recorder_name; /* Defaults to NULL. */ +static FILE *recorder_file; /* Defaults to NULL. */ +boolean recorder_enabled; /* Defaults to false. */ +string output_directory; /* Defaults to NULL. */ + +/* For TeX and MetaPost. See below. Always defined so we don't have to + #ifdef, and thus this file can be compiled once and go in lib.a. */ +int tfmtemp; +int ocptemp; +int texinputtype; + +/* Helpers for the filename recorder... */ +/* Start the recorder */ +static void +recorder_start() +{ + /* Alas, while we might want to use mkstemp it is not portable. + So we have to be content with using a default name... */ + string cwd; + recorder_name = (string)xmalloc(strlen(kpse_program_name)+5); + strcpy(recorder_name, kpse_program_name); + strcat(recorder_name, ".fls"); + recorder_file = xfopen(recorder_name, FOPEN_W_MODE); + cwd = xgetcwd(); + fprintf(recorder_file, "PWD %s\n", cwd); + free(cwd); +} + +/* Change the name of the recorder file. */ +void +recorder_change_filename P1C(string, new_name) +{ + if (!recorder_file) + return; + rename(recorder_name, new_name); + free(recorder_name); + recorder_name = xstrdup(new_name); +} + +/* Open an input file F, using the kpathsea format FILEFMT and passing + FOPEN_MODE to fopen. The filename is in `nameoffile+1'. We return + whether or not the open succeeded. If it did, `nameoffile' is set to + the full filename opened, and `namelength' to its length. */ + +boolean +open_input P3C(FILE **, f_ptr, int, filefmt, const_string, fopen_mode) +{ + string fname = NULL; +#ifdef FUNNY_CORE_DUMP + /* This only applies if a preloaded TeX/Metafont is being made; + it allows automatic creation of the core dump (typing ^\ loses + since that requires manual intervention). */ + if ((filefmt == kpse_tex_format || filefmt == kpse_mf_format + || filefmt == kpse_mp_format) + && STREQ (nameoffile + 1, "HackyInputFileNameForCoreDump.tex")) + funny_core_dump (); +#endif + + /* We havent found anything yet. */ + *f_ptr = NULL; + if (fullnameoffile) + free(fullnameoffile); + fullnameoffile = NULL; + + /* Handle -output-directory. + FIXME: We assume that it is OK to look here first. Possibly it + would be better to replace lookups in "." with lookups in the + output_directory followed by "." but to do this requires much more + invasive surgery in libkpathsea. */ + /* FIXME: This code assumes that the filename of the input file is + not an absolute filename. */ + if (output_directory) { + fname = concat3(output_directory, DIR_SEP_STRING, nameoffile + 1); + *f_ptr = fopen(fname, fopen_mode); + if (*f_ptr) { + free(nameoffile); + namelength = strlen (fname); + nameoffile = (string)xmalloc (namelength + 2); + strcpy (nameoffile + 1, fname); + fullnameoffile = fname; + } else { + free(fname); + } + } + + /* No file means do the normal search. */ + if (*f_ptr == NULL) { + /* A negative FILEFMT means don't use a path. */ + if (filefmt < 0) { + /* no_file_path, for BibTeX .aux files and MetaPost things. */ + *f_ptr = fopen(nameoffile + 1, fopen_mode); + /* FIXME... fullnameoffile = xstrdup(nameoffile + 1); */ + } else { + /* The only exception to `must_exist' being true is \openin, for + which we set `tex_input_type' to 0 in the change file. */ + /* According to the pdfTeX people, pounding the disk for .vf files + is overkill as well. A more general solution would be nice. */ + boolean must_exist = (filefmt != kpse_tex_format || texinputtype) + && (filefmt != kpse_vf_format); + fname = kpse_find_file (nameoffile + 1, + (kpse_file_format_type)filefmt, + must_exist); + if (fname) { + fullnameoffile = xstrdup(fname); + /* If we found the file in the current directory, don't leave + the `./' at the beginning of `nameoffile', since it looks + dumb when `tex foo' says `(./foo.tex ... )'. On the other + hand, if the user said `tex ./foo', and that's what we + opened, then keep it -- the user specified it, so we + shouldn't remove it. */ + if (fname[0] == '.' && IS_DIR_SEP (fname[1]) + && (nameoffile[1] != '.' || !IS_DIR_SEP (nameoffile[2]))) + { + unsigned i = 0; + while (fname[i + 2] != 0) { + fname[i] = fname[i + 2]; + i++; + } + fname[i] = 0; + } + + /* kpse_find_file always returns a new string. */ + free (nameoffile); + namelength = strlen (fname); + nameoffile = (string)xmalloc (namelength + 2); + strcpy (nameoffile + 1, fname); + free (fname); + + /* This fopen is not allowed to fail. */ + *f_ptr = xfopen (nameoffile + 1, fopen_mode); + } + } + } + + if (*f_ptr) { + if (recorder_enabled) { + if (!recorder_file) + recorder_start(); + fprintf(recorder_file, "INPUT %s\n", nameoffile + 1); + } + + /* If we just opened a TFM file, we have to read the first + byte, to pretend we're Pascal. See tex.ch and mp.ch. + Ditto for the ocp/ofm Omega file formats. */ + if (filefmt == kpse_tfm_format) { + tfmtemp = getc (*f_ptr); + /* We intentionally do not check for EOF here, i.e., an + empty TFM file. TeX will see the 255 byte and complain + about a bad TFM file, which is what we want. */ + } else if (filefmt == kpse_ocp_format) { + ocptemp = getc (*f_ptr); + } else if (filefmt == kpse_ofm_format) { + tfmtemp = getc (*f_ptr); + } + } + + return *f_ptr != NULL; +} + +/* Open an output file F either in the current directory or in + $TEXMFOUTPUT/F, if the environment variable `TEXMFOUTPUT' exists. + (Actually, this also applies to the BibTeX and MetaPost output files, + but `TEXMFMPBIBOUTPUT' was just too long.) The filename is in the + global `nameoffile' + 1. We return whether or not the open + succeeded. If it did, `nameoffile' is reset to the name opened if + necessary, and `namelength' to its length. */ + +boolean +open_output P2C(FILE **, f_ptr, const_string, fopen_mode) +{ + string fname; + boolean absolute = kpse_absolute_p(nameoffile+1, false); + + /* If we have an explicit output directory, use it. */ + if (output_directory && !absolute) { + fname = concat3(output_directory, DIR_SEP_STRING, nameoffile + 1); + } else { + fname = nameoffile + 1; + } + + /* Is the filename openable as given? */ + *f_ptr = fopen (fname, fopen_mode); + + if (!*f_ptr) { + /* Can't open as given. Try the envvar. */ + string texmfoutput = kpse_var_value("TEXMFOUTPUT"); + + if (texmfoutput && *texmfoutput && !absolute) { + string fname = concat3(texmfoutput, DIR_SEP_STRING, nameoffile+1); + *f_ptr = fopen(fname, fopen_mode); + } + } + /* If this succeeded, change nameoffile accordingly. */ + if (*f_ptr) { + if (fname != nameoffile + 1) { + free (nameoffile); + namelength = strlen (fname); + nameoffile = (string)xmalloc (namelength + 2); + strcpy (nameoffile + 1, fname); + } + if (recorder_enabled) { + if (!recorder_file) + recorder_start(); + fprintf(recorder_file, "OUTPUT %s\n", fname); + } + } + if (fname != nameoffile +1) + free(fname); + return *f_ptr != NULL; +} + +/* Close F. */ + +void +aclose P1C(FILE *, f) +{ + /* If F is null, just return. bad_pool might close a file that has + never been opened. */ + if (!f) + return; + + if (fclose (f) == EOF) { + /* It's not always nameoffile, we might have opened something else + in the meantime. And it's not easy to extract the filenames out + of the pool array. So just punt on the filename. Sigh. This + probably doesn't need to be a fatal error. */ + perror ("fclose"); + } +} |