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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.168  
changed lines
  Added in v.220

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