comparison th_config.c @ 378:afbc3bfd3e03

Sync th-libs.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 03 Oct 2011 00:31:46 +0300
parents e694c02d6982
children
comparison
equal deleted inserted replaced
377:9ad157feb99a 378:afbc3bfd3e03
21 */ 21 */
22 void th_cfg_free(cfgitem_t *cfg) 22 void th_cfg_free(cfgitem_t *cfg)
23 { 23 {
24 cfgitem_t *curr = cfg; 24 cfgitem_t *curr = cfg;
25 25
26 while (curr != NULL) { 26 while (curr != NULL)
27 {
27 cfgitem_t *next = curr->next; 28 cfgitem_t *next = curr->next;
28 29
29 if (curr->type == ITEM_SECTION) 30 if (curr->type == ITEM_SECTION)
30 th_cfg_free((cfgitem_t *) curr->v.data); 31 th_cfg_free((cfgitem_t *) curr->v.data);
31 32
32 th_free(curr->name); 33 th_free(curr->name);
33 th_free(curr); 34 th_free(curr);
34 curr = next; 35 curr = next;
35 } 36 }
36 } 37 }
37 38
38 39
39 /* Allocate and add new item to configuration 40 /* Allocate and add new item to configuration
40 */ 41 */
41 static cfgitem_t *th_cfg_add(cfgitem_t **cfg, const char *name, const int type, void *data) 42 static cfgitem_t *th_cfg_add(cfgitem_t **cfg, const char *name,
43 const int type, void *data)
42 { 44 {
43 cfgitem_t *node; 45 cfgitem_t *node;
44 46
45 if (cfg == NULL) 47 if (cfg == NULL)
46 return NULL; 48 return NULL;
52 54
53 /* Set values */ 55 /* Set values */
54 node->type = type; 56 node->type = type;
55 node->v.data = data; 57 node->v.data = data;
56 node->name = th_strdup(name); 58 node->name = th_strdup(name);
57 59
58 /* Insert into linked list */ 60 /* Insert into linked list */
59 if (*cfg != NULL) { 61 if (*cfg != NULL)
62 {
60 node->prev = (*cfg)->prev; 63 node->prev = (*cfg)->prev;
61 (*cfg)->prev->next = node; 64 (*cfg)->prev->next = node;
62 (*cfg)->prev = node; 65 (*cfg)->prev = node;
63 } else { 66 }
67 else
68 {
64 *cfg = node; 69 *cfg = node;
65 node->prev = node; 70 node->prev = node;
66 } 71 }
67 node->next = NULL; 72 node->next = NULL;
68 73
70 } 75 }
71 76
72 77
73 /* Add integer type setting into give configuration 78 /* Add integer type setting into give configuration
74 */ 79 */
75 int th_cfg_add_int(cfgitem_t ** cfg, char * name, 80 int th_cfg_add_int(cfgitem_t **cfg, char *name, int *itemData, int itemDef)
76 int *itemData, int itemDef)
77 { 81 {
78 cfgitem_t *node; 82 cfgitem_t *node;
79 83
80 node = th_cfg_add(cfg, name, ITEM_INT, (void *) itemData); 84 node = th_cfg_add(cfg, name, ITEM_INT, (void *) itemData);
81 if (node == NULL) 85 if (node == NULL)
85 89
86 return 0; 90 return 0;
87 } 91 }
88 92
89 93
90 int th_cfg_add_hexvalue(cfgitem_t ** cfg, char * name, 94 int th_cfg_add_hexvalue(cfgitem_t **cfg, char *name,
91 int *itemData, int itemDef) 95 int *itemData, int itemDef)
92 { 96 {
93 cfgitem_t *node; 97 cfgitem_t *node;
94 98
95 node = th_cfg_add(cfg, name, ITEM_HEX_TRIPLET, (void *) itemData); 99 node = th_cfg_add(cfg, name, ITEM_HEX_TRIPLET, (void *) itemData);
96 if (node == NULL) 100 if (node == NULL)
102 } 106 }
103 107
104 108
105 /* Add unsigned integer type setting into give configuration 109 /* Add unsigned integer type setting into give configuration
106 */ 110 */
107 int th_cfg_add_uint(cfgitem_t ** cfg, char * name, 111 int th_cfg_add_uint(cfgitem_t **cfg, char *name,
108 unsigned int * itemData, unsigned int itemDef) 112 unsigned int *itemData, unsigned int itemDef)
109 { 113 {
110 cfgitem_t *node; 114 cfgitem_t *node;
111 115
112 node = th_cfg_add(cfg, name, ITEM_UINT, (void *) itemData); 116 node = th_cfg_add(cfg, name, ITEM_UINT, (void *) itemData);
113 if (node == NULL) 117 if (node == NULL)
119 } 123 }
120 124
121 125
122 /* Add strint type setting into given configuration 126 /* Add strint type setting into given configuration
123 */ 127 */
124 int th_cfg_add_string(cfgitem_t ** cfg, char * name, 128 int th_cfg_add_string(cfgitem_t **cfg, char *name,
125 char ** itemData, char * itemDef) 129 char **itemData, char *itemDef)
126 { 130 {
127 cfgitem_t *node; 131 cfgitem_t *node;
128 132
129 node = th_cfg_add(cfg, name, ITEM_STRING, (void *) itemData); 133 node = th_cfg_add(cfg, name, ITEM_STRING, (void *) itemData);
130 if (node == NULL) 134 if (node == NULL)
136 } 140 }
137 141
138 142
139 /* Add boolean type setting into given configuration 143 /* Add boolean type setting into given configuration
140 */ 144 */
141 int th_cfg_add_bool(cfgitem_t ** cfg, char * name, 145 int th_cfg_add_bool(cfgitem_t **cfg, char *name,
142 BOOL * itemData, BOOL itemDef) 146 BOOL *itemData, BOOL itemDef)
143 { 147 {
144 cfgitem_t *node; 148 cfgitem_t *node;
145 149
146 node = th_cfg_add(cfg, name, ITEM_BOOL, (void *) itemData); 150 node = th_cfg_add(cfg, name, ITEM_BOOL, (void *) itemData);
147 if (node == NULL) 151 if (node == NULL)
153 } 157 }
154 158
155 159
156 /* Add implicit comment 160 /* Add implicit comment
157 */ 161 */
158 int th_cfg_add_comment(cfgitem_t ** cfg, char * comment) 162 int th_cfg_add_comment(cfgitem_t **cfg, char *comment)
159 { 163 {
160 cfgitem_t *node; 164 cfgitem_t *node;
161 165
162 node = th_cfg_add(cfg, comment, ITEM_COMMENT, NULL); 166 node = th_cfg_add(cfg, comment, ITEM_COMMENT, NULL);
163 if (node == NULL) 167 if (node == NULL)
167 } 171 }
168 172
169 173
170 /* Add new section 174 /* Add new section
171 */ 175 */
172 int th_cfg_add_section(cfgitem_t ** cfg, char * name, cfgitem_t *data) 176 int th_cfg_add_section(cfgitem_t **cfg, char *name, cfgitem_t *data)
173 { 177 {
174 cfgitem_t *node; 178 cfgitem_t *node;
175 179
176 node = th_cfg_add(cfg, name, ITEM_SECTION, (void *) data); 180 node = th_cfg_add(cfg, name, ITEM_SECTION, (void *) data);
177 if (node == NULL) 181 if (node == NULL)
178 return -1; 182 return -1;
179 183
180 return 0; 184 return 0;
181 } 185 }
182 186
183 187
184 int th_cfg_add_string_list(cfgitem_t ** cfg, char * name, qlist_t **data) 188 int th_cfg_add_string_list(cfgitem_t **cfg, char *name, qlist_t **data)
185 { 189 {
186 cfgitem_t *node; 190 cfgitem_t *node;
187 191
188 if (data == NULL) 192 if (data == NULL)
189 return -5; 193 return -5;
190 194
191 node = th_cfg_add(cfg, name, ITEM_STRING_LIST, (void *) data); 195 node = th_cfg_add(cfg, name, ITEM_STRING_LIST, (void *) data);
192 if (node == NULL) 196 if (node == NULL)
193 return -1; 197 return -1;
194 198
195 return 0; 199 return 0;
196 } 200 }
197 201
198 202
199 /* Read a given file into configuration structure and variables 203 /* Read a given file into configuration structure and variables
200 */ 204 */
201 enum { 205 enum
206 {
202 PM_EOF, 207 PM_EOF,
203 PM_ERROR, 208 PM_ERROR,
204 PM_NORMAL, 209 PM_NORMAL,
205 PM_COMMENT, 210 PM_COMMENT,
206 PM_NEXT, 211 PM_NEXT,
214 }; 219 };
215 220
216 #define VADDCH(ch) if (strPos < SET_MAX_BUF) { tmpStr[strPos++] = ch; } 221 #define VADDCH(ch) if (strPos < SET_MAX_BUF) { tmpStr[strPos++] = ch; }
217 #define VISEND(ch) (ch == '\r' || ch == '\n' || ch == ';' || th_isspace(c) || ch == '#') 222 #define VISEND(ch) (ch == '\r' || ch == '\n' || ch == ';' || th_isspace(c) || ch == '#')
218 223
219 typedef struct { 224 typedef struct
225 {
220 FILE *file; 226 FILE *file;
221 char *filename; 227 char *filename;
222 size_t line; 228 size_t line;
223 } conffile_t; 229 } conffile_t;
224 230
225 231
226 static void th_cfg_error(conffile_t *f, const char *fmt, ...) 232 static void th_cfg_error(conffile_t *f, const char *fmt, ...)
227 { 233 {
228 va_list ap; 234 va_list ap;
229 va_start(ap, fmt); 235 va_start(ap, fmt);
230 fprintf(stderr, "%s: '%s', line #%d: ", th_prog_name, f->filename, (unsigned int) f->line); 236 fprintf(stderr, "%s: '%s', line #%d: ", th_prog_name, f->filename,
237 (unsigned int) f->line);
231 vfprintf(stderr, fmt, ap); 238 vfprintf(stderr, fmt, ap);
232 va_end(ap); 239 va_end(ap);
233 } 240 }
234 241
235 242
236 static int th_cfg_read_sect(conffile_t *f, cfgitem_t * cfg, int nesting) 243 static int th_cfg_read_sect(conffile_t *f, cfgitem_t *cfg, int nesting)
237 { 244 {
238 cfgitem_t *item = NULL; 245 cfgitem_t *item = NULL;
239 char tmpStr[SET_MAX_BUF + 1]; 246 char tmpStr[SET_MAX_BUF + 1];
240 size_t strPos; 247 size_t strPos;
241 int c, parseMode, prevMode, nextMode, tmpCh; 248 int c, parseMode, prevMode, nextMode, tmpCh;
247 c = -1; 254 c = -1;
248 isFound = isStart = isError = validError = FALSE; 255 isFound = isStart = isError = validError = FALSE;
249 nextMode = prevMode = parseMode = PM_NORMAL; 256 nextMode = prevMode = parseMode = PM_NORMAL;
250 257
251 /* Parse the configuration */ 258 /* Parse the configuration */
252 while (parseMode != PM_EOF && parseMode != PM_ERROR) { 259 while (parseMode != PM_EOF && parseMode != PM_ERROR)
253 if (c == -1) { 260 {
261 if (c == -1)
262 {
254 /* Get next character */ 263 /* Get next character */
255 switch (c = fgetc(f->file)) { 264 switch (c = fgetc(f->file))
265 {
256 case EOF: 266 case EOF:
257 if (parseMode != PM_NORMAL) { 267 if (parseMode != PM_NORMAL)
258 th_cfg_error(f, 268 {
259 "Unexpected end of file.\n"); 269 th_cfg_error(f, "Unexpected end of file.\n");
260 parseMode = PM_ERROR; 270 parseMode = PM_ERROR;
261 } else 271 }
272 else
262 parseMode = PM_EOF; 273 parseMode = PM_EOF;
263 break; 274 break;
264 275
265 case '\n': 276 case '\n':
266 f->line++; 277 f->line++;
267 } 278 }
268 } 279 }
269 280
270 switch (parseMode) { 281 switch (parseMode)
282 {
271 case PM_COMMENT: 283 case PM_COMMENT:
272 /* Comment parsing mode */ 284 /* Comment parsing mode */
273 if (c == '\n') { 285 if (c == '\n')
286 {
274 /* End of line, end of comment */ 287 /* End of line, end of comment */
275 parseMode = prevMode; 288 parseMode = prevMode;
276 prevMode = PM_COMMENT; 289 prevMode = PM_COMMENT;
277 } 290 }
278 c = -1; 291 c = -1;
279 break; 292 break;
280 293
281 case PM_NORMAL: 294 case PM_NORMAL:
282 /* Normal parsing mode */ 295 /* Normal parsing mode */
283 if (c == '#') { 296 if (c == '#')
297 {
284 prevMode = parseMode; 298 prevMode = parseMode;
285 parseMode = PM_COMMENT; 299 parseMode = PM_COMMENT;
286 c = -1; 300 c = -1;
287 } else if (VISEND(c)) { 301 }
302 else if (VISEND(c))
303 {
288 c = -1; 304 c = -1;
289 } else if (c == '}') { 305 }
290 if (nesting > 0) { 306 else if (c == '}')
307 {
308 if (nesting > 0)
309 {
291 /* Check for validation errors */ 310 /* Check for validation errors */
292 return (validError) ? 1 : 0; 311 return (validError) ? 1 : 0;
293 } else { 312 }
294 th_cfg_error(f, "Invalid nesting sequence encountered.\n"); 313 else
314 {
315 th_cfg_error(f,
316 "Invalid nesting sequence encountered.\n");
295 parseMode = PM_ERROR; 317 parseMode = PM_ERROR;
296 } 318 }
297 } else if (th_isalpha(c)) { 319 }
320 else if (th_isalpha(c))
321 {
298 /* Start of key name found */ 322 /* Start of key name found */
299 prevMode = parseMode; 323 prevMode = parseMode;
300 parseMode = PM_KEYNAME; 324 parseMode = PM_KEYNAME;
301 strPos = 0; 325 strPos = 0;
302 } else { 326 }
327 else
328 {
303 /* Error! Invalid character found */ 329 /* Error! Invalid character found */
304 th_cfg_error(f, 330 th_cfg_error(f, "Unexpected character '%c'.\n", c);
305 "Unexpected character '%c'.\n", c);
306 parseMode = PM_ERROR; 331 parseMode = PM_ERROR;
307 } 332 }
308 break; 333 break;
309 334
310 case PM_KEYNAME: 335 case PM_KEYNAME:
311 /* Configuration KEY name parsing mode */ 336 /* Configuration KEY name parsing mode */
312 if (c == '#') { 337 if (c == '#')
338 {
313 /* Start of comment */ 339 /* Start of comment */
314 prevMode = parseMode; 340 prevMode = parseMode;
315 parseMode = PM_COMMENT; 341 parseMode = PM_COMMENT;
316 c = -1; 342 c = -1;
317 } else if (th_iscrlf(c) || th_isspace(c) || c == '=') { 343 }
344 else if (th_iscrlf(c) || th_isspace(c) || c == '=')
345 {
318 /* End of key name */ 346 /* End of key name */
319 prevMode = parseMode; 347 prevMode = parseMode;
320 parseMode = PM_NEXT; 348 parseMode = PM_NEXT;
321 nextMode = PM_KEYSET; 349 nextMode = PM_KEYSET;
322 } else if (th_isalnum(c) || c == '_') { 350 }
351 else if (th_isalnum(c) || c == '_')
352 {
323 /* Add to key name string */ 353 /* Add to key name string */
324 VADDCH(c) 354 VADDCH(c)
325 else 355 else
326 { 356 {
327 /* Error! Key name string too long! */ 357 /* Error! Key name string too long! */
328 th_cfg_error(f, 358 th_cfg_error(f, "Config key name too long!");
329 "Config key name too long!");
330 parseMode = PM_ERROR; 359 parseMode = PM_ERROR;
331 } 360 }
332 c = -1; 361 c = -1;
333 } else { 362 }
363 else
364 {
334 /* Error! Invalid character found */ 365 /* Error! Invalid character found */
335 tmpStr[strPos] = 0; 366 tmpStr[strPos] = 0;
336 th_cfg_error(f, 367 th_cfg_error(f,
337 "Unexpected character '%c' in key name '%s'.\n", c, tmpStr); 368 "Unexpected character '%c' in key name '%s'.\n",
369 c, tmpStr);
338 parseMode = PM_ERROR; 370 parseMode = PM_ERROR;
339 } 371 }
340 break; 372 break;
341 373
342 case PM_KEYSET: 374 case PM_KEYSET:
343 if (c == '=') { 375 if (c == '=')
376 {
344 /* Find key from configuration */ 377 /* Find key from configuration */
345 tmpStr[strPos] = 0; 378 tmpStr[strPos] = 0;
346 isFound = FALSE; 379 isFound = FALSE;
347 item = cfg; 380 item = cfg;
348 while (item != NULL && !isFound) { 381 while (item != NULL && !isFound)
382 {
349 if (item->name != NULL && strcmp(item->name, tmpStr) == 0) 383 if (item->name != NULL && strcmp(item->name, tmpStr) == 0)
350 isFound = TRUE; 384 isFound = TRUE;
351 else 385 else
352 item = item->next; 386 item = item->next;
353 } 387 }
354 388
355 /* Check if key was found */ 389 /* Check if key was found */
356 if (isFound) { 390 if (isFound)
391 {
357 /* Okay, set next mode */ 392 /* Okay, set next mode */
358 switch (item->type) { 393 switch (item->type)
394 {
359 case ITEM_HEX_TRIPLET: 395 case ITEM_HEX_TRIPLET:
360 case ITEM_STRING: 396 case ITEM_STRING:
361 nextMode = PM_STRING; 397 nextMode = PM_STRING;
362 break; 398 break;
363 399
371 break; 407 break;
372 408
373 case ITEM_BOOL: 409 case ITEM_BOOL:
374 nextMode = PM_BOOL; 410 nextMode = PM_BOOL;
375 break; 411 break;
376 412
377 case ITEM_SECTION: 413 case ITEM_SECTION:
378 nextMode = PM_SECTION; 414 nextMode = PM_SECTION;
379 break; 415 break;
380 } 416 }
381 417
382 prevMode = parseMode; 418 prevMode = parseMode;
383 parseMode = PM_NEXT; 419 parseMode = PM_NEXT;
384 isStart = TRUE; 420 isStart = TRUE;
385 strPos = 0; 421 strPos = 0;
386 } else { 422 }
423 else
424 {
387 /* Error! No configuration key by this name found */ 425 /* Error! No configuration key by this name found */
388 th_cfg_error(f, 426 th_cfg_error(f,
389 "No such configuration setting ('%s')\n", tmpStr); 427 "No such configuration setting ('%s')\n",
428 tmpStr);
390 parseMode = PM_ERROR; 429 parseMode = PM_ERROR;
391 } 430 }
392 431
393 c = -1; 432 c = -1;
394 } else { 433 }
434 else
435 {
395 /* Error! '=' expected! */ 436 /* Error! '=' expected! */
396 th_cfg_error(f, 437 th_cfg_error(f,
397 "Unexpected character '%c', assignation '=' was expected.\n", c); 438 "Unexpected character '%c', assignation '=' was expected.\n",
439 c);
398 parseMode = PM_ERROR; 440 parseMode = PM_ERROR;
399 } 441 }
400 break; 442 break;
401 443
402 case PM_NEXT: 444 case PM_NEXT:
403 /* Search next item parsing mode */ 445 /* Search next item parsing mode */
404 if (c == '#') { 446 if (c == '#')
447 {
405 /* Start of comment */ 448 /* Start of comment */
406 prevMode = parseMode; 449 prevMode = parseMode;
407 parseMode = PM_COMMENT; 450 parseMode = PM_COMMENT;
408 } else if (th_isspace(c) || th_iscrlf(c)) { 451 }
452 else if (th_isspace(c) || th_iscrlf(c))
453 {
409 /* Ignore whitespaces and linechanges */ 454 /* Ignore whitespaces and linechanges */
410 c = -1; 455 c = -1;
411 } else { 456 }
457 else
458 {
412 /* Next item found */ 459 /* Next item found */
413 prevMode = parseMode; 460 prevMode = parseMode;
414 parseMode = nextMode; 461 parseMode = nextMode;
415 } 462 }
416 break; 463 break;
417 464
418 case PM_ARRAY: 465 case PM_ARRAY:
419 if (isStart) { 466 if (isStart)
420 switch (item->type) { 467 {
421 case ITEM_STRING_LIST: 468 switch (item->type)
422 prevMode = parseMode; 469 {
423 parseMode = PM_STRING; 470 case ITEM_STRING_LIST:
424 break; 471 prevMode = parseMode;
425 } 472 parseMode = PM_STRING;
426 } else if (c == ',') { 473 break;
427 switch (item->type) { 474 }
428 case ITEM_STRING_LIST: 475 }
429 c = -1; 476 else if (c == ',')
430 isStart = TRUE; 477 {
431 prevMode = parseMode; 478 switch (item->type)
432 parseMode = PM_NEXT; 479 {
433 nextMode = PM_STRING; 480 case ITEM_STRING_LIST:
434 break; 481 c = -1;
435 } 482 isStart = TRUE;
436 } else { 483 prevMode = parseMode;
484 parseMode = PM_NEXT;
485 nextMode = PM_STRING;
486 break;
487 }
488 }
489 else
490 {
437 prevMode = parseMode; 491 prevMode = parseMode;
438 parseMode = PM_NORMAL; 492 parseMode = PM_NORMAL;
439 } 493 }
440 break; 494 break;
441 495
442 case PM_SECTION: 496 case PM_SECTION:
443 /* Section parsing mode */ 497 /* Section parsing mode */
444 if (c != '{') { 498 if (c != '{')
499 {
445 /* Error! Section start '{' expected! */ 500 /* Error! Section start '{' expected! */
446 th_cfg_error(f, 501 th_cfg_error(f,
447 "Unexpected character '%c', section start '{' was expected.\n", c); 502 "Unexpected character '%c', section start '{' was expected.\n",
503 c);
448 parseMode = PM_ERROR; 504 parseMode = PM_ERROR;
449 } else { 505 }
506 else
507 {
450 int res = th_cfg_read_sect(f, item->v.section, nesting + 1); 508 int res = th_cfg_read_sect(f, item->v.section, nesting + 1);
451 c = -1; 509 c = -1;
452 if (res > 0) 510 if (res > 0)
453 validError = TRUE; 511 validError = TRUE;
454 else if (res < 0) 512 else if (res < 0)
455 parseMode = PM_ERROR; 513 parseMode = PM_ERROR;
456 else { 514 else
515 {
457 prevMode = parseMode; 516 prevMode = parseMode;
458 parseMode = PM_NORMAL; 517 parseMode = PM_NORMAL;
459 } 518 }
460 } 519 }
461 break; 520 break;
462 521
463 case PM_STRING: 522 case PM_STRING:
464 /* String parsing mode */ 523 /* String parsing mode */
465 if (isStart) { 524 if (isStart)
525 {
466 /* Start of string, get delimiter */ 526 /* Start of string, get delimiter */
467 tmpCh = c; 527 tmpCh = c;
468 isStart = FALSE; 528 isStart = FALSE;
469 strPos = 0; 529 strPos = 0;
470 } else if (c == tmpCh) { 530 }
531 else if (c == tmpCh)
532 {
471 /* End of string, set the value */ 533 /* End of string, set the value */
472 tmpStr[strPos] = 0; 534 tmpStr[strPos] = 0;
473 535
474 switch (item->type) { 536 switch (item->type)
475 case ITEM_HEX_TRIPLET: 537 {
476 *(item->v.val_int) = th_get_hex_triplet(tmpStr); 538 case ITEM_HEX_TRIPLET:
477 prevMode = parseMode; 539 *(item->v.val_int) = th_get_hex_triplet(tmpStr);
478 parseMode = PM_NORMAL; 540 prevMode = parseMode;
479 break; 541 parseMode = PM_NORMAL;
480 case ITEM_STRING: 542 break;
481 th_pstrcpy(item->v.val_str, tmpStr); 543 case ITEM_STRING:
482 prevMode = parseMode; 544 th_pstrcpy(item->v.val_str, tmpStr);
483 parseMode = PM_NORMAL; 545 prevMode = parseMode;
484 break; 546 parseMode = PM_NORMAL;
485 case ITEM_STRING_LIST: 547 break;
486 th_llist_append(item->v.list, th_strdup(tmpStr)); 548 case ITEM_STRING_LIST:
487 prevMode = parseMode; 549 th_llist_append(item->v.list, th_strdup(tmpStr));
488 parseMode = PM_NEXT; 550 prevMode = parseMode;
489 nextMode = PM_ARRAY; 551 parseMode = PM_NEXT;
490 break; 552 nextMode = PM_ARRAY;
491 } 553 break;
492 554 }
493 } else { 555
556 }
557 else
558 {
494 /* Add character to string */ 559 /* Add character to string */
495 VADDCH(c) 560 VADDCH(c)
496 else 561 else
497 { 562 {
498 /* Error! String too long! */ 563 /* Error! String too long! */
499 th_cfg_error(f, 564 th_cfg_error(f,
500 "String too long! Maximum is %d characters.", 565 "String too long! Maximum is %d characters.",
501 SET_MAX_BUF); 566 SET_MAX_BUF);
502 parseMode = PM_ERROR; 567 parseMode = PM_ERROR;
503 } 568 }
504 } 569 }
505 570
506 c = -1; 571 c = -1;
507 break; 572 break;
508 573
509 case PM_INT: 574 case PM_INT:
510 /* Integer parsing mode */ 575 /* Integer parsing mode */
511 if (isStart && item->type == ITEM_UINT && c == '-') { 576 if (isStart && item->type == ITEM_UINT && c == '-')
577 {
512 /* Error! Negative values not allowed for unsigned ints */ 578 /* Error! Negative values not allowed for unsigned ints */
513 th_cfg_error(f, 579 th_cfg_error(f,
514 "Negative value specified for %s, unsigned value expected.", 580 "Negative value specified for %s, unsigned value expected.",
515 item->name); 581 item->name);
516 parseMode = PM_ERROR; 582 parseMode = PM_ERROR;
517 } else if (isStart && (c == '-' || c == '+')) { 583 }
584 else if (isStart && (c == '-' || c == '+'))
585 {
518 VADDCH(c) 586 VADDCH(c)
519 else 587 else
520 isError = TRUE; 588 isError = TRUE;
521 } else if (th_isdigit(c)) { 589 }
590 else if (th_isdigit(c))
591 {
522 VADDCH(c) 592 VADDCH(c)
523 else 593 else
524 isError = TRUE; 594 isError = TRUE;
525 } else if (VISEND(c)) { 595 }
596 else if (VISEND(c))
597 {
526 /* End of integer parsing mode */ 598 /* End of integer parsing mode */
527 tmpStr[strPos] = 0; 599 tmpStr[strPos] = 0;
528 switch (item->type) { 600 switch (item->type)
601 {
529 case ITEM_INT: 602 case ITEM_INT:
530 *(item->v.val_int) = atoi(tmpStr); 603 *(item->v.val_int) = atoi(tmpStr);
531 break; 604 break;
532 605
533 case ITEM_UINT: 606 case ITEM_UINT:
535 break; 608 break;
536 } 609 }
537 610
538 prevMode = parseMode; 611 prevMode = parseMode;
539 parseMode = PM_NORMAL; 612 parseMode = PM_NORMAL;
540 } else { 613 }
614 else
615 {
541 /* Error! Unexpected character. */ 616 /* Error! Unexpected character. */
542 th_cfg_error(f, 617 th_cfg_error(f,
543 "Unexpected character '%c' for integer setting '%s'.", 618 "Unexpected character '%c' for integer setting '%s'.",
544 c, item->name); 619 c, item->name);
545 parseMode = PM_ERROR; 620 parseMode = PM_ERROR;
546 } 621 }
547 622
548 if (isError) { 623 if (isError)
624 {
549 /* Error! String too long! */ 625 /* Error! String too long! */
550 th_cfg_error(f, "String too long! Maximum is %d characters.", 626 th_cfg_error(f, "String too long! Maximum is %d characters.",
551 SET_MAX_BUF); 627 SET_MAX_BUF);
552 parseMode = PM_ERROR; 628 parseMode = PM_ERROR;
553 } 629 }
554 630
555 isStart = FALSE; 631 isStart = FALSE;
556 c = -1; 632 c = -1;
557 break; 633 break;
558 634
559 case PM_BOOL: 635 case PM_BOOL:
560 /* Boolean parsing mode */ 636 /* Boolean parsing mode */
561 if (isStart) { 637 if (isStart)
638 {
562 tmpCh = c; 639 tmpCh = c;
563 isStart = FALSE; 640 isStart = FALSE;
564 } else if (VISEND(c)) { 641 }
642 else if (VISEND(c))
643 {
565 BOOL tmpBool = FALSE; 644 BOOL tmpBool = FALSE;
566 645
567 /* End of boolean parsing */ 646 /* End of boolean parsing */
568 switch (tmpCh) { 647 switch (tmpCh)
569 case 'Y': case 'y': 648 {
570 case 'T': case 't': 649 case 'Y':
650 case 'y':
651 case 'T':
652 case 't':
571 case '1': 653 case '1':
572 tmpBool = TRUE; 654 tmpBool = TRUE;
573 break; 655 break;
574 656
575 case 'N': case 'n': 657 case 'N':
576 case 'F': case 'f': 658 case 'n':
659 case 'F':
660 case 'f':
577 case '0': 661 case '0':
578 tmpBool = FALSE; 662 tmpBool = FALSE;
579 break; 663 break;
580 664
581 default: 665 default:
582 isError = TRUE; 666 isError = TRUE;
583 } 667 }
584 668
585 if (isError) { 669 if (isError)
586 th_cfg_error(f, "Invalid boolean value for '%s'.\n", item->name); 670 {
671 th_cfg_error(f, "Invalid boolean value for '%s'.\n",
672 item->name);
587 parseMode = PM_ERROR; 673 parseMode = PM_ERROR;
588 } else { 674 }
675 else
676 {
589 *(item->v.val_bool) = tmpBool; 677 *(item->v.val_bool) = tmpBool;
590 678
591 prevMode = parseMode; 679 prevMode = parseMode;
592 parseMode = PM_NORMAL; 680 parseMode = PM_NORMAL;
593 } 681 }
607 else 695 else
608 return 0; 696 return 0;
609 } 697 }
610 698
611 699
612 int th_cfg_read(FILE *inFile, char *filename, cfgitem_t * cfg) 700 int th_cfg_read(FILE *inFile, char *filename, cfgitem_t *cfg)
613 { 701 {
614 conffile_t f; 702 conffile_t f;
615 703
616 f.file = inFile; 704 f.file = inFile;
617 f.filename = filename; 705 f.filename = filename;
618 f.line = 1; 706 f.line = 1;
619 707
620 return th_cfg_read_sect(&f, cfg, 0); 708 return th_cfg_read_sect(&f, cfg, 0);
621 } 709 }
622 710
623 711
624 /* Write a configuration into file 712 /* Write a configuration into file
631 } 719 }
632 720
633 721
634 static int th_cfg_write_sect(conffile_t *f, cfgitem_t *item, int nesting) 722 static int th_cfg_write_sect(conffile_t *f, cfgitem_t *item, int nesting)
635 { 723 {
636 while (item != NULL) { 724 while (item != NULL)
637 if (item->type == ITEM_COMMENT) { 725 {
726 if (item->type == ITEM_COMMENT)
727 {
638 th_print_indent(f, nesting); 728 th_print_indent(f, nesting);
639 if (fprintf(f->file, "# %s\n", (item->name != NULL) ? item->name : "" ) < 0) 729 if (fprintf
730 (f->file, "# %s\n",
731 (item->name != NULL) ? item->name : "") < 0)
640 return -1; 732 return -1;
641 } else 733 }
642 if (item->name != NULL) { 734 else if (item->name != NULL)
735 {
643 th_print_indent(f, nesting); 736 th_print_indent(f, nesting);
644 737
645 switch (item->type) { 738 switch (item->type)
739 {
646 case ITEM_STRING: 740 case ITEM_STRING:
647 if (*(item->v.val_str) == NULL) { 741 if (*(item->v.val_str) == NULL)
742 {
648 if (fprintf(f->file, "#%s = \"\"\n", item->name) < 0) 743 if (fprintf(f->file, "#%s = \"\"\n", item->name) < 0)
649 return -3; 744 return -3;
650 } else { 745 }
746 else
747 {
651 if (fprintf(f->file, "%s = \"%s\"\n", 748 if (fprintf(f->file, "%s = \"%s\"\n",
652 item->name, *(item->v.val_str)) < 0) 749 item->name, *(item->v.val_str)) < 0)
653 return -3; 750 return -3;
654 } 751 }
655 break; 752 break;
656 753
657 case ITEM_STRING_LIST: 754 case ITEM_STRING_LIST:
658 if (*(item->v.list) == NULL) { 755 if (*(item->v.list) == NULL)
659 if (fprintf(f->file, "#%s = \"\", \"\"\n", item->name) < 0) 756 {
757 if (fprintf(f->file, "#%s = \"\", \"\"\n", item->name) <
758 0)
660 return -3; 759 return -3;
661 } else { 760 }
761 else
762 {
662 qlist_t *node = *(item->v.list); 763 qlist_t *node = *(item->v.list);
663 size_t n = th_llist_length(node); 764 size_t n = th_llist_length(node);
664 if (fprintf(f->file, "%s = ", item->name) < 0) 765 if (fprintf(f->file, "%s = ", item->name) < 0)
665 return -3; 766 return -3;
666 767
667 while (node != NULL) { 768 while (node != NULL)
769 {
668 if (node->data != NULL) 770 if (node->data != NULL)
669 fprintf(f->file, "\"%s\"", (char *) node->data); 771 fprintf(f->file, "\"%s\"", (char *) node->data);
670 772
671 if (--n > 0) { 773 if (--n > 0)
774 {
672 fprintf(f->file, ",\n"); 775 fprintf(f->file, ",\n");
673 th_print_indent(f, nesting); 776 th_print_indent(f, nesting);
674 } 777 }
675 node = node->next; 778 node = node->next;
676 } 779 }
680 } 783 }
681 break; 784 break;
682 785
683 case ITEM_INT: 786 case ITEM_INT:
684 if (fprintf(f->file, "%s = %i\n", 787 if (fprintf(f->file, "%s = %i\n",
685 item->name, *(item->v.val_int)) < 0) 788 item->name, *(item->v.val_int)) < 0)
686 return -4; 789 return -4;
687 break; 790 break;
688 791
689 case ITEM_UINT: 792 case ITEM_UINT:
690 if (fprintf(f->file, "%s = %d\n", 793 if (fprintf(f->file, "%s = %d\n",
691 item->name, *(item->v.val_uint)) < 0) 794 item->name, *(item->v.val_uint)) < 0)
692 return -5; 795 return -5;
693 break; 796 break;
694 797
695 case ITEM_BOOL: 798 case ITEM_BOOL:
696 if (fprintf(f->file, "%s = %s\n", 799 if (fprintf(f->file, "%s = %s\n",
697 item->name, *(item->v.val_bool) ? "yes" : "no") < 0) 800 item->name,
801 *(item->v.val_bool) ? "yes" : "no") < 0)
698 return -6; 802 return -6;
699 break; 803 break;
700 804
701 case ITEM_SECTION: 805 case ITEM_SECTION:
702 { 806 {
703 int res; 807 int res;
704 if (fprintf(f->file, "%s = {\n", item->name) < 0) 808 if (fprintf(f->file, "%s = {\n", item->name) < 0)
705 return -7; 809 return -7;
706 res = th_cfg_write_sect(f, item->v.section, nesting + 1); 810 res = th_cfg_write_sect(f, item->v.section, nesting + 1);
707 if (res != 0) return res; 811 if (res != 0)
708 if (fprintf(f->file, "}\n\n") < 0) 812 return res;
709 return -8; 813 if (fprintf(f->file, "}\n\n") < 0)
814 return -8;
710 } 815 }
711 break; 816 break;
712 817
713 case ITEM_HEX_TRIPLET: 818 case ITEM_HEX_TRIPLET:
714 if (fprintf(f->file, "%s = \"%06x\"\n", 819 if (fprintf(f->file, "%s = \"%06x\"\n",
715 item->name, *(item->v.val_int)) < 0) 820 item->name, *(item->v.val_int)) < 0)
716 return -6; 821 return -6;
717 break; 822 break;
718 } 823 }
719 } 824 }
720 item = item->next; 825 item = item->next;
721 } 826 }
722 827
723 return 0; 828 return 0;
724 } 829 }
725 830
726 831
727 int th_cfg_write(FILE *outFile, char *filename, cfgitem_t *cfg) 832 int th_cfg_write(FILE *outFile, char *filename, cfgitem_t *cfg)
728 { 833 {
729 conffile_t f; 834 conffile_t f;
730 835
731 if (cfg == NULL) 836 if (cfg == NULL)
732 return -1; 837 return -1;
733 838
734 f.file = outFile; 839 f.file = outFile;
735 f.filename = filename; 840 f.filename = filename;
736 f.line = 1; 841 f.line = 1;
737 842
738 fprintf(outFile, "# Configuration written by %s %s\n\n", 843 fprintf(outFile, "# Configuration written by %s %s\n\n",
739 th_prog_fullname, th_prog_version); 844 th_prog_fullname, th_prog_version);
740 845
741 return th_cfg_write_sect(&f, cfg, 0); 846 return th_cfg_write_sect(&f, cfg, 0);
742 } 847 }
743
744