2999
|
1 /* cnf.c: read config files. |
|
2 |
|
3 Copyright (C) 1994, 95, 96, 97 Karl Berry. |
|
4 |
|
5 This library is free software; you can redistribute it and/or |
|
6 modify it under the terms of the GNU Library General Public |
|
7 License as published by the Free Software Foundation; either |
|
8 version 2 of the License, or (at your option) any later version. |
|
9 |
|
10 This library is distributed in the hope that it will be useful, |
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 Library General Public License for more details. |
|
14 |
|
15 You should have received a copy of the GNU Library General Public |
|
16 License along with this library; if not, write to the Free Software |
|
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|
18 |
|
19 #include <kpathsea/config.h> |
|
20 #include <kpathsea/c-fopen.h> |
|
21 #include <kpathsea/c-ctype.h> |
|
22 #include <kpathsea/cnf.h> |
|
23 #include <kpathsea/db.h> |
|
24 #include <kpathsea/hash.h> |
|
25 #include <kpathsea/line.h> |
|
26 #include <kpathsea/paths.h> |
|
27 #include <kpathsea/pathsearch.h> |
|
28 #include <kpathsea/progname.h> |
|
29 #include <kpathsea/tex-file.h> |
|
30 #include <kpathsea/variable.h> |
|
31 |
|
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. */ |
|
39 static hash_table_type cnf_hash; |
|
40 #define CNF_HASH_SIZE 751 |
|
41 #define CNF_NAME "texmf.cnf" |
|
42 |
|
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. */ |
|
48 |
|
49 static void |
|
50 do_line P1C(string, line) |
|
51 { |
|
52 unsigned len; |
|
53 string start; |
|
54 string value, var; |
|
55 string prog = NULL; |
|
56 |
|
57 /* Skip leading whitespace. */ |
|
58 while (ISSPACE (*line)) |
|
59 line++; |
|
60 |
|
61 /* More to do only if we have non-comment material left. */ |
|
62 if (*line == 0 || *line == '%' || *line == '#') |
|
63 return; |
|
64 |
|
65 /* The variable name is everything up to the next space or = or `.'. */ |
|
66 start = line; |
|
67 while (!ISSPACE (*line) && *line != '=' && *line != '.') |
|
68 line++; |
|
69 |
|
70 /* `line' is now one character past the end of the variable name. */ |
|
71 len = line - start; |
|
72 var = xmalloc (len + 1); |
|
73 strncpy (var, start, len); |
|
74 var[len] = 0; |
|
75 |
|
76 /* If the variable is qualified with a program name, we might be |
|
77 ignoring it. */ |
|
78 while (ISSPACE (*line)) |
|
79 line++; |
|
80 if (*line == '.') { |
|
81 /* Skip spaces, then everything up to the next space or =. */ |
|
82 line++; |
|
83 while (ISSPACE (*line)) |
|
84 line++; |
|
85 start = line; |
|
86 while (!ISSPACE (*line) && *line != '=') |
|
87 line++; |
|
88 |
|
89 /* It's annoying to repeat all this, but making a tokenizing |
|
90 subroutine would be just as long and annoying. */ |
|
91 len = line - start; |
|
92 prog = xmalloc (len + 1); |
|
93 strncpy (prog, start, len); |
|
94 prog[len] = 0; |
|
95 |
|
96 /* If we are running `prog', fine; otherwise, we're done. */ |
3172
|
97 assert (kpse_program_name); |
|
98 if (!FILESTRCASEEQ (prog, kpse_program_name)) { |
2999
|
99 free (prog); |
|
100 free (var); |
|
101 return; |
|
102 } |
|
103 } |
|
104 |
|
105 /* Skip whitespace, an optional =, more whitespace. */ |
|
106 while (ISSPACE (*line)) |
|
107 line++; |
|
108 if (*line == '=') { |
|
109 line++; |
|
110 while (ISSPACE (*line)) |
|
111 line++; |
|
112 } |
|
113 |
|
114 /* The value is whatever remains. Remove trailing whitespace. */ |
|
115 start = line; |
|
116 len = strlen (start); |
|
117 while (ISSPACE (start[len - 1]) && len > 0) |
|
118 len--; |
|
119 |
|
120 value = xmalloc (len + 1); |
|
121 strncpy (value, start, len); |
|
122 value[len] = 0; |
|
123 |
|
124 /* Suppose we want to write a single texmf.cnf that can be used under |
|
125 both NT and Unix. This is feasible except for the path separators |
|
126 : on Unix, ; on NT. We can't switch NT to allowing :'s, since : |
|
127 is the drive separator. So we switch Unix to allowing ;'s. On the |
|
128 other hand, we don't want to change IS_ENV_SEP and all the rest. |
|
129 |
|
130 So, simply translate all ;'s in the path |
|
131 values to :'s if we are a Unix binary. (Fortunately we don't use ; |
|
132 in other kinds of texmf.cnf values.) |
|
133 |
|
134 If you really want to put ; in your filenames, add |
|
135 -DALLOW_SEMICOLON_IN_FILENAMES. (And there's no way to get :'s in |
|
136 your filenames, sorry.) */ |
|
137 |
|
138 /* gcc -ansi doesn't predefine `unix', since ANSI forbids it. And AIX |
|
139 generally doesn't predefine unix, who knows why. */ |
|
140 #ifndef unix |
|
141 #if defined (__unix__) || defined (_AIX) |
|
142 #define unix |
|
143 #endif |
|
144 #endif |
|
145 |
3172
|
146 /* DJGPP defines `unix' (for portability), but generates MSDOS programs. */ |
|
147 #ifndef __DJGPP__ |
|
148 #if !defined (ALLOW_SEMICOLON_IN_FILENAMES) && defined (unix) |
2999
|
149 { |
|
150 string loc; |
|
151 for (loc = value; *loc; loc++) { |
|
152 if (*loc == ';') |
|
153 *loc = ':'; |
|
154 } |
|
155 } |
|
156 #endif |
3172
|
157 #endif |
2999
|
158 |
|
159 /* We want TEXINPUTS.prog to override plain TEXINPUTS. The simplest |
|
160 way is to put both in the hash table (so we don't have to write |
|
161 hash_delete and hash_replace, and keep track of values' sources), |
|
162 and then look up the .prog version first in `kpse_cnf_get'. */ |
|
163 if (prog) { |
|
164 string lhs = concat3 (var, ".", prog); |
|
165 free (var); |
|
166 free (prog); |
|
167 var = lhs; |
|
168 } |
|
169 hash_insert (&cnf_hash, var, value); |
|
170 |
|
171 /* We could check that anything remaining is preceded by a comment |
|
172 character, but let's not bother. */ |
|
173 } |
|
174 |
|
175 /* Read all the configuration files in the path. */ |
|
176 |
|
177 static void |
|
178 read_all_cnf P1H(void) |
|
179 { |
|
180 string *cnf_files; |
|
181 const_string cnf_path = kpse_init_format (kpse_cnf_format); |
|
182 |
|
183 cnf_hash = hash_create (CNF_HASH_SIZE); |
|
184 |
|
185 for (cnf_files = kpse_all_path_search (cnf_path, CNF_NAME); |
|
186 cnf_files && *cnf_files; cnf_files++) { |
|
187 string line; |
|
188 string cnf_filename = *cnf_files; |
|
189 FILE *cnf_file = xfopen (cnf_filename, FOPEN_R_MODE); |
|
190 |
|
191 while ((line = read_line (cnf_file)) != NULL) { |
|
192 unsigned len = strlen (line); |
|
193 /* Concatenate consecutive lines that end with \. */ |
|
194 while (len > 0 && line[len - 1] == '\\') { |
|
195 string next_line = read_line (cnf_file); |
|
196 line[len - 1] = 0; |
|
197 if (!next_line) { |
|
198 WARNING1 ("%s: Last line ends with \\", cnf_filename); |
|
199 } else { |
|
200 string new_line; |
|
201 new_line = concat (line, next_line); |
|
202 free (line); |
|
203 line = new_line; |
|
204 len = strlen (line); |
|
205 } |
|
206 } |
|
207 |
|
208 do_line (line); |
|
209 free (line); |
|
210 } |
|
211 |
|
212 xfclose (cnf_file, cnf_filename); |
|
213 } |
|
214 } |
|
215 |
|
216 /* Read the cnf files on the first call. Return the first value in the |
|
217 returned list -- this will be from the last-read cnf file. */ |
|
218 |
|
219 string |
|
220 kpse_cnf_get P1C(const_string, name) |
|
221 { |
|
222 string ret, try; |
|
223 string *ret_list; |
|
224 static boolean doing_cnf_init = false; |
|
225 |
|
226 /* When we expand the compile-time value for DEFAULT_TEXMFCNF, |
|
227 we end up needing the value for TETEXDIR and other variables, |
|
228 so kpse_var_expand ends up calling us again. No good. */ |
|
229 if (doing_cnf_init) |
|
230 return NULL; |
|
231 |
|
232 if (cnf_hash.size == 0) { |
|
233 doing_cnf_init = true; |
|
234 read_all_cnf (); |
|
235 doing_cnf_init = false; |
|
236 |
|
237 /* Here's a pleasant kludge: Since `kpse_init_dbs' recursively calls |
|
238 us, we must call it from outside a `kpse_path_element' loop |
|
239 (namely, the one in `read_all_cnf' above): `kpse_path_element' is |
|
240 not reentrant. */ |
|
241 kpse_init_db (); |
|
242 } |
|
243 |
3172
|
244 /* First look up NAME.`kpse_program_name', then NAME. */ |
|
245 assert (kpse_program_name); |
|
246 try = concat3 (name, ".", kpse_program_name); |
2999
|
247 ret_list = hash_lookup (cnf_hash, try); |
|
248 if (ret_list) { |
|
249 ret = *ret_list; |
|
250 free (ret_list); |
|
251 } else { |
|
252 free (try); |
|
253 ret_list = hash_lookup (cnf_hash, name); |
|
254 if (ret_list) { |
|
255 ret = *ret_list; |
|
256 free (ret_list); |
|
257 } else { |
|
258 ret = NULL; |
|
259 } |
|
260 } |
|
261 |
|
262 return ret; |
|
263 |
|
264 } |