/[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 185 - (show annotations)
Fri Jan 9 22:20:03 2004 UTC (16 years, 4 months ago) by frodo
File MIME type: text/plain
File size: 11308 byte(s)
(Frodo) Psiconv program rewrite start
  * Add support for different encodings
  * Restructure some things
  * Only ASCII support at the moment

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

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