beta-0.89.2
[luatex.git] / source / texk / kpathsea / cnf.c
blob578e42a5a3915eccf4eb31145c799ed51ce3328e
1 /* cnf.c: read config files.
3 Copyright 1994, 1995, 1996, 1997, 2008, 2009, 2011, 2012 Karl Berry.
4 Copyright 1997-2005 Olaf Weber.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with this library; if not, see <http://www.gnu.org/licenses/>. */
19 #include <kpathsea/config.h>
20 #include <kpathsea/c-fopen.h>
21 #include <kpathsea/c-ctype.h>
22 #include <kpathsea/c-pathch.h>
23 #include <kpathsea/cnf.h>
24 #include <kpathsea/db.h>
25 #include <kpathsea/hash.h>
26 #include <kpathsea/line.h>
27 #include <kpathsea/paths.h>
28 #include <kpathsea/pathsearch.h>
29 #include <kpathsea/tex-file.h>
30 #include <kpathsea/variable.h>
32 /* By using our own hash table, instead of the environment, we
33 complicate variable expansion (because we have to look in two
34 places), but we don't bang so much on the system. DOS and System V
35 have very limited environment space. Also, this way
36 `kpse_init_format' can distinguish between values originating from
37 the cnf file and ones from environment variables, which can be useful
38 for users trying to figure out what's going on. */
40 #define CNF_HASH_SIZE 751
41 #define CNF_NAME "texmf.cnf"
43 /* Do a single line in a cnf file: if it's blank or a comment, skip it.
44 Otherwise, parse <variable>[.<program>] [=] <value>. Do
45 this even if the <variable> is already set in the environment, since
46 the envvalue might contain a trailing :, in which case we'll be
47 looking for the cnf value. */
49 static void
50 do_line (kpathsea kpse, string line)
52 unsigned len;
53 string start;
54 string value, var;
55 string prog = NULL;
57 /* Skip leading whitespace. */
58 while (ISSPACE (*line))
59 line++;
61 /* More to do only if we have non-comment material left. */
62 if (*line == 0 || *line == '%' || *line == '#')
63 return;
65 /* Remove trailing comment: a % or # preceded by whitespace. Also
66 remove any whitespace before that. For example, the value for
67 foo = a#b %something
68 is a#b. */
69 value = line + strlen (line) - 1; /* start at end of line */
70 while (value > line) {
71 if (*value == '%' || *value == '#') {
72 value--; /* move before comment char */
73 while (ISSPACE (*value))
74 *value-- = 0; /* wipe out as much preceding whitespace
75 continue; (and comment) as we find */
77 value--; /* move before the new null byte */
80 /* The variable name is everything up to the next space or = or `.'. */
81 start = line;
82 while (!ISSPACE (*line) && *line != '=' && *line != '.')
83 line++;
85 /* `line' is now one character past the end of the variable name. */
86 len = line - start;
87 var = (string)xmalloc (len + 1);
88 strncpy (var, start, len);
89 var[len] = 0;
91 /* If the variable is qualified with a program name, find out which. */
92 while (ISSPACE (*line))
93 line++;
94 if (*line == '.') {
95 /* Skip spaces, then everything up to the next space or =. */
96 line++;
97 while (ISSPACE (*line))
98 line++;
99 start = line;
100 while (!ISSPACE (*line) && *line != '=')
101 line++;
103 /* It's annoying to repeat all this, but making a tokenizing
104 subroutine would be just as long and annoying. */
105 len = line - start;
106 prog = (string)xmalloc (len + 1);
107 strncpy (prog, start, len);
108 prog[len] = 0;
111 /* Skip whitespace, an optional =, more whitespace. */
112 while (ISSPACE (*line))
113 line++;
114 if (*line == '=') {
115 line++;
116 while (ISSPACE (*line))
117 line++;
120 /* The value is whatever remains. Remove trailing whitespace. */
121 start = line;
122 len = strlen (start);
123 while (len > 0 && ISSPACE (start[len - 1]))
124 len--;
126 value = (string)xmalloc (len + 1);
127 strncpy (value, start, len);
128 value[len] = 0;
130 /* Suppose we want to write a single texmf.cnf that can be used under
131 both NT and Unix. This is feasible except for the path separators
132 : on Unix, ; on NT. We can't switch NT to allowing :'s, since :
133 is the drive separator. So we switch Unix to allowing ;'s. On the
134 other hand, we don't want to change IS_ENV_SEP and all the rest.
136 So, simply translate all ;'s in the path
137 values to :'s if we are a Unix binary. (Fortunately we don't use ;
138 in other kinds of texmf.cnf values.) */
140 if (IS_ENV_SEP(':')) {
141 string loc;
142 for (loc = value; *loc; loc++) {
143 if (*loc == ';')
144 *loc = ':';
148 /* We want TEXINPUTS.prog to override plain TEXINPUTS. The simplest
149 way is to put both in the hash table (so we don't have to write
150 hash_delete and hash_replace, and keep track of values' sources),
151 and then look up the .prog version first in `kpse_cnf_get'. */
152 if (prog) {
153 string lhs = concat3 (var, ".", prog);
154 free (var);
155 free (prog);
156 var = lhs;
158 hash_insert (&(kpse->cnf_hash), var, value);
160 /* We could check that anything remaining is preceded by a comment
161 character, but let's not bother. */
164 /* Read all the configuration files in the path. */
166 static void
167 read_all_cnf (kpathsea kpse)
169 string *cnf_files;
170 string *cnf;
171 const_string cnf_path = kpathsea_init_format (kpse, kpse_cnf_format);
173 kpse->cnf_hash = hash_create (CNF_HASH_SIZE);
175 cnf_files = kpathsea_all_path_search (kpse, cnf_path, CNF_NAME);
176 if (cnf_files && *cnf_files) {
177 for (cnf = cnf_files; *cnf; cnf++) {
178 string line;
179 FILE *cnf_file = xfopen (*cnf, FOPEN_R_MODE);
180 if (kpse->record_input)
181 kpse->record_input (*cnf);
183 while ((line = read_line (cnf_file)) != NULL) {
184 unsigned len = strlen (line);
185 /* Strip trailing spaces. */
186 while (len > 0 && ISSPACE(line[len-1])) {
187 line[len - 1] = 0;
188 --len;
190 /* Concatenate consecutive lines that end with \. */
191 while (len > 0 && line[len - 1] == '\\') {
192 string next_line = read_line (cnf_file);
193 line[len - 1] = 0;
194 if (!next_line) {
195 WARNING1 ("kpathsea: %s: Last line of file ends with \\", *cnf);
196 } else {
197 string new_line;
198 new_line = concat (line, next_line);
199 free (line);
200 line = new_line;
201 len = strlen (line);
205 do_line (kpse, line);
206 free (line);
209 xfclose (cnf_file, *cnf);
210 free (*cnf);
212 free (cnf_files);
213 } else {
214 string warn = getenv ("KPATHSEA_WARNING");
215 if (!(warn && STREQ (warn, "0"))) {
216 WARNING1
217 ("kpathsea: configuration file texmf.cnf not found in these directories: %s",
218 cnf_path);
223 /* Read the cnf files on the first call. Return the first value in the
224 returned list -- this will be from the last-read cnf file. */
226 const_string
227 kpathsea_cnf_get (kpathsea kpse, const_string name)
229 string ctry;
230 const_string ret, *ret_list;
232 /* When we expand the compile-time value for DEFAULT_TEXMFCNF,
233 we end up needing the value for TETEXDIR and other variables,
234 so kpse_var_expand ends up calling us again. No good. Except this
235 code is not sufficient, somehow the ls-R path needs to be
236 computed when initializing the cnf path. Better to ensure that the
237 compile-time path does not contain variable references. */
238 if (kpse->doing_cnf_init)
239 return NULL;
241 if (kpse->cnf_hash.size == 0) {
242 /* Read configuration files and initialize databases. */
243 kpse->doing_cnf_init = true;
244 read_all_cnf (kpse);
245 kpse->doing_cnf_init = false;
247 /* Since `kpse_init_db' recursively calls us, we must call it from
248 outside a `kpse_path_element' loop (namely, the one in
249 `read_all_cnf' above): `kpse_path_element' is not reentrant. */
250 kpathsea_init_db (kpse);
253 /* First look up NAME.`kpse->program_name', then NAME. */
254 assert (kpse->program_name);
255 ctry = concat3 (name, ".", kpse->program_name);
256 ret_list = hash_lookup (kpse->cnf_hash, ctry);
257 free (ctry);
258 if (ret_list) {
259 ret = *ret_list;
260 free (ret_list);
261 } else {
262 ret_list = hash_lookup (kpse->cnf_hash, name);
263 if (ret_list) {
264 ret = *ret_list;
265 free (ret_list);
266 } else {
267 ret = NULL;
271 return ret;
274 #if defined(KPSE_COMPAT_API)
275 const_string
276 kpse_cnf_get (const_string name)
278 return kpathsea_cnf_get(kpse_def, name);
280 #endif