2 * libcfg+ - precise command line & config file parsing library
4 * shared.c - shared stuff for command line and config file
5 * ____________________________________________________________
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.
12 * See README file for more information about this software.
13 * See COPYING file for license information.
15 * Download the latest version from
16 * http://platon.sk/projects/libcfg+/
19 /* $Platon: libcfg+/src/shared.c,v 1.36 2004/01/12 06:03:09 nepto Exp $ */
34 # if !STDC_HEADERS && HAVE_MEMORY_H
58 #include <platon/str/strplus.h>
59 #include <platon/str/strdyn.h>
64 /* Static function declarations {{{ */
65 static int search_cur_opt_idx(const CFG_CONTEXT con
);
66 static int add_to_used_opt_idx(const CFG_CONTEXT con
, int opt_idx
);
67 static int store_multi_arg(
69 const char **multi_arg
,
71 static int store_single_arg(
75 static int split_multi_arg(
78 char **quote_prefix_ar
,
79 char **quote_postfix_ar
,
81 static int unquote_single_arg(
83 char **quote_prefix_ar
,
84 char **quote_postfix_ar
);
92 __cfg_free_currents(con
)
93 const CFG_CONTEXT con
;
95 if (con
->cur_opt
!= NULL
)
97 if (con
->cur_arg
!= NULL
)
100 con
->cur_opt
= con
->cur_arg
= NULL
;
101 con
->cur_opt_type
= CFG_NONE_OPTION
;
105 __cfg_process_currents(con
, ret_val
, arg_used
)
106 const CFG_CONTEXT con
;
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
;
116 if (arg_used
!= NULL
)
119 opt_idx
= search_cur_opt_idx(con
);
121 #if defined(DEBUG) && DEBUG
122 fprintf(stderr
, "%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
? "[NULL]" : con
->cur_opt
,
127 con
->cur_arg
== NULL
? "[NULL]" : con
->cur_arg
,
128 opt_idx
, con
->cur_opt_type
);
130 if (con
->cur_opt_type
& CFG_LONG_OPTION
)
131 fputs("-LONG-", stderr
);
132 if (con
->cur_opt_type
& CFG_SHORT_OPTION
)
133 fputs("-SHORT-", stderr
);
134 if (con
->cur_opt_type
& CFG_SHORT_OPTIONS
)
135 fputs("-SHORTS-", stderr
);
136 if (con
->cur_opt_type
& CFG_LONG_SEPINIT
)
137 fputs("-SEPINIT-", stderr
);
139 fputs("]\n", stderr
);
143 return CFG_ERROR_UNKNOWN
; /* unknown option reached */
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
);
150 return CFG_ERROR_NOMEM
;
152 return CFG_ERROR_MULTI
;
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
);
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
];
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
];
177 switch (opt_data_type
) {
179 return CFG_ERROR_INTERNAL
;
182 /* Boolean data type */
185 if (con
->cur_opt_type
& CFG_LONG_SEPINIT
186 && con
->cur_arg
!= NULL
)
187 return CFG_ERROR_NOTALLOWEDARG
;
189 if (con
->options
[opt_idx
].value
!= NULL
)
190 (*((int *) con
->options
[opt_idx
].value
))++;
193 /* Numeric (int, long, float and double) data types */
202 if (con
->cur_arg
== NULL
)
203 return CFG_ERROR_NOARG
;
207 char *static_add
[2] = {NULL
, NULL
};
209 if (opt_f_multi_sep
) {
211 ret
= split_multi_arg(con
->cur_arg
, &add
,
212 quote_prefix_ar
, quote_postfix_ar
, separator_ar
);
215 PLATON_FUNC(strdyn_safe_free
)(add
);
221 add
[0] = con
->cur_arg
;
224 ret
= store_multi_arg(opt_data_type
,
226 con
->options
[opt_idx
].value
);
228 if (add
!= static_add
)
229 PLATON_FUNC(strdyn_free
)((char **) add
);
232 ret
= unquote_single_arg(con
->cur_arg
,
233 quote_prefix_ar
, quote_postfix_ar
);
238 ret
= store_single_arg(opt_data_type
, con
->cur_arg
,
239 con
->options
[opt_idx
].value
);
245 if (arg_used
!= NULL
)
249 /* String data type */
253 if (con
->cur_arg
== NULL
)
254 return CFG_ERROR_NOARG
;
256 if (con
->options
[opt_idx
].value
!= NULL
) {
259 p
= (char ***) con
->options
[opt_idx
].value
;
261 if (opt_f_multi_sep
) {
263 ret
= split_multi_arg(con
->cur_arg
, &ar
,
264 quote_prefix_ar
, quote_postfix_ar
,
268 PLATON_FUNC(strdyn_safe_free
)(ar
);
272 if ((*p
= PLATON_FUNC(strdyn_add_ar
)(*p
, ar
)) == NULL
)
273 return CFG_ERROR_NOMEM
;
275 PLATON_FUNC(strdyn_free
)(ar
);
278 ret
= unquote_single_arg(con
->cur_arg
,
279 quote_prefix_ar
, quote_postfix_ar
);
284 if ((*p
= PLATON_FUNC(strdyn_add
)(*p
, con
->cur_arg
)) == NULL
)
285 return CFG_ERROR_NOMEM
;
289 ret
= unquote_single_arg(con
->cur_arg
,
290 quote_prefix_ar
, quote_postfix_ar
);
295 *((char **) con
->options
[opt_idx
].value
) =
296 strdup(con
->cur_arg
);
300 if (arg_used
!= NULL
)
305 *ret_val
= con
->options
[opt_idx
].val
;
311 __cfg_cmdline_set_currents(con
)
312 const CFG_CONTEXT con
;
314 register int i
, size
;
315 register char *s
, *s_sep
, *s_tmp
;
318 size
= -1; /* size of matched prefix (0 is also valid) */
319 s
= con
->argv
[con
->cur_idx
]; /* string to scan */
321 /* Explicit `size_t' to `int' typecastings are required here near strlen()
322 calls, else strlen("") == 0 will be considered as smaller than -1. */
324 for (i
= 0; (ptr
= con
->prop
[CFG_LINE_SHORT_OPTION_PREFIX
][i
]) != NULL
; i
++)
325 if ((int) strlen(ptr
) > size
&& strstr(s
, ptr
) == s
) {
327 con
->cur_opt_type
= CFG_SHORT_OPTION
;
330 for (i
= 0; (ptr
= con
->prop
[CFG_LINE_LONG_OPTION_PREFIX
][i
]) != NULL
; i
++)
331 if ((int) strlen(ptr
) > size
&& strstr(s
, ptr
) == s
) {
333 con
->cur_opt_type
= CFG_LONG_OPTION
;
338 switch (con
->cur_opt_type
) {
340 case CFG_NONE_OPTION
: /* None option prefix */
343 case CFG_SHORT_OPTION
: /* Short option prefix */
345 s_sep
= strlen(s
) > 0 ? s
+ 1 : s
;
347 if (strlen(s_sep
) > 0) {
348 con
->cur_opt_type
+= CFG_SHORT_OPTIONS
;
350 if ((con
->cur_arg
= strdup(s_sep
)) == NULL
)
351 return CFG_ERROR_NOMEM
;
354 if (con
->argv
[con
->cur_idx
+ 1] != NULL
) {
355 con
->cur_arg
= strdup(con
->argv
[con
->cur_idx
+ 1]);
356 if (con
->cur_arg
== NULL
)
357 return CFG_ERROR_NOMEM
;
364 case CFG_LONG_OPTION
: /* Long option prefix */
368 for (i
= 0; (ptr
= con
->prop
[CFG_LINE_OPTION_ARG_SEPARATOR
][i
])
370 if ((s_tmp
= strstr(s
, ptr
)) != NULL
)
371 if (s_sep
== NULL
|| s_tmp
< s_sep
372 || (s_tmp
== s_sep
&& strlen(ptr
) > size
)) {
378 if (con
->argv
[con
->cur_idx
+ 1] != NULL
) {
379 con
->cur_arg
= strdup(con
->argv
[con
->cur_idx
+ 1]);
380 if (con
->cur_arg
== NULL
)
381 return CFG_ERROR_NOMEM
;
387 con
->cur_opt_type
+= CFG_LONG_SEPINIT
;
388 if ((con
->cur_arg
= strdup(s_sep
+ size
)) == NULL
)
389 return CFG_ERROR_NOMEM
;
394 s_sep
= s
+ strlen(s
);
396 con
->cur_opt
= (char *) malloc((s_sep
- s
+ 1) * sizeof(char));
397 if (con
->cur_opt
== NULL
)
398 return CFG_ERROR_NOMEM
;
400 strncpy(con
->cur_opt
, s
, s_sep
- s
);
401 con
->cur_opt
[s_sep
- s
] = '\0';
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
;
414 __cfg_cfgfile_set_currents(con
, buf
)
415 const CFG_CONTEXT con
;
419 register char *s_sep
, *s_tmp
;
424 for (pos
= con
->prop
[CFG_FILE_OPTION_ARG_SEPARATOR
];
425 pos
!= NULL
&& *pos
!= NULL
; pos
++) {
427 if ((s_tmp
= strstr(buf
, *pos
)) != NULL
)
428 if (s_sep
== NULL
|| s_tmp
< s_sep
429 || (s_tmp
== s_sep
&& strlen(*pos
) > size
)) {
438 con
->cur_opt
= strdup(buf
);
439 if (con
->cur_opt
== NULL
)
440 return CFG_ERROR_NOMEM
;
443 con
->cur_opt
= (char *) malloc((s_sep
- buf
+ 1) * sizeof(char));
444 if (con
->cur_opt
== NULL
)
445 return CFG_ERROR_NOMEM
;
447 strncpy(con
->cur_opt
, buf
, s_sep
- buf
);
448 con
->cur_opt
[s_sep
- buf
] = '\0';
450 if ((con
->cur_arg
= strdup(s_sep
+ size
)) == NULL
)
451 return CFG_ERROR_NOMEM
;
453 PLATON_FUNC(str_right_trim
)(con
->cur_opt
);
454 PLATON_FUNC(str_left_trim
)(con
->cur_arg
);
461 * STATIC PLATON_FUNCS
465 * search_cur_opt_idx()
467 * Function searches con->options for con->cur_opt.
468 * Returns index on success or -1 if not found.
472 search_cur_opt_idx(con
)
473 const CFG_CONTEXT con
;
477 for (i
= 0; con
->options
[i
].cmdline_long_name
!= NULL
478 || con
->options
[i
].cmdline_short_name
!= '\0'
479 || con
->options
[i
].cfgfile_name
!= NULL
480 || con
->options
[i
].type
!= CFG_END
481 || con
->options
[i
].value
!= NULL
482 || con
->options
[i
].val
!= 0;
485 if (con
->type
== CFG_CMDLINE
) { /* Command line context type */
486 if ((con
->cur_opt_type
& CFG_LONG_OPTION
&& con
->cur_opt
!= NULL
487 && con
->options
[i
].cmdline_long_name
!= NULL
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 */
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
))
498 else { /* Configuration file context type */
501 if (con
->cur_opt
!= NULL
502 && con
->options
[i
].cfgfile_name
!= NULL
503 && con
->cur_opt
== PLATON_FUNC(str_white_str
)(con
->cur_opt
,
504 (char *)(con
->options
[i
].cfgfile_name
), &len
)
505 && len
== strlen(con
->cur_opt
))
516 * Size of realloc() step for used_opt member of cfg_context structure.
517 * Value must be grater than 0.
520 #ifdef CFG_USED_OPT_IDX_STEP
521 # undef CFG_USED_OPT_IDX_STEP
524 #if defined(DEBUG) && DEBUG
525 # define CFG_USED_OPT_IDX_STEP (1)
527 # define CFG_USED_OPT_IDX_STEP (10)
531 * add_to_used_opt_idx()
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.
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.
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.
546 add_to_used_opt_idx(con
, opt_idx
)
547 const CFG_CONTEXT con
;
555 if (con
->used_opt_idx
!= NULL
)
556 for (p_i
= con
->used_opt_idx
; *p_i
>= 0; p_i
++)
560 if (p_i
== NULL
|| *p_i
== -255) {
562 register int new_size
;
564 new_size
= (p_i
== NULL
? 0 : p_i
- con
->used_opt_idx
)
565 + 1 + CFG_USED_OPT_IDX_STEP
;
567 con
->used_opt_idx
= (int *) realloc(con
->used_opt_idx
,
568 new_size
* sizeof(int));
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
);
575 if (con
->used_opt_idx
== NULL
)
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
++) ;
583 for (p_j
= p_i
; p_j
- p_i
< CFG_USED_OPT_IDX_STEP
; p_j
++)
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.
603 store_multi_arg(type
, multi_arg
, ar
)
605 const char **multi_arg
;
608 register int ptr_len
, item_len
;
609 register int size_plus
, size
;
614 return CFG_ERROR_INTERNAL
;
618 ptr_len
= sizeof(int *);
619 item_len
= sizeof(int);
623 ptr_len
= sizeof(unsigned int *);
624 item_len
= sizeof(unsigned int);
628 ptr_len
= sizeof(long *);
629 item_len
= sizeof(long);
633 ptr_len
= sizeof(unsigned long *);
634 item_len
= sizeof(unsigned long);
638 ptr_len
= sizeof(float *);
639 item_len
= sizeof(float);
643 ptr_len
= sizeof(double *);
644 item_len
= sizeof(double);
648 for (size_plus
= 0; multi_arg
[size_plus
] != NULL
; size_plus
++) ;
649 for (size
= 0; *ar
!= NULL
&& (*ar
)[size
] != NULL
; size
++) ;
651 *ar
= realloc(*ar
, (size
+ 1 + size_plus
) * ptr_len
);
654 return CFG_ERROR_NOMEM
;
656 /* Array terminated NULL pointer (end of array). */
657 (*ar
)[size
+ size_plus
] = NULL
;
659 for (k
= 0; k
< size_plus
; k
++) {
660 (*ar
)[size
+ k
] = malloc(item_len
);
661 if ((*ar
)[size
+ k
] == NULL
)
662 return CFG_ERROR_NOMEM
;
664 ret
= store_single_arg(type
, multi_arg
[k
], (*ar
)[size
+ k
]);
667 /* To prevent having random value at size + k position in *ar. */
668 (*ar
)[size
+ k
] = NULL
;
679 * According to option date type (type) parses and stores single argument (arg)
680 * to specified place pointed by where.
684 store_single_arg(type
, arg
, where
)
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? */
698 /* Conveting to numeric value. */
701 return CFG_ERROR_INTERNAL
;
709 if (type
== CFG_ULONG
) {
710 ulong_val
= strtoul(arg
, &end
, 0);
712 long_val
= strtol(arg
, &end
, 0);
714 if (! (end
== NULL
|| *end
!= '\0'))
715 /* Decimal number conversion succeed */
718 /* If conversion for integer number failed, we are going to try
719 further integer number initialization in float-like style. */
723 double_val
= strtod(arg
, &end
);
725 return CFG_ERROR_BADNUMBER
;
727 if (double_val
== +HUGE_VAL
|| double_val
== -HUGE_VAL
)
728 /* Purpously always return overflow error */
729 return f_integer
? CFG_ERROR_OVERFLOW
: CFG_ERROR_OVERFLOW
;
731 if (double_val
== 0.0 && errno
== ERANGE
)
733 if (double_val
== 0.0 && end
== arg
)
735 /* Again always return overflow error */
736 return f_integer
? CFG_ERROR_OVERFLOW
: CFG_ERROR_OVERFLOW
;
738 /* Validating coversion results */
739 if (end
== NULL
|| *end
!= '\0')
740 return CFG_ERROR_BADNUMBER
;
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
;
752 return CFG_ERROR_BADNUMBER
;
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
;
760 return CFG_ERROR_BADNUMBER
;
765 /* Range checking and value storing. */
768 return CFG_ERROR_INTERNAL
;
772 if (long_val
>= INT_MAX
|| long_val
<= INT_MIN
)
773 return CFG_ERROR_OVERFLOW
;
775 *((int *) where
) = (int) long_val
;
779 if (long_val
> UINT_MAX
|| long_val
< 0)
780 return CFG_ERROR_OVERFLOW
;
782 *((unsigned int *) where
) = (unsigned int) long_val
;
786 if (long_val
== LONG_MIN
|| long_val
== LONG_MAX
)
787 return CFG_ERROR_OVERFLOW
;
789 *((long *) where
) = long_val
;
793 /* Fix strange strtoul() behaviour. */
794 for (end
= (char *) arg
; isspace(*end
); end
++) ;
796 /* Testing errno after strtoul() is not needed here. */
797 if (*end
== '-' || ulong_val
== ULONG_MAX
/* || ulong_val == 0 */)
798 return CFG_ERROR_OVERFLOW
;
800 *((unsigned long *) where
) = (unsigned long) ulong_val
;
804 #ifdef ABS /* Borrowed from popt library. */
807 #define ABS(a) (((a) < 0) ? -(a) : (a))
809 if (double_val
!= 0.0)
810 if (ABS(double_val
) > FLT_MAX
|| ABS(double_val
) < FLT_MIN
)
811 return CFG_ERROR_OVERFLOW
;
813 *((float *) where
) = (float) double_val
;
817 *((double *) where
) = (double) double_val
;
827 * Splits multi argument with separators with focusing on quotations.
828 * Returns cfg_error type and in ar is result array stored.
832 split_multi_arg(arg
, ar
, quote_prefix_ar
, quote_postfix_ar
, separator_ar
)
835 char **quote_prefix_ar
;
836 char **quote_postfix_ar
;
840 int sep_ar_idx
, quote_idx
, sep_size
, tmp_sep_size
;
841 char *p_quote
, *p_sep
, *tmp_s
;
842 char *arg_base
= arg
;
844 if ((*ar
= PLATON_FUNC(strdyn_create
)()) == NULL
)
845 return CFG_ERROR_NOMEM
;
849 /* Searching first quotation string (p_quote)
850 and set quotation variables */
851 p_quote
= PLATON_FUNC(strdyn_str2
)(arg
, quote_prefix_ar
, "e_idx
);
852 p_sep
= NULL
; /* pointer to separator */
853 sep_ar_idx
= -1; /* index of separator */
854 sep_size
= 0; /* length of separator string */
856 /* Searching first separator string (p_sep) */
857 for (i
= 0; separator_ar
[i
] != NULL
; i
++) {
858 if ((tmp_s
= PLATON_FUNC(str_white_str
)(arg
, separator_ar
[i
], &tmp_sep_size
))
859 != NULL
&& (p_sep
== NULL
|| tmp_s
< p_sep
)) {
862 sep_size
= tmp_sep_size
;
867 if is is on lower position than separator */
868 if ((p_quote
!= NULL
&& p_sep
== NULL
)
869 || (p_quote
!= NULL
&& p_sep
!= NULL
&& p_quote
< p_sep
)) {
871 register char *end_ptr
, *prefix
, *postfix
;
872 register int prefix_len
, postfix_len
;
874 if (quote_idx
< 0 /* not optimized */
875 || quote_idx
> PLATON_FUNC(strdyn_get_size
)(quote_prefix_ar
) - 1
876 || quote_idx
> PLATON_FUNC(strdyn_get_size
)(quote_postfix_ar
) - 1
877 || (prefix
= quote_prefix_ar
[quote_idx
]) == NULL
878 || (postfix
= quote_postfix_ar
[quote_idx
]) == NULL
)
879 return CFG_ERROR_INTERNAL
;
881 prefix_len
= strlen(prefix
);
882 postfix_len
= strlen(postfix
);
884 memmove(p_quote
, p_quote
+ prefix_len
,
885 strlen(p_quote
+ prefix_len
) + 1);
887 end_ptr
= strstr(p_quote
, postfix
);
890 return CFG_ERROR_BADQUOTE
;
892 memmove(end_ptr
, end_ptr
+ postfix_len
,
893 strlen(end_ptr
+ postfix_len
) + 1);
897 /* Separator processing otherwise */
898 else if ((p_sep
!= NULL
&& p_quote
== NULL
)
899 || (p_sep
!= NULL
&& p_quote
!= NULL
&& p_sep
<= p_quote
)) {
905 *ar
= PLATON_FUNC(strdyn_add_va
)(*ar
, arg_base
, NULL
);
907 arg
= arg_base
= p_sep
+ sep_size
;
910 return CFG_ERROR_NOMEM
;
913 } while (p_quote
!= NULL
|| p_sep
!= NULL
);
915 if ((*ar
= PLATON_FUNC(strdyn_add_va
)(*ar
, arg_base
, NULL
)) == NULL
)
916 return CFG_ERROR_NOMEM
;
922 * unquote_single_arg()
924 * Unquotes signle argument passed by reference as arg parameter.
925 * Returns cfg_error type and modyfies arg parameter.
929 unquote_single_arg(arg
, quote_prefix_ar
, quote_postfix_ar
)
931 char **quote_prefix_ar
;
932 char **quote_postfix_ar
;
934 register char *p_quote
;
938 p_quote
= PLATON_FUNC(strdyn_str2
)(arg
, quote_prefix_ar
, "e_idx
);
940 /* If beginning of quotation was found */
941 if (p_quote
!= NULL
) {
942 register char *end_ptr
, *prefix
, *postfix
;
943 register int prefix_len
, postfix_len
;
945 if (quote_idx
< 0 /* not optimized */
946 || quote_idx
> PLATON_FUNC(strdyn_get_size
)(quote_prefix_ar
) - 1
947 || quote_idx
> PLATON_FUNC(strdyn_get_size
)(quote_postfix_ar
) - 1
948 || (prefix
= quote_prefix_ar
[quote_idx
]) == NULL
949 || (postfix
= quote_postfix_ar
[quote_idx
]) == NULL
)
950 return CFG_ERROR_INTERNAL
;
952 prefix_len
= strlen(prefix
);
953 postfix_len
= strlen(postfix
);
955 memmove(p_quote
, p_quote
+ prefix_len
,
956 strlen(p_quote
+ prefix_len
) + 1);
958 end_ptr
= strstr(p_quote
, postfix
);
961 return CFG_ERROR_BADQUOTE
;
963 memmove(end_ptr
, end_ptr
+ postfix_len
,
964 strlen(end_ptr
+ postfix_len
) + 1);
968 } while (p_quote
!= NULL
);
973 /* Modeline for ViM {{{
975 * vim600:fdm=marker fdl=0 fdc=0: