/[public]/psiconv/trunk/lib/psiconv/configuration.c
ViewVC logotype

Contents of /psiconv/trunk/lib/psiconv/configuration.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 200 - (show annotations)
Wed Feb 4 15:28:56 2004 UTC (20 years, 1 month ago) by frodo
File MIME type: text/plain
File size: 11749 byte(s)
(Frodo) Documentation updates. Removed fatals.

1 /*
2 configuration.c - Part of psiconv, a PSION 5 file formats converter
3 Copyright (c) 1999-2004 Frodo Looijaard <frodol@dds.nl>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program 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
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "config.h"
21 #include "compat.h"
22 #include "error.h"
23 #include "unicode.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <strings.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33
34 #include "configuration.h"
35
36 #ifdef DMALLOC
37 #include <dmalloc.h>
38 #endif
39
40 #ifndef CONFIGURATION_SEARCH_PATH
41 #define CONFIGURATION_SEARCH_PATH PSICONVETCDIR "/psiconv.conf:~/.psiconv.conf"
42 #endif
43 static struct psiconv_config_s default_config =
44 { PSICONV_VERB_WARN, 2, 0,0,0,psiconv_bool_false,NULL,'?' };
45
46 static void psiconv_config_parse_statement(const char *filename,
47 int linenr,
48 const char *var, int value,
49 psiconv_config *config);
50
51 static void psiconv_config_parse_line(const char *filename, int linenr,
52 const char *line, psiconv_config *config);
53
54 static void psiconv_config_parse_file(const char *filename,
55 psiconv_config *config);
56
57 psiconv_config psiconv_config_default(void)
58 {
59 psiconv_config result;
60 result = malloc(sizeof(*result));
61 *result = default_config;
62 return result;
63 }
64
65 void psiconv_config_parse_statement(const char *filename,
66 int linenr,
67 const char *var, int value,
68 psiconv_config *config)
69 {
70 int charnr;
71
72 if (!(strcasecmp(var,"verbosity"))) {
73 if ((value >= 1) && (value <= 4))
74 (*config)->verbosity = value;
75 else
76 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
77 "Verbosity should be between 1 and 5",filename,linenr);
78 } else if (!(strcasecmp(var,"color"))) {
79 if ((value == 0) || (value == 1))
80 (*config)->color = value;
81 else
82 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
83 "Color should be 0 or 1",filename,linenr);
84 } else if (!(strcasecmp(var,"colordepth"))) {
85 if ((value > 0) && (value <= 32))
86 (*config)->colordepth = value;
87 else
88 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
89 "ColorDepth should be between 1 and 32",filename,linenr);
90 } else if (!(strcasecmp(var,"redbits"))) {
91 if ((value >= 0) && (value <= 32))
92 (*config)->redbits = value;
93 else
94 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
95 "RedBits should be between 1 and 32 or 0",filename,linenr);
96 } else if (!(strcasecmp(var,"greenbits"))) {
97 if ((value >= 0) && (value <= 32))
98 (*config)->greenbits = value;
99 else
100 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
101 "GreenBits should be between 1 and 32 or 0",filename,linenr);
102 } else if (!(strcasecmp(var,"bluebits"))) {
103 if ((value >= 0) && (value <= 32))
104 (*config)->bluebits = value;
105 else
106 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
107 "BlueBits should be between 1 and 32 or 0",filename,linenr);
108 } else if (!(strcasecmp(var,"characterset"))) {
109 if ((value >= 0) && (value <= 1))
110 psiconv_unicode_select_characterset(*config,value);
111 else
112 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
113 "CharacterSet should be between 0 and 0",
114 filename,linenr);
115 } else if (!(strcasecmp(var,"unknownunicodechar"))) {
116 if ((value >= 1) && (value < 0x10000))
117 (*config)->unknown_unicode_char = value;
118 else
119 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
120 "UnknownUnicodeChar should be between 1 and 65535",
121 filename,linenr);
122 } else if (!(strcasecmp(var,"unknownepocchar"))) {
123 if ((value >= 1) && (value < 0x100))
124 (*config)->unknown_epoc_char = value;
125 else
126 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
127 "UnknownEPOCChar should be between 1 and 255",
128 filename,linenr);
129 } else if (sscanf(var,"char%d",&charnr) == strlen(var)) {
130 if ((charnr < 0) || (charnr > 255))
131 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
132 "CharXXX should have XXX between 0 and 255",
133 filename,linenr);
134 if ((value >= 1) && (value <= 0x10000))
135 (*config)->unicode_table[charnr] = value;
136 else
137 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
138 "CharXXX should be between 1 and 65535",
139 filename,linenr);
140 } else {
141 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
142 "Unknown variable %s",filename,linenr,var);
143 }
144 psiconv_debug(*config,0,0,"Configuration file %s, line %d: "
145 "Set variable %s to %d",filename,linenr,var,value);
146 }
147
148
149 void psiconv_config_parse_line(const char *filename, int linenr,
150 const char *line, psiconv_config *config)
151 {
152
153 int sovar,eovar,soval,eoval,eol;
154 char *var;
155 long val;
156
157 psiconv_debug(*config,0,0,"Going to parse line %d: %s",linenr,line);
158 sovar = 0;
159 while (line[sovar] && (line[sovar] < 32))
160 sovar ++;
161 if (!line[sovar] || line[sovar] == '#')
162 return;
163 eovar = sovar;
164 while (line[eovar] && (((line[eovar] >= 'A') && (line[eovar] <= 'Z')) ||
165 ((line[eovar] >= 'a') && (line[eovar] <= 'z'))))
166 eovar ++;
167 if (sovar == eovar) {
168 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
169 "Syntax error (no variable found)",filename,linenr);
170 return;
171 }
172 soval = eovar;
173 while (line[soval] && (line[soval] <= 32))
174 soval ++;
175 if (line[soval] != '=') {
176 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
177 "Syntax error (no = token found)",filename,linenr);
178 return;
179 }
180 soval ++;
181 while (line[soval] && (line[soval] <= 32))
182 soval ++;
183 eoval = soval;
184 while (line[eoval] && ((line[eoval] >= '0') && (line[eovar] <= '9')))
185 eoval ++;
186 if (eoval == soval) {
187 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
188 "Syntax error (no value found)",filename,linenr);
189 return;
190 }
191 if (soval - eoval > 7) {
192 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
193 "Syntax error (value too large)",filename,linenr);
194 return;
195 }
196 eol = eoval;
197 while (line[eol] && (line[eol] < 32))
198 eol ++;
199 if (line[eol]) {
200 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
201 "Syntax error (trailing garbage)",filename,linenr);
202 return;
203 }
204
205 var = malloc(eovar - sovar + 1);
206 memcpy(var,line + sovar, eovar - sovar);
207 var[eovar-sovar] = 0;
208
209 val = atol(line + soval);
210
211 psiconv_config_parse_statement(filename,linenr,var,val,config);
212 free(var);
213 }
214
215
216 void psiconv_config_parse_file(const char *filename, psiconv_config *config)
217 {
218 int file,linenr;
219 struct stat stat_buf;
220 off_t filesize,bytes_left,bytes_read,sol,eol;
221 char *filebuffer,*filebuffer_ptr;
222
223 psiconv_progress(*config,0,0,
224 "Going to access configuration file %s",filename);
225
226 /* Try to open the file; it may fail, if it does not exist for example */
227 if ((file = open(filename,O_RDONLY)) == -1)
228 goto ERROR0;
229
230 /* Read the contents of the file into filebuffer. This may fail */
231 if (fstat(file,&stat_buf)) {
232 if (close(file))
233 psiconv_error(*config,0,0,"Configuration file %s: "
234 "Couldn't close file",filename);
235 return;
236 }
237
238 filesize = stat_buf.st_size;
239 if (!(filebuffer = malloc(filesize + 1))) {
240 psiconv_error(*config,0,0,"Configuration file %s: "
241 "Out of memory error",filename);
242 goto ERROR1;
243 }
244
245 filebuffer_ptr = filebuffer;
246 bytes_left = filesize;
247 bytes_read = 1; /* Dummy for the first time through the loop */
248 while ((bytes_read > 0) && bytes_left) {
249 bytes_read = read(file,filebuffer_ptr,bytes_left);
250 if (bytes_read > 0) {
251 filebuffer_ptr += bytes_read;
252 bytes_left -= bytes_read;
253 }
254 }
255
256 /* On NFS, the first read may fail and this is not fatal */
257 if (bytes_left && (bytes_left != filesize)) {
258 psiconv_error(*config,0,0,"Configuration file %s: "
259 "Couldn't read file into memory",filename);
260 goto ERROR2;
261 }
262
263 if (close(file)) {
264 psiconv_error(*config,0,0,"Configuration file %s: "
265 "Couldn't close file",filename);
266 file = -1;
267 goto ERROR2;
268 }
269 file = -1;
270
271 psiconv_progress(*config,0,0,
272 "Going to parse configuration file %s: ",filename);
273 /* Now we walk through the file to isolate lines */
274 linenr = 0;
275 sol = 0;
276
277 while (sol < filesize) {
278 linenr ++;
279 eol = sol;
280 while ((eol < filesize) && (filebuffer[eol] != 13) &&
281 (filebuffer[eol] != 10) && (filebuffer[eol] != 0))
282 eol ++;
283
284 if ((eol < filesize) && (filebuffer[eol] == 0)) {
285 psiconv_error(*config,0,0,"Configuration file %s, line %d: "
286 "Unexpected character \000 found",filename,linenr);
287 goto ERROR2;
288 }
289 if ((eol < filesize + 1) &&
290 (((filebuffer[eol] == 13) && (filebuffer[eol+1] == 10)) ||
291 ((filebuffer[eol] == 10) && (filebuffer[eol+1] == 13)))) {
292 filebuffer[eol] = 0;
293 eol ++;
294 }
295 filebuffer[eol] = 0;
296 psiconv_config_parse_line(filename,linenr,filebuffer + sol,config);
297 sol = eol+1;
298 }
299 free(filebuffer);
300 return;
301
302 ERROR2:
303 free(filebuffer);
304 ERROR1:
305 if ((file != -1) && close(file))
306 psiconv_error(*config,0,0,"Configuration file %s: "
307 "Couldn't close file",filename);
308 ERROR0:
309 return;
310 }
311
312 void psiconv_config_read(const char *extra_config_files,
313 psiconv_config *config)
314 {
315 char *path,*pathptr,*filename,*filename_old;
316 const char *home;
317 int filename_len;
318
319 /* Make path be the complete search path, colon separated */
320 if (extra_config_files && strlen(extra_config_files)) {
321 path = malloc(strlen(CONFIGURATION_SEARCH_PATH) +
322 strlen(extra_config_files) + 2);
323 strcpy(path,CONFIGURATION_SEARCH_PATH);
324 strcat(path,":");
325 strcat(path,extra_config_files);
326 } else {
327 path = strdup(CONFIGURATION_SEARCH_PATH);
328 }
329
330 pathptr = path;
331 while (strlen(pathptr)) {
332 /* Isolate the next filename */
333 filename_len = (index(pathptr,':')?(index(pathptr,':') - pathptr):
334 strlen(pathptr));
335 filename = malloc(filename_len + 1);
336 filename = strncpy(filename,pathptr,filename_len);
337 filename[filename_len] = 0;
338 pathptr += filename_len;
339 if (strlen(pathptr))
340 pathptr ++;
341
342 /* Do ~ substitution */
343 if ((filename[0] == '~') && ((filename[1] == '/') || filename[1] == 0)) {
344 home = getenv("HOME");
345 if (home) {
346 filename_old = filename;
347 filename = malloc(strlen(filename_old) + strlen(home));
348 strcpy(filename,home);
349 strcpy(filename + strlen(filename),filename_old+1);
350 free(filename_old);
351 }
352 }
353
354 psiconv_config_parse_file(filename,config);
355 free(filename);
356 }
357 }

frodo@frodo.looijaard.name
ViewVC Help
Powered by ViewVC 1.1.26