| version 1.1, 2001/10/03 19:12:04 |
version 1.2, 2001/10/23 00:05:18 |
|
|
| |
/* TODO: ./configure check HAVE_FLOAT_H je dolezity!!! */ |
| |
/* no uz ani nie, ked mam limits.h :P */ |
| |
|
| |
#include <limits.h> |
| |
|
| |
|
| |
static int cfg_cmdline_get_next_opt(const CFG_CONTEXT con); |
| |
static void free_currents(const CFG_CONTEXT con); |
| |
static int set_currents(const CFG_CONTEXT con); |
| |
static int search_cur_opt(const CFG_CONTEXT con); |
| |
|
| |
|
| |
static int cfg_cmdline_get_next_opt(const CFG_CONTEXT con) { |
| |
|
| |
/* |
| |
while (con->argv[con->cur_idx] != NULL && con->argc > con->cur_idx) { |
| |
|
| |
if (set_currents(con) == 0) |
| |
return CFG_ERROR_NOMEM; |
| |
|
| |
printf("DEBUG|%d|%s|%s|%s|%s|\n", con->cur_idx, con->argv[con->cur_idx], |
| |
con->cur_opt_type ? con->cur_opt_type == 1 |
| |
? "SHORT" : "LONG" |
| |
: "NONE", |
| |
con->cur_opt == NULL ? "[NULL]" : con->cur_opt, |
| |
con->cur_arg == NULL ? "[NULL]" : con->cur_arg); |
| |
|
| |
free_currents(con); |
| |
|
| |
con->cur_idx++; |
| |
} |
| |
|
| |
return 0; |
| |
*/ |
| |
|
| |
register int opt_idx; |
| |
|
| |
char cur_opt_types[][10] = { "NONE", "SHORT", "SHORTS", "LONG" }; |
| |
|
| |
while (con->argv[con->cur_idx] != NULL) { |
| |
|
| |
if (con->cur_opt_type == CFG_SHORT_OPTIONS) { |
| |
con->cur_opt[0] = con->cur_arg[0]; |
| |
strdel(con->cur_arg); |
| |
|
| |
if (strlen(con->cur_arg) == 0) { |
| |
con->cur_opt_type = CFG_SHORT_OPTION; |
| |
free(con->cur_arg); |
| |
con->cur_arg = strdup(con->argv[con->cur_idx + 1]); |
| |
} |
| |
} |
| |
else { |
| |
free_currents(con); |
| |
|
| |
if (set_currents(con) == 0) |
| |
return CFG_ERROR_NOMEM; |
| |
} |
| |
|
| |
opt_idx = search_cur_opt(con); |
| |
|
| |
fprintf(stderr, "DEBUG|%d|%s|%s|%s|%s|%d|\n", |
| |
con->cur_idx, con->argv[con->cur_idx], |
| |
cur_opt_types[con->cur_opt_type], |
| |
con->cur_opt == NULL ? "[NULL]" : con->cur_opt, |
| |
con->cur_arg == NULL ? "[NULL]" : con->cur_arg, |
| |
opt_idx); |
| |
|
| |
if (opt_idx < 0) |
| |
return CFG_ERROR_UNKNOWN; |
| |
|
| |
switch (con->options[opt_idx].type) { |
| |
default: |
| |
return CFG_ERROR_INTERNAL; |
| |
break; |
| |
|
| |
case CFG_BOOLEAN: |
| |
if (con->cur_opt_type & CFG_LONG_SEPINIT |
| |
&& con->cur_arg != NULL) |
| |
return CFG_ERROR_NOTALLOWEDARG; |
| |
|
| |
if (con->options[opt_idx].value != NULL) |
| |
*((int *)con->options[opt_idx].value) = 1; |
| |
break; |
| |
|
| |
case CFG_INTEGER: |
| |
case CFG_UNSIGNED_INT: |
| |
case CFG_LONG: |
| |
/* |
| |
case POPT_ARG_INT: |
| |
case POPT_ARG_LONG: |
| |
{ long aLong = 0; |
| |
char *end; |
| |
|
| |
if (con->os->nextArg) { |
| |
aLong = strtol(con->os->nextArg, &end, 0); |
| |
if (!(end && *end == '\0')) |
| |
return POPT_ERROR_BADNUMBER; |
| |
} |
| |
|
| |
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) { |
| |
if (aLong == LONG_MIN || aLong == LONG_MAX) |
| |
return POPT_ERROR_OVERFLOW; |
| |
if (poptSaveLong(opt, aLong)) |
| |
return POPT_ERROR_BADOPERATION; |
| |
} else { |
| |
if (aLong > INT_MAX || aLong < INT_MIN) |
| |
return POPT_ERROR_OVERFLOW; |
| |
if (poptSaveInt(opt, aLong)) |
| |
return POPT_ERROR_BADOPERATION; |
| |
} |
| |
} break; |
| |
|
| |
*/ |
| |
{ |
| |
register long value; |
| |
char *end; |
| |
|
| |
value = strtol(con->cur_arg, &end, 0); |
| |
if (!(end && *end == '\0')) |
| |
return CFG_ERROR_BADNUMBER; |
| |
|
| |
if (con->options[opt_idx].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 (con->options[opt_idx].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) = |
| |
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) = value; |
| |
} |
| |
|
| |
if (! (con->cur_opt_type & CFG_LONG_SEPINIT)) { |
| |
puts("not sepinit"); |
| |
con->cur_idx++; |
| |
} |
| |
} |
| |
|
| |
break; |
| |
|
| |
case CFG_UNSIGNED_LONG: |
| |
break; |
| |
|
| |
case CFG_FLOAT: |
| |
break; |
| |
|
| |
case CFG_DOUBLE: |
| |
/* |
| |
case POPT_ARG_FLOAT: |
| |
case POPT_ARG_DOUBLE: |
| |
{ double aDouble = 0.0; |
| |
char *end; |
| |
|
| |
if (con->os->nextArg) { |
| |
aDouble = strtod(con->os->nextArg, &end); |
| |
if (*end) |
| |
return POPT_ERROR_BADNUMBER; |
| |
} |
| |
|
| |
if (aDouble == +HUGE_VAL || aDouble == -HUGE_VAL) |
| |
return POPT_ERROR_OVERFLOW; |
| |
if (aDouble == 0.0 && errno == ERANGE) |
| |
return POPT_ERROR_OVERFLOW; |
| |
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_DOUBLE) { |
| |
*((double *) opt->arg) = aDouble; |
| |
} else { |
| |
#ifdef ABS |
| |
#undef ABS |
| |
#endif |
| |
#define ABS(a) (((a) < 0) ? -(a) : (a)) |
| |
if (ABS(aDouble) > FLT_MAX) |
| |
return POPT_ERROR_OVERFLOW; |
| |
if (ABS(aDouble) < FLT_MIN) |
| |
return POPT_ERROR_OVERFLOW; |
| |
*((float *) opt->arg) = aDouble; |
| |
} |
| |
} break; |
| |
*/ |
| |
break; |
| |
|
| |
case CFG_STRING: |
| |
break; |
| |
} |
| |
|
| |
if (con->cur_opt_type != CFG_SHORT_OPTIONS) |
| |
con->cur_idx++; |
| |
|
| |
if (con->options[opt_idx].val != 0) |
| |
return con->options[opt_idx].val; |
| |
} |
| |
|
| |
return CFG_OK; |
| |
} |
| |
|
| |
static void free_currents(const CFG_CONTEXT con) { |
| |
|
| |
if (con->cur_opt != NULL) |
| |
free(con->cur_opt); |
| |
if (con->cur_arg != NULL) |
| |
free(con->cur_arg); |
| |
|
| |
con->cur_opt_type = CFG_NONE_OPTION; |
| |
|
| |
con->cur_opt = con->cur_arg = NULL; |
| |
} |
| |
|
| |
|
| |
/* |
| |
* set_curents() |
| |
* |
| |
* Function allocate and initialize variables con->cur_opt and con->cur_arg |
| |
* according to con->argv[con->cur_idx]. |
| |
* Returns 1 on success, 0 on error (not enough memory). |
| |
*/ |
| |
|
| |
static int set_currents(const CFG_CONTEXT con) { |
| |
register int i, size; |
| |
register char *s, *s_sep, *s_tmp; |
| |
|
| |
size = 0; |
| |
s = con->argv[con->cur_idx]; |
| |
|
| |
for (i = 0; con->short_option_prefix[i] != NULL; i++) |
| |
if (strlen(con->short_option_prefix[i]) > size |
| |
&& strstr(s, con->short_option_prefix[i]) == s) |
| |
size = strlen(con->short_option_prefix[i]); |
| |
|
| |
size = -size; |
| |
|
| |
for (i = 0; con->long_option_prefix[i] != NULL; i++) |
| |
if (strlen(con->long_option_prefix[i]) > (size < 0 ? -size : size) |
| |
&& strstr(s, con->long_option_prefix[i]) == s) |
| |
size = strlen(con->long_option_prefix[i]); |
| |
|
| |
s_sep = NULL; |
| |
|
| |
if (size == 0) { |
| |
con->cur_opt_type = CFG_NONE_OPTION; |
| |
} |
| |
else if (size < 0) { |
| |
s += -size; |
| |
s_sep = s + 1; |
| |
|
| |
if (strlen(s_sep) > 0) { |
| |
con->cur_opt_type = CFG_SHORT_OPTIONS; |
| |
|
| |
if ((con->cur_arg = strdup(s_sep)) == NULL) |
| |
return 0; |
| |
} |
| |
else { |
| |
con->cur_opt_type = CFG_SHORT_OPTION; |
| |
|
| |
if ((con->cur_arg = strdup(con->argv[con->cur_idx])) == NULL) |
| |
return 0; |
| |
} |
| |
} |
| |
else { |
| |
con->cur_opt_type = CFG_LONG_OPTION; |
| |
|
| |
s += size; |
| |
size = 0; |
| |
|
| |
for (i = 0; con->line_option_arg_separator[i] != NULL; i++) |
| |
if ((s_tmp = strstr(s, con->line_option_arg_separator[i])) != NULL) |
| |
if (s_sep == NULL || s_tmp < s_sep || (s_tmp == s_sep |
| |
&& strlen(con->line_option_arg_separator[i]) > size)) |
| |
{ |
| |
s_sep = s_tmp; |
| |
size = strlen(con->line_option_arg_separator[i]); |
| |
} |
| |
|
| |
if (s_sep == NULL) { |
| |
if (con->argv[con->cur_idx + 1] != NULL) { |
| |
con->cur_arg = strdup(con->argv[con->cur_idx + 1]); |
| |
if (con->cur_arg == NULL) |
| |
return 0; |
| |
} |
| |
else |
| |
con->cur_arg = NULL; |
| |
} |
| |
else { |
| |
con->cur_opt_type += CFG_LONG_SEPINIT; |
| |
if ((con->cur_arg = strdup(s_sep + size)) == NULL) |
| |
return 0; |
| |
} |
| |
} |
| |
|
| |
if (s_sep == NULL) |
| |
s_sep = s + strlen(s); |
| |
|
| |
con->cur_opt = (char *) malloc((s_sep - s + 1) * sizeof(char)); |
| |
if (con->cur_opt != NULL) { |
| |
strncpy(con->cur_opt, s, s_sep - s); |
| |
con->cur_opt[s_sep - s] = '\0'; |
| |
} |
| |
else |
| |
return 0; |
| |
|
| |
return 1; |
| |
} |
| |
|
| |
static int search_cur_opt(const CFG_CONTEXT con) { |
| |
register int i; |
| |
|
| |
for (i = 0; con->options[i].cmdline_long_name != NULL |
| |
|| con->options[i].cmdline_short_name != '\0' |
| |
|| con->options[i].cfgfile_name != NULL |
| |
|| con->options[i].type != CFG_END |
| |
|| con->options[i].value != NULL |
| |
|| con->options[i].val != 0; |
| |
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, |
| |
con->options[i].cmdline_long_name)) |
| |
|| (con->cur_opt_type == CFG_SHORT_OPTION && |
| |
con->cur_opt[0] == |
| |
con->options[i].cmdline_short_name) |
| |
|| (con->cur_opt_type == CFG_NONE_OPTION && |
| |
con->options[i].type & CFG_LEFTOVER_ARGS)) |
| |
|
| |
return i; |
| |
} |
| |
|
| |
return -1; |
| |
} |
| |
|
| |
/* 0 - No, 1 - Short, 2 - Long */ |
| |
static int is_cmdline_option(const CFG_CONTEXT con, char *s) { |
| |
register int i, size, ret; |
| |
|
| |
size = ret = 0; |
| |
|
| |
for (i = 0; con->short_option_prefix[i] != NULL; i++) { |
| |
if (strstr(s, con->short_option_prefix[i]) == s) { |
| |
size = strlen(con->short_option_prefix[i]); |
| |
ret = 1; |
| |
break; |
| |
} |
| |
} |
| |
|
| |
for (i = 0; con->long_option_prefix[i] != NULL; i++) { |
| |
if (ret == 1 && strlen(con->long_option_prefix[i]) <= size) |
| |
continue; |
| |
|
| |
if (strstr(s, con->long_option_prefix[i]) == s) { |
| |
size = strlen(con->long_option_prefix[i]); |
| |
ret = 2; |
| |
break; |
| |
} |
| |
} |
| |
|
| |
return ret; |
| |
} |
| |
|