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