Bug Summary

File:src/cfg/shared.c
Location:line 491, column 7
Description:Dereference of null pointer

Annotated Source Code

1/*
2 * libcfg+ - precise command line & config file parsing library
3 *
4 * shared.c - shared stuff for command line and config file
5 * ____________________________________________________________
6 *
7 * Developed by Ondrej Jombik <nepto@platon.sk>
8 * and Lubomir Host <rajo@platon.sk>
9 * Copyright (c) 2001-2004 Platon SDG, http://platon.sk/
10 * All rights reserved.
11 *
12 * See README file for more information about this software.
13 * See COPYING file for license information.
14 *
15 * Download the latest version from
16 * http://platon.sk/projects/libcfg+/
17 */
18
19/* $Platon: libcfg+/src/shared.c,v 1.36 2004/01/12 06:03:09 nepto Exp $ */
20
21/* Includes {{{ */
22#ifdef HAVE_CONFIG_H1
23# include <config.h>
24#endif
25
26#if STDC_HEADERS1
27# include <stdlib.h>
28#else
29# if HAVE_STDLIB_H1
30# include <stdlib.h>
31# endif
32#endif
33#if HAVE_STRING_H1
34# if !STDC_HEADERS1 && HAVE_MEMORY_H1
35# include <memory.h>
36# endif
37# include <string.h>
38#endif
39#if HAVE_STRINGS_H1
40# include <strings.h>
41#endif
42#if HAVE_MATH_H1
43# include <math.h>
44#endif
45#if HAVE_LIMITS_H1
46# include <limits.h>
47#endif
48#if HAVE_FLOAT_H1
49# include <float.h>
50#endif
51#if HAVE_CTYPE_H1
52# include <ctype.h>
53#endif
54#if HAVE_ERRNO_H1
55# include <errno(*__errno_location ()).h>
56#endif
57
58#include <platon/str/strplus.h>
59#include <platon/str/strdyn.h>
60
61#include "cfg+.h"
62/* }}} */
63
64/* Static function declarations {{{ */
65static int search_cur_opt_idx(const CFG_CONTEXT con);
66static int add_to_used_opt_idx(const CFG_CONTEXT con, int opt_idx);
67static int store_multi_arg(
68 const int type,
69 const char **multi_arg,
70 void ***ar);
71static int store_single_arg(
72 const int type,
73 const char *arg,
74 const void *where);
75static int split_multi_arg(
76 char *arg,
77 char ***ar,
78 char **quote_prefix_ar,
79 char **quote_postfix_ar,
80 char **separator_ar);
81static int unquote_single_arg(
82 char *arg,
83 char **quote_prefix_ar,
84 char **quote_postfix_ar);
85/* }}} */
86
87/*
88 * EXTERN PLATON_FUNCS
89 */
90
91 void
92__cfg_free_currents(con)
93 const CFG_CONTEXT con;
94{ /* {{{ */
95 if (con->cur_opt != NULL((void*)0))
96 free(con->cur_opt);
97 if (con->cur_arg != NULL((void*)0))
98 free(con->cur_arg);
99
100 con->cur_opt = con->cur_arg = NULL((void*)0);
101 con->cur_opt_type = CFG_NONE_OPTION;
102} /* }}} */
103
104 int
105__cfg_process_currents(con, ret_val, arg_used)
106 const CFG_CONTEXT con;
107 int *ret_val;
108 int *arg_used;
109{ /* {{{ */
110 register int ret = 0;
111 register int opt_idx;
112 register int opt_type, opt_data_type, opt_f_multi, opt_f_multi_sep;
113 register char **quote_prefix_ar, **quote_postfix_ar, **separator_ar;
114
115 *ret_val = 0;
116 if (arg_used != NULL((void*)0))
117 *arg_used = 0;
118
119 opt_idx = search_cur_opt_idx(con);
120
121#if defined(DEBUG) && DEBUG
122 fprintf(stderrstderr, "%s|%ld|%s|%s|%s|%d|flags=%x[",
123 con->type == CFG_LINE ? "cmdline" : "cfgfile",
124 con->type == CFG_LINE ? con->cur_idx : 0,
125 con->type == CFG_LINE ? con->argv[con->cur_idx] : "N/A",
126 con->cur_opt == NULL((void*)0) ? "[NULL]" : con->cur_opt,
127 con->cur_arg == NULL((void*)0) ? "[NULL]" : con->cur_arg,
128 opt_idx, con->cur_opt_type);
129
130 if (con->cur_opt_type & CFG_LONG_OPTION)
131 fputs("-LONG-", stderrstderr);
132 if (con->cur_opt_type & CFG_SHORT_OPTION)
133 fputs("-SHORT-", stderrstderr);
134 if (con->cur_opt_type & CFG_SHORT_OPTIONS)
135 fputs("-SHORTS-", stderrstderr);
136 if (con->cur_opt_type & CFG_LONG_SEPINIT)
137 fputs("-SEPINIT-", stderrstderr);
138
139 fputs("]\n", stderrstderr);
140#endif
141
142 if (opt_idx < 0)
143 return CFG_ERROR_UNKNOWN; /* unknown option reached */
144
145 if (! (con->flags & CFG_IGNORE_MULTI)
146 && ! (con->options[opt_idx].type & CFG_MULTI)) {
147 ret = add_to_used_opt_idx(con, opt_idx);
148
149 if (ret < 0)
150 return CFG_ERROR_NOMEM;
151 else if (ret > 0)
152 return CFG_ERROR_MULTI;
153 }
154
155 /* Setting others opt_XXX constants according to *opt_idx. */
156 /* opt_data_type - option data type, opt_f_XXX - option flags */
157 opt_type = con->options[opt_idx].type;
158 opt_data_type = opt_type & CFG_DATA_TYPE_MASK;
159 opt_f_multi = opt_type & CFG_MULTI;
160 opt_f_multi_sep = opt_type & (CFG_MULTI_SEPARATED & ~CFG_MULTI);
161
162 if (con->type == CFG_LINE) {
163 quote_prefix_ar = con->prop[CFG_LINE_QUOTE_PREFIX];
164 quote_postfix_ar = con->prop[CFG_LINE_QUOTE_POSTFIX];
165 separator_ar = (opt_type & CFG_LEFTOVER_ARGS)
166 ? con->prop[CFG_LINE_LEFTOVER_MULTI_VALS_SEPARATOR]
167 : con->prop[CFG_LINE_NORMAL_MULTI_VALS_SEPARATOR];
168 }
169 else {
170 quote_prefix_ar = con->prop[CFG_FILE_QUOTE_PREFIX];
171 quote_postfix_ar = con->prop[CFG_FILE_QUOTE_POSTFIX];
172 separator_ar = (opt_type & CFG_LEFTOVER_ARGS)
173 ? con->prop[CFG_FILE_LEFTOVER_MULTI_VALS_SEPARATOR]
174 : con->prop[CFG_FILE_NORMAL_MULTI_VALS_SEPARATOR];
175 }
176
177 switch (opt_data_type) {
178 default:
179 return CFG_ERROR_INTERNAL;
180 break;
181
182 /* Boolean data type */
183
184 case CFG_BOOLEAN:
185 if (con->cur_opt_type & CFG_LONG_SEPINIT
186 && con->cur_arg != NULL((void*)0))
187 return CFG_ERROR_NOTALLOWEDARG;
188
189 if (con->options[opt_idx].value != NULL((void*)0))
190 (*((int *) con->options[opt_idx].value))++;
191 break;
192
193 /* Numeric (int, long, float and double) data types */
194
195 case CFG_INT:
196 case CFG_UINT:
197 case CFG_LONG:
198 case CFG_ULONG:
199 case CFG_FLOAT:
200 case CFG_DOUBLE:
201
202 if (con->cur_arg == NULL((void*)0))
203 return CFG_ERROR_NOARG;
204
205 if (opt_f_multi) {
206 char **add;
207 char *static_add[2] = {NULL((void*)0), NULL((void*)0)};
208
209 if (opt_f_multi_sep) {
210
211 ret = split_multi_arg(con->cur_arg, &add,
212 quote_prefix_ar, quote_postfix_ar, separator_ar);
213
214 if (ret != CFG_OK) {
215 PLATON_FUNC(strdyn_safe_free)strdyn_safe_free(add);
216 return ret;
217 }
218 }
219 else {
220 add = static_add;
221 add[0] = con->cur_arg;
222 }
223
224 ret = store_multi_arg(opt_data_type,
225 (const char **) add,
226 con->options[opt_idx].value);
227
228 if (add != static_add)
229 PLATON_FUNC(strdyn_free)strdyn_free((char **) add);
230 }
231 else {
232 ret = unquote_single_arg(con->cur_arg,
233 quote_prefix_ar, quote_postfix_ar);
234
235 if (ret != CFG_OK)
236 return ret;
237
238 ret = store_single_arg(opt_data_type, con->cur_arg,
239 con->options[opt_idx].value);
240 }
241
242 if (ret != CFG_OK)
243 return ret;
244
245 if (arg_used != NULL((void*)0))
246 *arg_used = 1;
247 break;
248
249 /* String data type */
250
251 case CFG_STRING:
252
253 if (con->cur_arg == NULL((void*)0))
254 return CFG_ERROR_NOARG;
255
256 if (con->options[opt_idx].value != NULL((void*)0)) {
257 if (opt_f_multi) {
258 register char ***p;
259 p = (char ***) con->options[opt_idx].value;
260
261 if (opt_f_multi_sep) {
262 char **ar;
263 ret = split_multi_arg(con->cur_arg, &ar,
264 quote_prefix_ar, quote_postfix_ar,
265 separator_ar);
266
267 if (ret != CFG_OK) {
268 PLATON_FUNC(strdyn_safe_free)strdyn_safe_free(ar);
269 return ret;
270 }
271
272 if ((*p = PLATON_FUNC(strdyn_add_ar)strdyn_add_ar(*p, ar)) == NULL((void*)0))
273 return CFG_ERROR_NOMEM;
274
275 PLATON_FUNC(strdyn_free)strdyn_free(ar);
276 }
277 else {
278 ret = unquote_single_arg(con->cur_arg,
279 quote_prefix_ar, quote_postfix_ar);
280
281 if (ret != CFG_OK)
282 return ret;
283
284 if ((*p = PLATON_FUNC(strdyn_add)strdyn_add(*p, con->cur_arg)) == NULL((void*)0))
285 return CFG_ERROR_NOMEM;
286 }
287 }
288 else {
289 ret = unquote_single_arg(con->cur_arg,
290 quote_prefix_ar, quote_postfix_ar);
291
292 if (ret != CFG_OK)
293 return ret;
294
295 *((char **) con->options[opt_idx].value) =
296 strdup(con->cur_arg);
297 }
298 }
299
300 if (arg_used != NULL((void*)0))
301 *arg_used = 1;
302 break;
303 }
304
305 *ret_val = con->options[opt_idx].val;
306
307 return CFG_OK;
308} /* }}} */
309
310 int
311__cfg_cmdline_set_currents(con)
312 const CFG_CONTEXT con;
313{ /* {{{ */
314 register int i, size;
315 register char *s, *s_sep, *s_tmp;
316 register char *ptr;
317
318 size = -1; /* size of matched prefix (0 is also valid) */
319 s = con->argv[con->cur_idx]; /* string to scan */
320
321 /* Explicit `size_t' to `int' typecastings are required here near strlen()
322 calls, else strlen("") == 0 will be considered as smaller than -1. */
323
324 for (i = 0; (ptr = con->prop[CFG_LINE_SHORT_OPTION_PREFIX][i]) != NULL((void*)0); i++)
325 if ((int) strlen(ptr) > size && strstr(s, ptr) == s) {
326 size = strlen(ptr);
327 con->cur_opt_type = CFG_SHORT_OPTION;
328 }
329
330 for (i = 0; (ptr = con->prop[CFG_LINE_LONG_OPTION_PREFIX][i]) != NULL((void*)0); i++)
331 if ((int) strlen(ptr) > size && strstr(s, ptr) == s) {
332 size = strlen(ptr);
333 con->cur_opt_type = CFG_LONG_OPTION;
334 }
335
336 s_sep = NULL((void*)0);
337
338 switch (con->cur_opt_type) {
339 default:
340 case CFG_NONE_OPTION: /* None option prefix */
341 break;
342
343 case CFG_SHORT_OPTION: /* Short option prefix */
344 s += size;
345 s_sep = strlen(s) > 0 ? s + 1 : s;
346
347 if (strlen(s_sep) > 0) {
348 con->cur_opt_type += CFG_SHORT_OPTIONS;
349
350 if ((con->cur_arg = strdup(s_sep)) == NULL((void*)0))
351 return CFG_ERROR_NOMEM;
352 }
353 else {
354 if (con->argv[con->cur_idx + 1] != NULL((void*)0)) {
355 con->cur_arg = strdup(con->argv[con->cur_idx + 1]);
356 if (con->cur_arg == NULL((void*)0))
357 return CFG_ERROR_NOMEM;
358 }
359 else
360 con->cur_arg = NULL((void*)0);
361 }
362 break;
363
364 case CFG_LONG_OPTION: /* Long option prefix */
365 s += size;
366 size = 0;
367
368 for (i = 0; (ptr = con->prop[CFG_LINE_OPTION_ARG_SEPARATOR][i])
369 != NULL((void*)0); i++)
370 if ((s_tmp = strstr(s, ptr)) != NULL((void*)0))
371 if (s_sep == NULL((void*)0) || s_tmp < s_sep
372 || (s_tmp == s_sep && strlen(ptr) > size)) {
373 s_sep = s_tmp;
374 size = strlen(ptr);
375 }
376
377 if (s_sep == NULL((void*)0)) {
378 if (con->argv[con->cur_idx + 1] != NULL((void*)0)) {
379 con->cur_arg = strdup(con->argv[con->cur_idx + 1]);
380 if (con->cur_arg == NULL((void*)0))
381 return CFG_ERROR_NOMEM;
382 }
383 else
384 con->cur_arg = NULL((void*)0);
385 }
386 else {
387 con->cur_opt_type += CFG_LONG_SEPINIT;
388 if ((con->cur_arg = strdup(s_sep + size)) == NULL((void*)0))
389 return CFG_ERROR_NOMEM;
390 }
391 }
392
393 if (s_sep == NULL((void*)0))
394 s_sep = s + strlen(s);
395
396 con->cur_opt = (char *) malloc((s_sep - s + 1) * sizeof(char));
397 if (con->cur_opt == NULL((void*)0))
398 return CFG_ERROR_NOMEM;
399
400 strncpy(con->cur_opt, s, s_sep - s);
401 con->cur_opt[s_sep - s] = '\0';
402
403 if (con->cur_opt_type == CFG_NONE_OPTION) {
404 register char *tmp_str;
405 tmp_str = con->cur_opt;
406 con->cur_opt = con->cur_arg;
407 con->cur_arg = tmp_str;
408 }
409
410 return CFG_OK;
411} /* }}} */
412
413 int
414__cfg_cfgfile_set_currents(con, buf)
415 const CFG_CONTEXT con;
416 char *buf;
417{ /* {{{ */
418 register char **pos;
419 register char *s_sep, *s_tmp;
420 register int size;
421
422 s_sep = NULL((void*)0);
423 size = 0;
424 for (pos = con->prop[CFG_FILE_OPTION_ARG_SEPARATOR];
425 pos != NULL((void*)0) && *pos != NULL((void*)0); pos++) {
426
427 if ((s_tmp = strstr(buf, *pos)) != NULL((void*)0))
428 if (s_sep == NULL((void*)0) || s_tmp < s_sep
429 || (s_tmp == s_sep && strlen(*pos) > size)) {
430 s_sep = s_tmp;
431 size = strlen(*pos);
432 }
433 }
434
435 if (s_sep == NULL((void*)0)) {
436 con->cur_arg = NULL((void*)0);
437
438 con->cur_opt = strdup(buf);
439 if (con->cur_opt == NULL((void*)0))
440 return CFG_ERROR_NOMEM;
441 }
442 else {
443 con->cur_opt = (char *) malloc((s_sep - buf + 1) * sizeof(char));
444 if (con->cur_opt == NULL((void*)0))
445 return CFG_ERROR_NOMEM;
446
447 strncpy(con->cur_opt, buf, s_sep - buf);
448 con->cur_opt[s_sep - buf] = '\0';
449
450 if ((con->cur_arg = strdup(s_sep + size)) == NULL((void*)0))
451 return CFG_ERROR_NOMEM;
452
453 PLATON_FUNC(str_right_trim)str_right_trim(con->cur_opt);
454 PLATON_FUNC(str_left_trim)str_left_trim(con->cur_arg);
455 }
456
457 return CFG_OK;
458} /* }}} */
459
460/*
461 * STATIC PLATON_FUNCS
462 */
463
464/*
465 * search_cur_opt_idx()
466 *
467 * Function searches con->options for con->cur_opt.
468 * Returns index on success or -1 if not found.
469 */
470
471 static int
472search_cur_opt_idx(con)
473 const CFG_CONTEXT con;
474{ /* {{{ */
475 register int i;
476
477 for (i = 0; con->options[i].cmdline_long_name != NULL((void*)0)
1
Loop condition is true. Entering loop body
478 || con->options[i].cmdline_short_name != '\0'
479 || con->options[i].cfgfile_name != NULL((void*)0)
480 || con->options[i].type != CFG_END
481 || con->options[i].value != NULL((void*)0)
482 || con->options[i].val != 0;
483 i++)
484 {
485 if (con->type == CFG_CMDLINE) { /* Command line context type */
2
Taking true branch
486 if ((con->cur_opt_type & CFG_LONG_OPTION && con->cur_opt != NULL((void*)0)
3
Assuming pointer value is null
487 && con->options[i].cmdline_long_name != NULL((void*)0)
488 && ! strcmp(con->cur_opt,
489 con->options[i].cmdline_long_name))
490 || (con->cur_opt_type & CFG_SHORT_OPTION &&
491 con->cur_opt[0] != '\0' && /* to prevent '-' option */
4
Dereference of null pointer
492 con->cur_opt[0] == con->options[i].cmdline_short_name)
493 || (con->cur_opt_type == CFG_NONE_OPTION &&
494 con->options[i].type & CFG_LEFTOVER_ARGS))
495
496 return i;
497 }
498 else { /* Configuration file context type */
499 int len;
500
501 if (con->cur_opt != NULL((void*)0)
502 && con->options[i].cfgfile_name != NULL((void*)0)
503 && con->cur_opt == PLATON_FUNC(str_white_str)str_white_str(con->cur_opt,
504 (char *)(con->options[i].cfgfile_name), &len)
505 && len == strlen(con->cur_opt))
506
507 return i;
508 }
509 }
510
511 return -1;
512} /* }}} */
513
514
515/*
516 * Size of realloc() step for used_opt member of cfg_context structure.
517 * Value must be grater than 0.
518 */
519
520#ifdef CFG_USED_OPT_IDX_STEP(10)
521# undef CFG_USED_OPT_IDX_STEP(10)
522#endif
523
524#if defined(DEBUG) && DEBUG
525# define CFG_USED_OPT_IDX_STEP(10) (1)
526#else
527# define CFG_USED_OPT_IDX_STEP(10) (10)
528#endif
529
530/*
531 * add_to_used_opt_idx()
532 *
533 * Function adds opt_idx to dynamic array con->used_opt_idx. If array is full,
534 * it is realloc()-ed according to CFG_USED_OPT_IDX_STEP constant. Array
535 * used_opt_idx is primary used for detecting multiple options on command line.
536 *
537 * Note, that in array -1 means empty cell, which can be overwritten by option
538 * index value and -255 means end of array. If there is no -1 left in array,
539 * array must be resized to add new option index value.
540 *
541 * Retuns -1 on not enough memory error, 1 if opt_idx founded in array and 0 if
542 * opt_idx was sucessfully added to array.
543 */
544
545 static int
546add_to_used_opt_idx(con, opt_idx)
547 const CFG_CONTEXT con;
548 int opt_idx;
549{ /* {{{ */
550 int *p_i = NULL((void*)0);
551
552 if (opt_idx < 0)
553 return 1;
554
555 if (con->used_opt_idx != NULL((void*)0))
556 for (p_i = con->used_opt_idx; *p_i >= 0; p_i++)
557 if (*p_i == opt_idx)
558 return 1;
559
560 if (p_i == NULL((void*)0) || *p_i == -255) {
561 register int *p_j;
562 register int new_size;
563
564 new_size = (p_i == NULL((void*)0) ? 0 : p_i - con->used_opt_idx)
565 + 1 + CFG_USED_OPT_IDX_STEP(10);
566
567 con->used_opt_idx = (int *) realloc(con->used_opt_idx,
568 new_size * sizeof(int));
569
570#if defined(DEBUG) && DEBUG
571 printf("add_to_used_opt_idx(con, %d): realloc(%d) = %p\n",
572 opt_idx, new_size, (void *) con->used_opt_idx);
573#endif
574
575 if (con->used_opt_idx == NULL((void*)0))
576 return -1;
577
578 if (p_i == NULL((void*)0))
579 p_i = con->used_opt_idx;
580 else /* Searching for new p_i after realloc(). */
581 for (p_i = con->used_opt_idx; *p_i >= 0; p_i++) ;
582
583 for (p_j = p_i; p_j - p_i < CFG_USED_OPT_IDX_STEP(10); p_j++)
584 *p_j = -1;
585
586 *p_j = -255;
587 }
588
589 *p_i = opt_idx;
590
591 return 0;
592} /* }}} */
593
594/*
595 * store_multi_arg()
596 *
597 * According to option date type (type) parses and stores multiple arguments
598 * (multi_arg) by adding to *ar dynamic array. Array resizing is done as first
599 * and than is store_single_arg() function called with appropriate parameters.
600 */
601
602 static int
603store_multi_arg(type, multi_arg, ar)
604 const int type;
605 const char **multi_arg;
606 void ***ar;
607{ /* {{{ */
608 register int ptr_len, item_len;
609 register int size_plus, size;
610 register int k, ret;
611
612 switch (type) {
613 default:
614 return CFG_ERROR_INTERNAL;
615 break;
616
617 case CFG_INT:
618 ptr_len = sizeof(int *);
619 item_len = sizeof(int);
620 break;
621
622 case CFG_UINT:
623 ptr_len = sizeof(unsigned int *);
624 item_len = sizeof(unsigned int);
625 break;
626
627 case CFG_LONG:
628 ptr_len = sizeof(long *);
629 item_len = sizeof(long);
630 break;
631
632 case CFG_ULONG:
633 ptr_len = sizeof(unsigned long *);
634 item_len = sizeof(unsigned long);
635 break;
636
637 case CFG_FLOAT:
638 ptr_len = sizeof(float *);
639 item_len = sizeof(float);
640 break;
641
642 case CFG_DOUBLE:
643 ptr_len = sizeof(double *);
644 item_len = sizeof(double);
645 break;
646 }
647
648 for (size_plus = 0; multi_arg[size_plus] != NULL((void*)0); size_plus++) ;
649 for (size = 0; *ar != NULL((void*)0) && (*ar)[size] != NULL((void*)0); size++) ;
650
651 *ar = realloc(*ar, (size + 1 + size_plus) * ptr_len);
652
653 if (*ar == NULL((void*)0))
654 return CFG_ERROR_NOMEM;
655
656 /* Array terminated NULL pointer (end of array). */
657 (*ar)[size + size_plus] = NULL((void*)0);
658
659 for (k = 0; k < size_plus; k++) {
660 (*ar)[size + k] = malloc(item_len);
661 if ((*ar)[size + k] == NULL((void*)0))
662 return CFG_ERROR_NOMEM;
663
664 ret = store_single_arg(type, multi_arg[k], (*ar)[size + k]);
665
666 if (ret != CFG_OK) {
667 /* To prevent having random value at size + k position in *ar. */
668 (*ar)[size + k] = NULL((void*)0);
669 return ret;
670 }
671 }
672
673 return CFG_OK;
674} /* }}} */
675
676/*
677 * store_single_arg()
678 *
679 * According to option date type (type) parses and stores single argument (arg)
680 * to specified place pointed by where.
681 */
682
683 static int
684store_single_arg(type, arg, where)
685 const int type;
686 const char *arg;
687 const void *where;
688{ /* {{{ */
689 register long long_val = 0;
690 register unsigned long ulong_val = 0;
691 register double double_val = 0.0;
692 register int f_integer = 0; /* Searching for integer value? */
693 char *end;
694
695 if (where == NULL((void*)0))
696 return CFG_OK;
697
698 /* Conveting to numeric value. */
699 switch (type) {
700 default:
701 return CFG_ERROR_INTERNAL;
702 break;
703
704 case CFG_INT:
705 case CFG_UINT:
706 case CFG_LONG:
707 case CFG_ULONG:
708 f_integer = 1;
709 if (type == CFG_ULONG) {
710 ulong_val = strtoul(arg, &end, 0);
711 } else {
712 long_val = strtol(arg, &end, 0);
713 }
714 if (! (end == NULL((void*)0) || *end != '\0'))
715 /* Decimal number conversion succeed */
716 break;
717
718 /* If conversion for integer number failed, we are going to try
719 further integer number initialization in float-like style. */
720
721 case CFG_FLOAT:
722 case CFG_DOUBLE:
723 double_val = strtod(arg, &end);
724 if (*end)
725 return CFG_ERROR_BADNUMBER;
726
727 if (double_val == +HUGE_VAL(__builtin_huge_val()) || double_val == -HUGE_VAL(__builtin_huge_val()))
728 /* Purpously always return overflow error */
729 return f_integer ? CFG_ERROR_OVERFLOW : CFG_ERROR_OVERFLOW;
730#if HAVE_ERRNO_H1
731 if (double_val == 0.0 && errno(*__errno_location ()) == ERANGE34)
732#else
733 if (double_val == 0.0 && end == arg)
734#endif
735 /* Again always return overflow error */
736 return f_integer ? CFG_ERROR_OVERFLOW : CFG_ERROR_OVERFLOW;
737
738 /* Validating coversion results */
739 if (end == NULL((void*)0) || *end != '\0')
740 return CFG_ERROR_BADNUMBER;
741
742 if (! f_integer)
743 break;
744
745 if (type == CFG_ULONG) {
746 register double diff;
747 ulong_val = (unsigned long) double_val;
748 diff = double_val - (double) long_val;
749 if (diff >= 1.0 || diff <= -1.0)
750 return CFG_ERROR_OVERFLOW;
751 if (diff != 0.0)
752 return CFG_ERROR_BADNUMBER;
753 } else {
754 register double diff;
755 long_val = (long) double_val;
756 diff = double_val - (double) long_val;
757 if (diff >= 1.0 || diff <= -1.0)
758 return CFG_ERROR_OVERFLOW;
759 if (diff != 0.0)
760 return CFG_ERROR_BADNUMBER;
761 }
762 break;
763 }
764
765 /* Range checking and value storing. */
766 switch (type) {
767 default:
768 return CFG_ERROR_INTERNAL;
769 break;
770
771 case CFG_INT:
772 if (long_val >= INT_MAX2147483647 || long_val <= INT_MIN(-2147483647 -1))
773 return CFG_ERROR_OVERFLOW;
774
775 *((int *) where) = (int) long_val;
776 break;
777
778 case CFG_UINT:
779 if (long_val > UINT_MAX(2147483647 *2U +1U) || long_val < 0)
780 return CFG_ERROR_OVERFLOW;
781
782 *((unsigned int *) where) = (unsigned int) long_val;
783 break;
784
785 case CFG_LONG:
786 if (long_val == LONG_MIN(-9223372036854775807L -1L) || long_val == LONG_MAX9223372036854775807L)
787 return CFG_ERROR_OVERFLOW;
788
789 *((long *) where) = long_val;
790 break;
791
792 case CFG_ULONG:
793 /* Fix strange strtoul() behaviour. */
794 for (end = (char *) arg; isspace(*end)((*__ctype_b_loc ())[(int) ((*end))] & (unsigned short int
) _ISspace)
; end++) ;
795
796 /* Testing errno after strtoul() is not needed here. */
797 if (*end == '-' || ulong_val == ULONG_MAX(9223372036854775807L *2UL +1UL) /* || ulong_val == 0 */)
798 return CFG_ERROR_OVERFLOW;
799
800 *((unsigned long *) where) = (unsigned long) ulong_val;
801 break;
802
803 case CFG_FLOAT:
804#ifdef ABS /* Borrowed from popt library. */
805# undef ABS
806#endif
807#define ABS(a)(((a) < 0) ? -(a) : (a)) (((a) < 0) ? -(a) : (a))
808
809 if (double_val != 0.0)
810 if (ABS(double_val)(((double_val) < 0) ? -(double_val) : (double_val)) > FLT_MAX3.40282347e+38F || ABS(double_val)(((double_val) < 0) ? -(double_val) : (double_val)) < FLT_MIN1.17549435e-38F)
811 return CFG_ERROR_OVERFLOW;
812
813 *((float *) where) = (float) double_val;
814 break;
815
816 case CFG_DOUBLE:
817 *((double *) where) = (double) double_val;
818 break;
819 }
820
821 return CFG_OK;
822} /* }}} */
823
824/*
825 * split_multi_arg()
826 *
827 * Splits multi argument with separators with focusing on quotations.
828 * Returns cfg_error type and in ar is result array stored.
829 */
830
831 static int
832split_multi_arg(arg, ar, quote_prefix_ar, quote_postfix_ar, separator_ar)
833 char *arg;
834 char ***ar;
835 char **quote_prefix_ar;
836 char **quote_postfix_ar;
837 char **separator_ar;
838{ /* {{{ */
839 register int i;
840 int quote_idx, sep_size, tmp_sep_size;
841 char *p_quote, *p_sep, *tmp_s;
842 char *arg_base = arg;
843
844 if ((*ar = PLATON_FUNC(strdyn_create)strdyn_create()) == NULL((void*)0))
845 return CFG_ERROR_NOMEM;
846
847 do {
848
849 /* Searching first quotation string (p_quote)
850 and set quotation variables */
851 p_quote = PLATON_FUNC(strdyn_str2)strdyn_str2(arg, quote_prefix_ar, &quote_idx);
852 p_sep = NULL((void*)0); /* pointer to separator */
853 sep_size = 0; /* length of separator string */
854
855 /* Searching first separator string (p_sep) */
856 for (i = 0; separator_ar[i] != NULL((void*)0); i++) {
857 if ((tmp_s = PLATON_FUNC(str_white_str)str_white_str(arg, separator_ar[i], &tmp_sep_size))
858 != NULL((void*)0) && (p_sep == NULL((void*)0) || tmp_s < p_sep)) {
859 p_sep = tmp_s;
860 sep_size = tmp_sep_size;
861 }
862 }
863
864 /* Process quotation
865 if is is on lower position than separator */
866 if ((p_quote != NULL((void*)0) && p_sep == NULL((void*)0))
867 || (p_quote != NULL((void*)0) && p_sep != NULL((void*)0) && p_quote < p_sep)) {
868
869 register char *end_ptr, *prefix, *postfix;
870 register int prefix_len, postfix_len;
871
872 if (quote_idx < 0 /* not optimized */
873 || quote_idx > PLATON_FUNC(strdyn_get_size)strdyn_get_size(quote_prefix_ar) - 1
874 || quote_idx > PLATON_FUNC(strdyn_get_size)strdyn_get_size(quote_postfix_ar) - 1
875 || (prefix = quote_prefix_ar[quote_idx]) == NULL((void*)0)
876 || (postfix = quote_postfix_ar[quote_idx]) == NULL((void*)0))
877 return CFG_ERROR_INTERNAL;
878
879 prefix_len = strlen(prefix);
880 postfix_len = strlen(postfix);
881
882 memmove(p_quote, p_quote + prefix_len,
883 strlen(p_quote + prefix_len) + 1);
884
885 end_ptr = strstr(p_quote, postfix);
886
887 if (end_ptr == NULL((void*)0))
888 return CFG_ERROR_BADQUOTE;
889
890 memmove(end_ptr, end_ptr + postfix_len,
891 strlen(end_ptr + postfix_len) + 1);
892
893 arg = end_ptr;
894 }
895 /* Separator processing otherwise */
896 else if ((p_sep != NULL((void*)0) && p_quote == NULL((void*)0))
897 || (p_sep != NULL((void*)0) && p_quote != NULL((void*)0) && p_sep <= p_quote)) {
898
899 register char c;
900
901 c = *p_sep;
902 *p_sep = '\0';
903 *ar = PLATON_FUNC(strdyn_add_va)strdyn_add_va(*ar, arg_base, NULL((void*)0));
904 *p_sep = c;
905 arg = arg_base = p_sep + sep_size;
906
907 if (*ar == NULL((void*)0))
908 return CFG_ERROR_NOMEM;
909 }
910
911 } while (p_quote != NULL((void*)0) || p_sep != NULL((void*)0));
912
913 if ((*ar = PLATON_FUNC(strdyn_add_va)strdyn_add_va(*ar, arg_base, NULL((void*)0))) == NULL((void*)0))
914 return CFG_ERROR_NOMEM;
915
916 return CFG_OK;
917} /* }}} */
918
919/*
920 * unquote_single_arg()
921 *
922 * Unquotes signle argument passed by reference as arg parameter.
923 * Returns cfg_error type and modyfies arg parameter.
924 */
925
926 static int
927unquote_single_arg(arg, quote_prefix_ar, quote_postfix_ar)
928 char *arg;
929 char **quote_prefix_ar;
930 char **quote_postfix_ar;
931{ /* {{{ */
932 register char *p_quote;
933 int quote_idx;
934
935 do {
936 p_quote = PLATON_FUNC(strdyn_str2)strdyn_str2(arg, quote_prefix_ar, &quote_idx);
937
938 /* If beginning of quotation was found */
939 if (p_quote != NULL((void*)0)) {
940 register char *end_ptr, *prefix, *postfix;
941 register int prefix_len, postfix_len;
942
943 if (quote_idx < 0 /* not optimized */
944 || quote_idx > PLATON_FUNC(strdyn_get_size)strdyn_get_size(quote_prefix_ar) - 1
945 || quote_idx > PLATON_FUNC(strdyn_get_size)strdyn_get_size(quote_postfix_ar) - 1
946 || (prefix = quote_prefix_ar[quote_idx]) == NULL((void*)0)
947 || (postfix = quote_postfix_ar[quote_idx]) == NULL((void*)0))
948 return CFG_ERROR_INTERNAL;
949
950 prefix_len = strlen(prefix);
951 postfix_len = strlen(postfix);
952
953 memmove(p_quote, p_quote + prefix_len,
954 strlen(p_quote + prefix_len) + 1);
955
956 end_ptr = strstr(p_quote, postfix);
957
958 if (end_ptr == NULL((void*)0))
959 return CFG_ERROR_BADQUOTE;
960
961 memmove(end_ptr, end_ptr + postfix_len,
962 strlen(end_ptr + postfix_len) + 1);
963
964 arg = end_ptr;
965 }
966 } while (p_quote != NULL((void*)0));
967
968 return CFG_OK;
969} /* }}} */
970
971/* Modeline for ViM {{{
972 * vim:set ts=4:
973 * vim600:fdm=marker fdl=0 fdc=0:
974 * }}} */
975