summaryrefslogtreecommitdiff
path: root/Build/source/texk/kpathsea/cnf.c
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
committerKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
commit487ca4806cc046076293cf6cc5fbba0db282bac7 (patch)
tree847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/kpathsea/cnf.c
parenta3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (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.c251
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;
+
+}