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/kpathsea/cnf.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/kpathsea/cnf.c')
-rw-r--r-- | Build/source/texk/kpathsea/cnf.c | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/Build/source/texk/kpathsea/cnf.c b/Build/source/texk/kpathsea/cnf.c new file mode 100644 index 00000000000..982495bde48 --- /dev/null +++ b/Build/source/texk/kpathsea/cnf.c @@ -0,0 +1,251 @@ +/* cnf.c: read config files. + + Copyright 1997-2005 Olaf Weber. + Copyright 1994, 95, 96, 97 Karl Berry. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include <kpathsea/config.h> +#include <kpathsea/c-fopen.h> +#include <kpathsea/c-ctype.h> +#include <kpathsea/c-pathch.h> +#include <kpathsea/cnf.h> +#include <kpathsea/db.h> +#include <kpathsea/hash.h> +#include <kpathsea/line.h> +#include <kpathsea/paths.h> +#include <kpathsea/pathsearch.h> +#include <kpathsea/progname.h> +#include <kpathsea/tex-file.h> +#include <kpathsea/variable.h> + +/* By using our own hash table, instead of the environment, we + complicate variable expansion (because we have to look in two + places), but we don't bang so much on the system. DOS and System V + have very limited environment space. Also, this way + `kpse_init_format' can distinguish between values originating from + the cnf file and ones from environment variables, which can be useful + for users trying to figure out what's going on. */ +static hash_table_type cnf_hash; +#define CNF_HASH_SIZE 751 +#define CNF_NAME "texmf.cnf" + +/* Do a single line in a cnf file: if it's blank or a comment, skip it. + Otherwise, parse <variable>[.<program>] [=] <value>. Do + this even if the <variable> is already set in the environment, since + the envvalue might contain a trailing :, in which case we'll be + looking for the cnf value. */ + +static void +do_line P1C(string, line) +{ + unsigned len; + string start; + string value, var; + string prog = NULL; + + /* Skip leading whitespace. */ + while (ISSPACE (*line)) + line++; + + /* More to do only if we have non-comment material left. */ + if (*line == 0 || *line == '%' || *line == '#') + return; + + /* The variable name is everything up to the next space or = or `.'. */ + start = line; + while (!ISSPACE (*line) && *line != '=' && *line != '.') + line++; + + /* `line' is now one character past the end of the variable name. */ + len = line - start; + var = (string)xmalloc (len + 1); + strncpy (var, start, len); + var[len] = 0; + + /* If the variable is qualified with a program name, find out which. */ + while (ISSPACE (*line)) + line++; + if (*line == '.') { + /* Skip spaces, then everything up to the next space or =. */ + line++; + while (ISSPACE (*line)) + line++; + start = line; + while (!ISSPACE (*line) && *line != '=') + line++; + + /* It's annoying to repeat all this, but making a tokenizing + subroutine would be just as long and annoying. */ + len = line - start; + prog = (string)xmalloc (len + 1); + strncpy (prog, start, len); + prog[len] = 0; + } + + /* Skip whitespace, an optional =, more whitespace. */ + while (ISSPACE (*line)) + line++; + if (*line == '=') { + line++; + while (ISSPACE (*line)) + line++; + } + + /* The value is whatever remains. Remove trailing whitespace. */ + start = line; + len = strlen (start); + while (len > 0 && ISSPACE (start[len - 1])) + len--; + + value = (string)xmalloc (len + 1); + strncpy (value, start, len); + value[len] = 0; + + /* Suppose we want to write a single texmf.cnf that can be used under + both NT and Unix. This is feasible except for the path separators + : on Unix, ; on NT. We can't switch NT to allowing :'s, since : + is the drive separator. So we switch Unix to allowing ;'s. On the + other hand, we don't want to change IS_ENV_SEP and all the rest. + + So, simply translate all ;'s in the path + values to :'s if we are a Unix binary. (Fortunately we don't use ; + in other kinds of texmf.cnf values.) */ + + if (IS_ENV_SEP(':')) { + string loc; + for (loc = value; *loc; loc++) { + if (*loc == ';') + *loc = ':'; + } + } + + /* We want TEXINPUTS.prog to override plain TEXINPUTS. The simplest + way is to put both in the hash table (so we don't have to write + hash_delete and hash_replace, and keep track of values' sources), + and then look up the .prog version first in `kpse_cnf_get'. */ + if (prog) { + string lhs = concat3 (var, ".", prog); + free (var); + free (prog); + var = lhs; + } + hash_insert (&cnf_hash, var, value); + + /* We could check that anything remaining is preceded by a comment + character, but let's not bother. */ +} + +/* Read all the configuration files in the path. */ + +static void +read_all_cnf P1H(void) +{ + string *cnf_files; + string *cnf; + const_string cnf_path = kpse_init_format (kpse_cnf_format); + + cnf_hash = hash_create (CNF_HASH_SIZE); + + cnf_files = kpse_all_path_search (cnf_path, CNF_NAME); + if (cnf_files) { + for (cnf = cnf_files; *cnf; cnf++) { + string line; + FILE *cnf_file = xfopen (*cnf, FOPEN_R_MODE); + + while ((line = read_line (cnf_file)) != NULL) { + unsigned len = strlen (line); + /* Strip trailing spaces. */ + while (len > 0 && ISSPACE(line[len-1])) { + line[len - 1] = 0; + --len; + } + /* Concatenate consecutive lines that end with \. */ + while (len > 0 && line[len - 1] == '\\') { + string next_line = read_line (cnf_file); + line[len - 1] = 0; + if (!next_line) { + WARNING1 ("%s: Last line ends with \\", *cnf); + } else { + string new_line; + new_line = concat (line, next_line); + free (line); + line = new_line; + len = strlen (line); + } + } + + do_line (line); + free (line); + } + + xfclose (cnf_file, *cnf); + free (*cnf); + } + free (cnf_files); + } +} + +/* Read the cnf files on the first call. Return the first value in the + returned list -- this will be from the last-read cnf file. */ + +string +kpse_cnf_get P1C(const_string, name) +{ + string ret, ctry; + string *ret_list; + static boolean doing_cnf_init = false; + + /* When we expand the compile-time value for DEFAULT_TEXMFCNF, + we end up needing the value for TETEXDIR and other variables, + so kpse_var_expand ends up calling us again. No good. */ + if (doing_cnf_init) + return NULL; + + if (cnf_hash.size == 0) { + doing_cnf_init = true; + read_all_cnf (); + doing_cnf_init = false; + + /* Here's a pleasant kludge: Since `kpse_init_dbs' recursively calls + us, we must call it from outside a `kpse_path_element' loop + (namely, the one in `read_all_cnf' above): `kpse_path_element' is + not reentrant. */ + kpse_init_db (); + } + + /* First look up NAME.`kpse_program_name', then NAME. */ + assert (kpse_program_name); + ctry = concat3 (name, ".", kpse_program_name); + ret_list = hash_lookup (cnf_hash, ctry); + free (ctry); + if (ret_list) { + ret = *ret_list; + free (ret_list); + } else { + ret_list = hash_lookup (cnf_hash, name); + if (ret_list) { + ret = *ret_list; + free (ret_list); + } else { + ret = NULL; + } + } + + return ret; + +} |