67 #pragma warning (disable: 4996 4018)
99 static void arg_dump_r(
cmd_ln_t *cmdln, FILE * fp,
arg_t const *defn, int32 doc);
100 static cmd_ln_t * parse_options(
cmd_ln_t *cmdln,
const arg_t *defn, int32 argc,
char* argv[], int32 strict);
107 arg_strlen(
const arg_t * defn, int32 * namelen, int32 * deflen)
111 *namelen = *deflen = 0;
112 for (i = 0; defn[i].name; i++) {
113 l = strlen(defn[i].name);
118 l = strlen(defn[i].deflt);
120 l = strlen(
"(null)");
131 cmp_name(
const void *a,
const void *b)
133 return (strcmp_nocase
134 ((* (
arg_t**) a)->name,
135 (* (
arg_t**) b)->name));
138 static const arg_t **
139 arg_sort(
const arg_t * defn, int32 n)
145 for (i = 0; i < n; ++i)
147 qsort(pos, n,
sizeof(
arg_t *), cmp_name);
153 strnappend(
char **dest,
size_t *dest_allocation,
154 const char *source,
size_t n)
156 size_t source_len, required_allocation;
158 if (dest == NULL || dest_allocation == NULL)
160 if (*dest == NULL && *dest_allocation != 0)
163 return *dest_allocation;
165 source_len = strlen(source);
166 if (n && n < source_len)
169 required_allocation = (*dest ? strlen(*dest) : 0) + source_len + 1;
170 if (*dest_allocation < required_allocation) {
171 if (*dest_allocation == 0) {
172 *dest =
ckd_calloc(required_allocation * 2, 1);
174 *dest =
ckd_realloc(*dest, required_allocation * 2);
176 *dest_allocation = required_allocation * 2;
179 strncat(*dest, source, source_len);
181 return *dest_allocation;
185 strappend(
char **dest,
size_t *dest_allocation,
188 return strnappend(dest, dest_allocation, source, 0);
192 arg_resolve_env(
const char *str)
194 char *resolved_str = NULL;
198 const char *i = str, *j;
205 strnappend(&resolved_str, &alloced, i, j - i);
208 j = strchr(i + 2,
')');
210 if (j - (i + 2) < 100) {
211 strncpy(env_name, i + 2, j - (i + 2));
212 env_name[j - (i + 2)] =
'\0';
213 #if !defined(_WIN32_WCE)
214 env_val = getenv(env_name);
216 strappend(&resolved_str, &alloced, env_val);
225 strnappend(&resolved_str, &alloced, i, j - i);
229 strappend(&resolved_str, &alloced, i);
237 arg_dump_r(
cmd_ln_t *cmdln, FILE * fp,
const arg_t * defn, int32 doc)
241 int32 namelen, deflen;
252 n = arg_strlen(defn, &namelen, &deflen);
254 namelen = namelen & 0xfffffff8;
255 deflen = deflen & 0xfffffff8;
257 fprintf(fp,
"[NAME]");
258 for (l = strlen(
"[NAME]"); l < namelen; l += 8)
260 fprintf(fp,
"\t[DEFLT]");
261 for (l = strlen(
"[DEFLT]"); l < deflen; l += 8)
265 fprintf(fp,
"\t[DESCR]\n");
268 fprintf(fp,
"\t[VALUE]\n");
272 pos = arg_sort(defn, n);
273 for (i = 0; i < n; i++) {
274 fprintf(fp,
"%s", pos[i]->name);
275 for (l = strlen(pos[i]->name); l < namelen; l += 8)
280 fprintf(fp,
"%s", pos[i]->deflt);
281 l = strlen(pos[i]->deflt);
285 for (; l < deflen; l += 8)
291 fprintf(fp,
"%s", pos[i]->doc);
296 switch (pos[i]->type) {
299 fprintf(fp,
"%ld", vp->i);
303 fprintf(fp,
"%e", vp->fl);
308 fprintf(fp,
"%s", (
char *)vp->ptr);
311 array = (
char const**)vp->ptr;
313 for (l = 0; array[l] != 0; l++) {
314 fprintf(fp,
"%s,", array[l]);
319 fprintf(fp,
"%s", vp->i ?
"yes" :
"no");
322 E_ERROR(
"Unknown argument type: %d\n", pos[i]->type);
336 parse_string_list(
const char *str)
350 result = (
char **)
ckd_calloc(count + 1,
sizeof(
char *));
352 for (i = 0; i < count; i++) {
353 for (j = 0; p[j] !=
',' && p[j] != 0; j++);
355 strncpy( result[i], p, j);
362 cmd_ln_val_init(
int t,
const char *str)
370 memset(&val, 0,
sizeof(val));
374 e_str = arg_resolve_env(str);
379 if (sscanf(e_str,
"%ld", &val.i) != 1)
384 if (e_str == NULL || e_str[0] == 0)
390 if ((e_str[0] ==
'y') || (e_str[0] ==
't') ||
391 (e_str[0] ==
'Y') || (e_str[0] ==
'T') || (e_str[0] ==
'1')) {
394 else if ((e_str[0] ==
'n') || (e_str[0] ==
'f') ||
395 (e_str[0] ==
'N') || (e_str[0] ==
'F') |
400 E_ERROR(
"Unparsed boolean value '%s'\n", str);
409 val.ptr = parse_string_list(e_str);
412 E_ERROR(
"Unknown argument type: %d\n", t);
422 memcpy(v, &val,
sizeof(val));
434 parse_options(
cmd_ln_t *cmdln,
const arg_t *defn, int32 argc,
char* argv[], int32 strict)
440 if (new_cmdln == NULL) {
442 for (i = 0; i < argc; ++i)
449 if (new_cmdln == cmdln) {
453 (new_cmdln->f_argc + argc)
454 *
sizeof(*new_cmdln->f_argv));
455 memcpy(new_cmdln->f_argv + new_cmdln->f_argc, argv,
456 argc *
sizeof(*argv));
458 new_cmdln->f_argc += argc;
462 new_cmdln->f_argc = argc;
463 new_cmdln->f_argv = argv;
474 char const** array = (
char const **)val->val.ptr;
476 for (i = 0; array[i] != NULL; i++) {
495 const char *default_argfn,
503 if ((argc == 2) && (strcmp(argv[1],
"help") == 0)) {
508 if ((argc == 2) && (argv[1][0] !=
'-'))
510 else if (argc == 1) {
512 E_INFO(
"Looking for default argument file: %s\n", default_argfn);
514 if ((fp = fopen(default_argfn,
"r")) == NULL) {
515 E_INFO(
"Can't find default argument file %s.\n",
528 E_INFO(
"Parsing command lines from file %s\n", str);
531 E_INFOCONT(
"\t%s argument-list, or\n", argv[0]);
532 E_INFOCONT(
"\t%s [argument-file] (default file: . %s)\n\n",
533 argv[0], default_argfn);
553 int32 i, j, n, argstart;
559 E_INFO(
"Parsing command line:\n");
560 for (i = 0; i < argc; i++) {
561 if (argv[i][0] ==
'-')
570 if (inout_cmdln == NULL) {
580 for (n = 0; defn[n].name; n++) {
584 if (strict && (v != &defn[n])) {
585 E_ERROR(
"Duplicate argument name in definition: %s\n", defn[n].name);
596 if (cmdln->ht == NULL)
602 if (argc > 0 && argv[0][0] !=
'-') {
607 for (j = argstart; j < argc; j += 2) {
614 E_ERROR(
"Unknown argument name '%s'\n", argv[j]);
617 else if (defn == NULL)
627 E_ERROR(
"Argument value for '%s' missing\n", argv[j]);
632 val = cmd_ln_val_init(
ARG_STRING, argv[j + 1]);
634 if ((val = cmd_ln_val_init(argdef->type, argv[j + 1])) == NULL) {
636 E_ERROR(
"Bad argument value for %s: %s\n", argv[j],
642 if ((v =
hash_table_enter(cmdln->ht, argv[j], (
void *)val)) != (
void *)val) {
644 cmd_ln_val_free(val);
645 E_ERROR(
"Duplicate argument name in arguments: %s\n",
657 for (i = 0; i < n; i++) {
662 if ((val = cmd_ln_val_init(defn[i].type, defn[i].deflt)) == NULL) {
664 (
"Bad default argument value for %s: %s\n",
665 defn[i].name, defn[i].deflt);
674 for (i = 0; i < n; i++) {
678 E_ERROR(
"Missing required argument %s\n", defn[i].name);
686 if (strict && argc == 1) {
687 E_ERROR(
"No arguments given, exiting\n");
703 if (inout_cmdln == NULL)
705 E_ERROR(
"cmd_ln_parse_r failed\n");
713 const char *arg, *val;
717 va_start(args, strict);
719 while ((arg = va_arg(args,
const char *))) {
721 val = va_arg(args,
const char*);
723 E_ERROR(
"Number of arguments must be even!\n");
732 va_start(args, strict);
734 while ((arg = va_arg(args,
const char *))) {
737 val = va_arg(args,
const char*);
743 return parse_options(inout_cmdln, defn, f_argc, f_argv, strict);
754 E_ERROR(
"cmd_ln_parse failed, forced exit\n");
758 if (global_cmdln == NULL) {
759 global_cmdln = cmdln;
771 int arg_max_length = 512;
776 const char separator[] =
" \t\r\n";
778 if ((file = fopen(filename,
"r")) == NULL) {
779 E_ERROR(
"Cannot open configuration file %s for reading\n",
786 for (; ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
798 f_argv =
ckd_calloc(argv_size,
sizeof(
char *));
800 str =
ckd_calloc(arg_max_length + 1,
sizeof(
char));
805 if (len == 0 && argc % 2 == 0) {
808 for (ch = fgetc(file); ch != EOF && ch !=
'\n'; ch = fgetc(file)) ;
810 for (ch = fgetc(file); ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
819 if (ch ==
'"' || ch ==
'\'') {
823 E_ERROR(
"Nesting quotations is not supported!\n");
830 else if (ch == EOF || (!quoting && strchr(separator, ch))) {
832 if (argc >= argv_size) {
835 ckd_realloc(f_argv, argv_size * 2 *
sizeof(
char *)))) {
849 E_WARN(
"Unclosed quotation, having EOF close it...\n");
852 for (; ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
861 if (len >= arg_max_length) {
864 if ((tmp_str =
ckd_realloc(str, (1 + arg_max_length * 2) *
sizeof(
char))) == NULL) {
885 for (ch = 0; ch < argc; ++ch)
891 return parse_options(inout_cmdln, defn, argc, f_argv, strict);
904 if (global_cmdln == NULL) {
905 global_cmdln = cmdln;
915 fprintf(fp,
"Arguments list definition:\n");
916 arg_dump_r(cmdln, fp, defn, 1);
934 E_ERROR(
"Unknown argument: %s\n", name);
947 return (
char const *)val->ptr;
957 return (
char const **)val->ptr;
986 E_ERROR(
"Unknown argument: %s\n", name);
1002 E_ERROR(
"Unknown argument: %s\n", name);
1014 E_ERROR(
"Unknown argument: %s\n", name);
1032 if (--cmdln->refcount > 0)
1033 return cmdln->refcount;
1041 for (gn = entries; gn; gn = gnode_next(gn)) {
1050 if (cmdln->f_argv) {
1052 for (i = 0; i < cmdln->f_argc; ++i) {
1056 cmdln->f_argv = NULL;
1067 global_cmdln = NULL;