| version 1.8, 2001/11/30 02:10:27 |
version 1.9, 2001/12/01 01:27:47 |
|
|
| static int cfg_cmdline_get_next_opt(const CFG_CONTEXT con); |
static int cfg_cmdline_get_next_opt(const CFG_CONTEXT con); |
| static void free_currents(const CFG_CONTEXT con); |
static void free_currents(const CFG_CONTEXT con); |
| static int set_currents(const CFG_CONTEXT con); |
static int set_currents(const CFG_CONTEXT con); |
| static int search_cur_opt(const CFG_CONTEXT con); |
static int search_cur_opt_idx(const CFG_CONTEXT con); |
| static int add_to_used_opt_idx(const CFG_CONTEXT con, int opt_idx); |
static int add_to_used_opt_idx(const CFG_CONTEXT con, int opt_idx); |
| |
static int store_multi_arg(const int type, const char **multi_arg, void ***ar); |
| |
static int store_single_arg(const int type, const char *arg, const void *where); |
| |
|
| |
|
| static int cfg_cmdline_get_next_opt(const CFG_CONTEXT con) { |
static int cfg_cmdline_get_next_opt(const CFG_CONTEXT con) { |
| Line 20 static int cfg_cmdline_get_next_opt(cons |
|
| Line 22 static int cfg_cmdline_get_next_opt(cons |
|
| register int opt_idx; |
register int opt_idx; |
| register int arg_used; |
register int arg_used; |
| |
|
| register int opt_data_type, opt_f_multi, opt_f_multi_sep, opt_f_leftover; |
register int opt_data_type, opt_f_multi, opt_f_multi_sep; |
| |
|
| while (1) { |
while (1) { |
| |
|
| Line 59 static int cfg_cmdline_get_next_opt(cons |
|
| Line 61 static int cfg_cmdline_get_next_opt(cons |
|
| return CFG_ERROR_NOMEM; |
return CFG_ERROR_NOMEM; |
| } |
} |
| |
|
| opt_idx = search_cur_opt(con); |
opt_idx = search_cur_opt_idx(con); |
| |
|
| #if defined(DEBUG) && DEBUG |
#if defined(DEBUG) && DEBUG |
| fprintf(stderr, "--\nDEBUG|%d|%s|%s|%s|%d|flags=%x(", |
fprintf(stderr, "--\nDEBUG|%d|%s|%s|%s|%d|flags=%x[", |
| con->cur_idx, con->argv[con->cur_idx], |
con->cur_idx, con->argv[con->cur_idx], |
| con->cur_opt == NULL ? "[NULL]" : con->cur_opt, |
con->cur_opt == NULL ? "[NULL]" : con->cur_opt, |
| con->cur_arg == NULL ? "[NULL]" : con->cur_arg, |
con->cur_arg == NULL ? "[NULL]" : con->cur_arg, |
| Line 77 static int cfg_cmdline_get_next_opt(cons |
|
| Line 79 static int cfg_cmdline_get_next_opt(cons |
|
| if (con->cur_opt_type & CFG_LONG_SEPINIT) |
if (con->cur_opt_type & CFG_LONG_SEPINIT) |
| fputs("-SEPINIT-", stderr); |
fputs("-SEPINIT-", stderr); |
| |
|
| fputs(")\n", stderr); |
fputs("]\n", stderr); |
| #endif |
#endif |
| |
|
| if (opt_idx < 0) |
if (opt_idx < 0) { |
| return CFG_ERROR_UNKNOWN; |
return CFG_ERROR_UNKNOWN; |
| |
} |
| |
|
| if ( ! (con->flags & CFG_IGNORE_MULTI) |
if ( ! (con->flags & CFG_IGNORE_MULTI) |
| && ! (con->options[opt_idx].type & CFG_MULTI)) { |
&& ! (con->options[opt_idx].type & CFG_MULTI)) { |
| Line 101 static int cfg_cmdline_get_next_opt(cons |
|
| Line 104 static int cfg_cmdline_get_next_opt(cons |
|
| opt_f_multi = con->options[opt_idx].type & CFG_MULTI; |
opt_f_multi = con->options[opt_idx].type & CFG_MULTI; |
| opt_f_multi_sep = con->options[opt_idx].type & |
opt_f_multi_sep = con->options[opt_idx].type & |
| (CFG_MULTI_SEPARATED & ~CFG_MULTI); |
(CFG_MULTI_SEPARATED & ~CFG_MULTI); |
| opt_f_leftover = con->options[opt_idx].type & CFG_LEFTOVER_ARGS; |
/* opt_f_leftover = con->options[opt_idx].type & CFG_LEFTOVER_ARGS; */ |
| |
|
| switch (opt_data_type) { |
switch (opt_data_type) { |
| default: |
default: |
| return CFG_ERROR_INTERNAL; |
return CFG_ERROR_INTERNAL; |
| break; |
break; |
| |
|
| /* |
/* Boolean data type. */ |
| * Boolean data type. |
|
| */ |
|
| |
|
| case CFG_BOOLEAN: |
case CFG_BOOLEAN: |
| if (con->cur_opt_type & CFG_LONG_SEPINIT |
if (con->cur_opt_type & CFG_LONG_SEPINIT |
| Line 121 static int cfg_cmdline_get_next_opt(cons |
|
| Line 122 static int cfg_cmdline_get_next_opt(cons |
|
| (*((int *)con->options[opt_idx].value))++; |
(*((int *)con->options[opt_idx].value))++; |
| break; |
break; |
| |
|
| /* |
/* Numeric (int, long, float and double) data types. */ |
| * Integer, unsigned integer and long data type. |
|
| */ |
|
| |
|
| case CFG_INTEGER: |
case CFG_INT: |
| case CFG_UNSIGNED_INT: |
case CFG_UINT: |
| case CFG_LONG: |
case CFG_LONG: |
| |
case CFG_ULONG: |
| if (con->cur_arg == NULL) |
|
| return CFG_ERR_NOARG; |
|
| |
|
| { |
|
| register long value; |
|
| char *end; |
|
| |
|
| value = strtol(con->cur_arg, &end, 0); |
|
| if (!(end && *end == '\0')) |
|
| return CFG_ERROR_BADNUMBER; |
|
| |
|
| if (opt_data_type == CFG_LONG) { |
|
| if (value == LONG_MIN || value == LONG_MAX) |
|
| return CFG_ERROR_OVERFLOW; |
|
| |
|
| if (con->options[opt_idx].value != NULL) |
|
| *((long *)con->options[opt_idx].value) = value; |
|
| } |
|
| else if (opt_data_type == CFG_UNSIGNED_INT) { |
|
| if (value > UINT_MAX || value < 0) |
|
| return CFG_ERROR_OVERFLOW; |
|
| |
|
| if (con->options[opt_idx].value != NULL) |
|
| *((unsigned int *)con->options[opt_idx].value) = |
|
| (unsigned int) value; |
|
| } |
|
| else { |
|
| |
|
| if (value >= INT_MAX || value <= INT_MIN) |
|
| return CFG_ERROR_OVERFLOW; |
|
| |
|
| if (con->options[opt_idx].value != NULL) |
|
| *((int *)con->options[opt_idx].value) = |
|
| (int) value; |
|
| } |
|
| } |
|
| |
|
| arg_used = 1; |
|
| break; |
|
| |
|
| /* |
|
| * Unsigned long data type |
|
| */ |
|
| |
|
| case CFG_UNSIGNED_LONG: |
|
| |
|
| if (con->cur_arg == NULL) |
|
| return CFG_ERR_NOARG; |
|
| |
|
| { |
|
| register long value; |
|
| char *end; |
|
| |
|
| value = strtoul(con->cur_arg, &end, 0); |
|
| if (!(end && *end == '\0')) |
|
| return CFG_ERROR_BADNUMBER; |
|
| |
|
| /* Fix strange strtoul() behaviour. */ |
|
| for (end = con->cur_arg; isspace(*end); end++) ; |
|
| |
|
| /* Testing errno after strtoul() is not needed here. */ |
|
| if (*end == '-' || value == ULONG_MAX /* || value == 0 */) |
|
| return CFG_ERROR_OVERFLOW; |
|
| |
|
| if (con->options[opt_idx].value != NULL) |
|
| *((unsigned long *)con->options[opt_idx].value) = value; |
|
| } |
|
| |
|
| arg_used = 1; |
|
| break; |
|
| |
|
| /* |
|
| * Float and double data type. |
|
| */ |
|
| |
|
| case CFG_FLOAT: |
case CFG_FLOAT: |
| case CFG_DOUBLE: |
case CFG_DOUBLE: |
| |
|
| Line 211 static int cfg_cmdline_get_next_opt(cons |
|
| Line 135 static int cfg_cmdline_get_next_opt(cons |
|
| return CFG_ERR_NOARG; |
return CFG_ERR_NOARG; |
| |
|
| { |
{ |
| double value; |
register int ret; |
| char *end; |
|
| |
|
| value = strtod(con->cur_arg, &end); |
if (opt_f_multi) { |
| if (*end) |
char **add; |
| return CFG_ERROR_BADNUMBER; |
char *static_add[2] = { NULL, NULL }; |
| |
|
| if (value == +HUGE_VAL || value == -HUGE_VAL) |
|
| return CFG_ERROR_OVERFLOW; |
|
| if (value == 0.0 && errno == ERANGE) |
|
| return CFG_ERROR_OVERFLOW; |
|
| |
|
| if (opt_data_type == CFG_FLOAT) { |
if (opt_f_multi_sep) { |
| #ifdef ABS /* Borrowed from popt library. */ |
add = strdyn_explode_ar(con->cur_arg, |
| # undef ABS |
con->multi_separator); |
| #endif |
if (add == NULL) |
| #define ABS(a) (((a) < 0) ? -(a) : (a)) |
return CFG_ERROR_NOMEM; |
| |
} |
| |
else { |
| |
add = static_add; |
| |
add[0] = con->cur_arg; |
| |
} |
| |
|
| if (ABS(value) > FLT_MAX) |
ret = store_multi_arg(opt_data_type, |
| return CFG_ERROR_OVERFLOW; |
(const char **) add, |
| if (ABS(value) < FLT_MIN) |
con->options[opt_idx].value); |
| return CFG_ERROR_OVERFLOW; |
|
| |
if (add != static_add) |
| if (con->options[opt_idx].value != NULL) |
strdyn_free((char **) add); |
| *((float *)con->options[opt_idx].value) = |
|
| (float) value; |
|
| } |
|
| else { /* type == CFG_DOUBLE */ |
|
| if (con->options[opt_idx].value != NULL) |
|
| *((double *)con->options[opt_idx].value) = value; |
|
| } |
} |
| |
else |
| |
ret = store_single_arg(opt_data_type, con->cur_arg, |
| |
con->options[opt_idx].value); |
| |
|
| |
if (ret != CFG_OK) |
| |
return ret; |
| } |
} |
| |
|
| arg_used = 1; |
arg_used = 1; |
| break; |
break; |
| |
|
| /* |
/* String data type. */ |
| * String data type. |
|
| */ |
|
| |
|
| case CFG_STRING: |
case CFG_STRING: |
| |
|
| Line 258 static int cfg_cmdline_get_next_opt(cons |
|
| Line 179 static int cfg_cmdline_get_next_opt(cons |
|
| |
|
| if (con->options[opt_idx].value != NULL) { |
if (con->options[opt_idx].value != NULL) { |
| if (opt_f_multi) { |
if (opt_f_multi) { |
| char ***p = (char ***)con->options[opt_idx].value; |
register char ***p; |
| if (opt_f_multi_sep) { |
p = (char ***)con->options[opt_idx].value; |
| /* TODO: split by all multi_separator[] |
|
| for (register int i = 0; |
|
| con->multi_separator[i] != NULL; i++) |
|
| */ |
|
| char **ar; |
|
| |
|
| ar = strdyn_explode_str(con->cur_arg, |
if (opt_f_multi_sep) { |
| con->multi_separator[0]); |
register char **ar; |
| |
|
| |
ar = strdyn_explode_ar(con->cur_arg, |
| |
con->multi_separator); |
| if (ar == NULL) |
if (ar == NULL) |
| return CFG_ERROR_NOMEM; |
return CFG_ERROR_NOMEM; |
| |
|
| Line 293 static int cfg_cmdline_get_next_opt(cons |
|
| Line 211 static int cfg_cmdline_get_next_opt(cons |
|
| |
|
| if (arg_used) { |
if (arg_used) { |
| if (! (con->cur_opt_type & CFG_LONG_SEPINIT) |
if (! (con->cur_opt_type & CFG_LONG_SEPINIT) |
| && !(con->cur_opt_type & CFG_SHORT_OPTIONS)) |
&& !(con->cur_opt_type & CFG_SHORT_OPTIONS) |
| |
&& !(con->cur_opt_type == CFG_NONE_OPTION)) |
| { |
{ |
| puts("[1] argument used, moving cur_idx"); |
puts("[1] argument used, moving cur_idx"); |
| con->cur_idx_tmp++; |
con->cur_idx_tmp++; |
| Line 424 static int set_currents(const CFG_CONTEX |
|
| Line 343 static int set_currents(const CFG_CONTEX |
|
| s_sep = s + strlen(s); |
s_sep = s + strlen(s); |
| |
|
| con->cur_opt = (char *) malloc((s_sep - s + 1) * sizeof(char)); |
con->cur_opt = (char *) malloc((s_sep - s + 1) * sizeof(char)); |
| if (con->cur_opt != NULL) { |
if (con->cur_opt == NULL) |
| strncpy(con->cur_opt, s, s_sep - s); |
|
| con->cur_opt[s_sep - s] = '\0'; |
|
| } |
|
| else |
|
| return 0; |
return 0; |
| |
|
| |
strncpy(con->cur_opt, s, s_sep - s); |
| |
con->cur_opt[s_sep - s] = '\0'; |
| |
|
| |
if (con->cur_opt_type == CFG_NONE_OPTION) { |
| |
register char *tmp_str; |
| |
|
| |
tmp_str =con->cur_opt; |
| |
con->cur_opt = con->cur_arg; |
| |
con->cur_arg = tmp_str; |
| |
} |
| |
|
| return 1; |
return 1; |
| } |
} |
| |
|
| /* |
/* |
| * search_cur_opt() |
* search_cur_opt_idx() |
| * |
* |
| * Function searches con->options for con->cur_opt. |
* Function searches con->options for con->cur_opt. |
| * Returns index on success or -1 if not found. |
* Returns index on success or -1 if not found. |
| */ |
*/ |
| |
|
| static int search_cur_opt(const CFG_CONTEXT con) { |
static int search_cur_opt_idx(const CFG_CONTEXT con) { |
| register int i; |
register int i; |
| |
|
| for (i = 0; con->options[i].cmdline_long_name != NULL |
for (i = 0; con->options[i].cmdline_long_name != NULL |
| Line 452 static int search_cur_opt(const CFG_CONT |
|
| Line 378 static int search_cur_opt(const CFG_CONT |
|
| || con->options[i].val != 0; |
|| con->options[i].val != 0; |
| i++) |
i++) |
| { |
{ |
| /* |
|
| printf("cur_opt = %s, long_name = %s, short_name = %c\n", |
|
| con->cur_opt, |
|
| con->options[i].cmdline_long_name, |
|
| con->options[i].cmdline_short_name); |
|
| */ |
|
| |
|
| if ((con->cur_opt_type & CFG_LONG_OPTION && ! strcmp(con->cur_opt, |
if ((con->cur_opt_type & CFG_LONG_OPTION && con->cur_opt != NULL |
| |
&& con->options[i].cmdline_long_name != NULL |
| |
&& ! strcmp(con->cur_opt, |
| con->options[i].cmdline_long_name)) |
con->options[i].cmdline_long_name)) |
| || (con->cur_opt_type & CFG_SHORT_OPTION && |
|| (con->cur_opt_type & CFG_SHORT_OPTION && |
| con->cur_opt[0] == |
con->cur_opt[0] == |
| Line 543 static int add_to_used_opt_idx(const CFG |
|
| Line 465 static int add_to_used_opt_idx(const CFG |
|
| return 0; |
return 0; |
| } |
} |
| |
|
| |
/* |
| |
* store_multi_arg() |
| |
* |
| |
* According to option date type (type) parses and stores multiple arguments |
| |
* (multi_arg) by adding to *ar dynamic array. Array resizing is done as first |
| |
* and than is store_single_arg() function called with appropriate parameters. |
| |
*/ |
| |
|
| |
static int store_multi_arg(const int type, const char **multi_arg, void ***ar) |
| |
{ |
| |
register int ptr_len, item_len; |
| |
register int size_plus, size; |
| |
register int k, ret; |
| |
|
| |
switch (type) { |
| |
default: |
| |
return CFG_ERROR_INTERNAL; |
| |
break; |
| |
|
| |
case CFG_INT: |
| |
ptr_len = sizeof(int *); |
| |
item_len = sizeof(int); |
| |
break; |
| |
|
| |
case CFG_UINT: |
| |
ptr_len = sizeof(unsigned int *); |
| |
item_len = sizeof(unsigned int); |
| |
break; |
| |
|
| |
case CFG_LONG: |
| |
ptr_len = sizeof(long *); |
| |
item_len = sizeof(long); |
| |
break; |
| |
|
| |
case CFG_ULONG: |
| |
ptr_len = sizeof(unsigned long *); |
| |
item_len = sizeof(unsigned long); |
| |
break; |
| |
|
| |
case CFG_FLOAT: |
| |
ptr_len = sizeof(float *); |
| |
item_len = sizeof(float); |
| |
break; |
| |
|
| |
case CFG_DOUBLE: |
| |
ptr_len = sizeof(double *); |
| |
item_len = sizeof(double); |
| |
break; |
| |
} |
| |
|
| |
for (size_plus = 0; multi_arg[size_plus] != NULL; size_plus++) ; |
| |
for (size = 0; *ar != NULL && (*ar)[size] != NULL; size++) ; |
| |
|
| |
*ar = realloc(*ar, (size + 1 + size_plus) * ptr_len); |
| |
|
| |
if (*ar == NULL) |
| |
return CFG_ERROR_NOMEM; |
| |
|
| |
/* Array terminated NULL pointer (end of array). */ |
| |
(*ar)[size + size_plus] = NULL; |
| |
|
| |
for (k = 0; k < size_plus; k++) { |
| |
(*ar)[size + k] = malloc(item_len); |
| |
if ((*ar)[size + k] == NULL) |
| |
return CFG_ERROR_NOMEM; |
| |
|
| |
ret = store_single_arg(type, multi_arg[k], (*ar)[size + k]); |
| |
|
| |
if (ret != CFG_OK) { |
| |
/* To prevent having random value at size + k position in *ar. */ |
| |
(*ar)[size + k] = NULL; |
| |
return ret; |
| |
} |
| |
} |
| |
|
| |
return CFG_OK; |
| |
} |
| |
|
| |
/* |
| |
* store_single_arg() |
| |
* |
| |
* According to option date type (type) parses and stores single argument (arg) |
| |
* to specified place pointed by where. |
| |
*/ |
| |
|
| |
static int store_single_arg(const int type, const char *arg, const void *where) |
| |
{ |
| |
register long long_val = 0; |
| |
register unsigned long ulong_val = 0; |
| |
register double double_val = 0.0; |
| |
char *end; |
| |
|
| |
if (where == NULL) |
| |
return CFG_OK; |
| |
|
| |
/* Conveting to numeric value. */ |
| |
switch (type) { |
| |
default: |
| |
return CFG_ERROR_INTERNAL; |
| |
break; |
| |
|
| |
case CFG_INT: |
| |
case CFG_UINT: |
| |
case CFG_LONG: |
| |
long_val = strtol(arg, &end, 0); |
| |
break; |
| |
|
| |
case CFG_ULONG: |
| |
ulong_val = strtoul(arg, &end, 0); |
| |
break; |
| |
|
| |
case CFG_FLOAT: |
| |
case CFG_DOUBLE: |
| |
double_val = strtod(arg, &end); |
| |
if (*end) |
| |
return CFG_ERROR_BADNUMBER; |
| |
|
| |
if (double_val == +HUGE_VAL || double_val == -HUGE_VAL) |
| |
return CFG_ERROR_OVERFLOW; |
| |
if (double_val == 0.0 && errno == ERANGE) |
| |
return CFG_ERROR_OVERFLOW; |
| |
break; |
| |
} |
| |
|
| |
/* Validating coversion results. */ |
| |
if (!(end && *end == '\0')) |
| |
return CFG_ERROR_BADNUMBER; |
| |
|
| |
/* Range checking and value storing. */ |
| |
switch (type) { |
| |
default: |
| |
return CFG_ERROR_INTERNAL; |
| |
break; |
| |
|
| |
case CFG_INT: |
| |
if (long_val >= INT_MAX || long_val <= INT_MIN) |
| |
return CFG_ERROR_OVERFLOW; |
| |
|
| |
*((int *) where) = (int) long_val; |
| |
break; |
| |
|
| |
case CFG_UINT: |
| |
if (long_val > UINT_MAX || long_val < 0) |
| |
return CFG_ERROR_OVERFLOW; |
| |
|
| |
*((unsigned int *) where) = (unsigned int) long_val; |
| |
break; |
| |
|
| |
case CFG_LONG: |
| |
if (long_val == LONG_MIN || long_val == LONG_MAX) |
| |
return CFG_ERROR_OVERFLOW; |
| |
|
| |
*((long *) where) = long_val; |
| |
break; |
| |
|
| |
case CFG_ULONG: |
| |
/* Fix strange strtoul() behaviour. */ |
| |
for (end = (char *) arg; isspace(*end); end++) ; |
| |
|
| |
/* Testing errno after strtoul() is not needed here. */ |
| |
if (*end == '-' || ulong_val == ULONG_MAX /* || ulong_val == 0 */) |
| |
return CFG_ERROR_OVERFLOW; |
| |
|
| |
*((unsigned long *) where) = (unsigned long) ulong_val; |
| |
break; |
| |
|
| |
case CFG_FLOAT: |
| |
#ifdef ABS /* Borrowed from popt library. */ |
| |
# undef ABS |
| |
#endif |
| |
#define ABS(a) (((a) < 0) ? -(a) : (a)) |
| |
|
| |
if (double_val != 0.0) |
| |
if (ABS(double_val) > FLT_MAX || ABS(double_val) < FLT_MIN) |
| |
return CFG_ERROR_OVERFLOW; |
| |
|
| |
*((float *) where) = (float) double_val; |
| |
break; |
| |
|
| |
case CFG_DOUBLE: |
| |
*((double *) where) = (double) double_val; |
| |
break; |
| |
} |
| |
|
| |
return CFG_OK; |
| |
} |
| |
|