00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #include <stdio.h>
00062 #include <stdlib.h>
00063 #include <string.h>
00064 #include <assert.h>
00065
00066 #ifdef _MSC_VER
00067 #pragma warning (disable: 4996 4018)
00068 #endif
00069
00070 #ifdef HAVE_CONFIG_H
00071 #include <config.h>
00072 #endif
00073
00074 #ifdef HAVE_UNISTD_H
00075 #include <unistd.h>
00076 #endif
00077
00078 #include "cmd_ln.h"
00079 #include "err.h"
00080 #include "ckd_alloc.h"
00081 #include "hash_table.h"
00082 #include "case.h"
00083
00084 typedef struct cmd_ln_val_s {
00085 anytype_t val;
00086 int type;
00087 } cmd_ln_val_t;
00088
00089 struct cmd_ln_s {
00090 int refcount;
00091 hash_table_t *ht;
00092 char **f_argv;
00093 uint32 f_argc;
00094 };
00095
00097 cmd_ln_t *global_cmdln;
00098 static void arg_dump_r(cmd_ln_t *cmdln, FILE * fp, arg_t const *defn, int32 doc);
00099 static cmd_ln_t * parse_options(cmd_ln_t *cmdln, const arg_t *defn, int32 argc, char* argv[], int32 strict);
00100
00101
00102
00103
00104
00105 static int32
00106 arg_strlen(const arg_t * defn, int32 * namelen, int32 * deflen)
00107 {
00108 int32 i, l;
00109
00110 *namelen = *deflen = 0;
00111 for (i = 0; defn[i].name; i++) {
00112 l = strlen(defn[i].name);
00113 if (*namelen < l)
00114 *namelen = l;
00115
00116 if (defn[i].deflt)
00117 l = strlen(defn[i].deflt);
00118 else
00119 l = strlen("(null)");
00120
00121 if (*deflen < l)
00122 *deflen = l;
00123 }
00124
00125 return i;
00126 }
00127
00128
00129 static int32
00130 cmp_name(const void *a, const void *b)
00131 {
00132 return (strcmp_nocase
00133 ((* (arg_t**) a)->name,
00134 (* (arg_t**) b)->name));
00135 }
00136
00137 static const arg_t **
00138 arg_sort(const arg_t * defn, int32 n)
00139 {
00140 const arg_t ** pos;
00141 int32 i;
00142
00143 pos = (const arg_t **) ckd_calloc(n, sizeof(arg_t *));
00144 for (i = 0; i < n; ++i)
00145 pos[i] = &defn[i];
00146 qsort(pos, n, sizeof(arg_t *), cmp_name);
00147
00148 return pos;
00149 }
00150
00151 static size_t
00152 strnappend(char **dest, size_t *dest_allocation,
00153 const char *source, size_t n)
00154 {
00155 size_t source_len, required_allocation;
00156
00157 if (dest == NULL || dest_allocation == NULL)
00158 return -1;
00159 if (*dest == NULL && *dest_allocation != 0)
00160 return -1;
00161 if (source == NULL)
00162 return *dest_allocation;
00163
00164 source_len = strlen(source);
00165 if (n && n < source_len)
00166 source_len = n;
00167
00168 required_allocation = (*dest ? strlen(*dest) : 0) + source_len + 1;
00169 if (*dest_allocation < required_allocation) {
00170 if (*dest_allocation == 0) {
00171 *dest = ckd_calloc(required_allocation * 2, 1);
00172 } else {
00173 *dest = ckd_realloc(*dest, required_allocation * 2);
00174 }
00175 *dest_allocation = required_allocation * 2;
00176 }
00177
00178 strncat(*dest, source, source_len);
00179
00180 return *dest_allocation;
00181 }
00182
00183 static size_t
00184 strappend(char **dest, size_t *dest_allocation,
00185 const char *source)
00186 {
00187 return strnappend(dest, dest_allocation, source, 0);
00188 }
00189
00190 static char*
00191 arg_resolve_env(const char *str)
00192 {
00193 char *resolved_str = NULL;
00194 char env_name[100];
00195 const char *env_val;
00196 size_t alloced = 0;
00197 const char *i = str, *j;
00198
00199
00200 do {
00201 j = strstr(i, "$(");
00202 if (j != NULL) {
00203 if (j != i) {
00204 strnappend(&resolved_str, &alloced, i, j - i);
00205 i = j;
00206 }
00207 j = strchr(i + 2, ')');
00208 if (j != NULL) {
00209 if (j - (i + 2) < 100) {
00210 strncpy(env_name, i + 2, j - (i + 2));
00211 env_name[j - (i + 2)] = '\0';
00212 #if !defined(_WIN32_WCE)
00213 env_val = getenv(env_name);
00214 if (env_val)
00215 strappend(&resolved_str, &alloced, env_val);
00216 #else
00217 env_val = 0;
00218 #endif
00219 }
00220 i = j + 1;
00221 } else {
00222
00223 j = i + 2;
00224 strnappend(&resolved_str, &alloced, i, j - i);
00225 i = j;
00226 }
00227 } else {
00228 strappend(&resolved_str, &alloced, i);
00229 }
00230 } while(j != NULL);
00231
00232 return resolved_str;
00233 }
00234
00235 static void
00236 arg_dump_r(cmd_ln_t *cmdln, FILE * fp, const arg_t * defn, int32 doc)
00237 {
00238 const arg_t **pos;
00239 int32 i, l, n;
00240 int32 namelen, deflen;
00241 anytype_t *vp;
00242
00243
00244 if (defn == NULL)
00245 return;
00246 if (fp == NULL)
00247 return;
00248
00249
00250 n = arg_strlen(defn, &namelen, &deflen);
00251
00252 namelen = namelen & 0xfffffff8;
00253 deflen = deflen & 0xfffffff8;
00254
00255 fprintf(fp, "[NAME]");
00256 for (l = strlen("[NAME]"); l < namelen; l += 8)
00257 fprintf(fp, "\t");
00258 fprintf(fp, "\t[DEFLT]");
00259 for (l = strlen("[DEFLT]"); l < deflen; l += 8)
00260 fprintf(fp, "\t");
00261
00262 if (doc) {
00263 fprintf(fp, "\t[DESCR]\n");
00264 }
00265 else {
00266 fprintf(fp, "\t[VALUE]\n");
00267 }
00268
00269
00270 pos = arg_sort(defn, n);
00271 for (i = 0; i < n; i++) {
00272 fprintf(fp, "%s", pos[i]->name);
00273 for (l = strlen(pos[i]->name); l < namelen; l += 8)
00274 fprintf(fp, "\t");
00275
00276 fprintf(fp, "\t");
00277 if (pos[i]->deflt) {
00278 fprintf(fp, "%s", pos[i]->deflt);
00279 l = strlen(pos[i]->deflt);
00280 }
00281 else
00282 l = 0;
00283 for (; l < deflen; l += 8)
00284 fprintf(fp, "\t");
00285
00286 fprintf(fp, "\t");
00287 if (doc) {
00288 if (pos[i]->doc)
00289 fprintf(fp, "%s", pos[i]->doc);
00290 }
00291 else {
00292 vp = cmd_ln_access_r(cmdln, pos[i]->name);
00293 if (vp) {
00294 switch (pos[i]->type) {
00295 case ARG_INTEGER:
00296 case REQARG_INTEGER:
00297 fprintf(fp, "%ld", vp->i);
00298 break;
00299 case ARG_FLOATING:
00300 case REQARG_FLOATING:
00301 fprintf(fp, "%e", vp->fl);
00302 break;
00303 case ARG_STRING:
00304 case REQARG_STRING:
00305 if (vp->ptr)
00306 fprintf(fp, "%s", (char *)vp->ptr);
00307 break;
00308 case ARG_BOOLEAN:
00309 case REQARG_BOOLEAN:
00310 fprintf(fp, "%s", vp->i ? "yes" : "no");
00311 break;
00312 default:
00313 E_ERROR("Unknown argument type: %d\n", pos[i]->type);
00314 }
00315 }
00316 }
00317
00318 fprintf(fp, "\n");
00319 }
00320 ckd_free(pos);
00321
00322 fprintf(fp, "\n");
00323 fflush(fp);
00324 }
00325
00326 static cmd_ln_val_t *
00327 cmd_ln_val_init(int t, const char *str)
00328 {
00329 cmd_ln_val_t *v;
00330 anytype_t val;
00331 char *e_str;
00332
00333 if (!str) {
00334
00335 memset(&val, 0, sizeof(val));
00336 }
00337 else {
00338 int valid = 1;
00339 e_str = arg_resolve_env(str);
00340
00341 switch (t) {
00342 case ARG_INTEGER:
00343 case REQARG_INTEGER:
00344 if (sscanf(e_str, "%ld", &val.i) != 1)
00345 valid = 0;
00346 break;
00347 case ARG_FLOATING:
00348 case REQARG_FLOATING:
00349 if (sscanf(e_str, "%lf", &val.fl) != 1)
00350 valid = 0;
00351 break;
00352 case ARG_BOOLEAN:
00353 case REQARG_BOOLEAN:
00354 if ((e_str[0] == 'y') || (e_str[0] == 't') ||
00355 (e_str[0] == 'Y') || (e_str[0] == 'T') || (e_str[0] == '1')) {
00356 val.i = TRUE;
00357 }
00358 else if ((e_str[0] == 'n') || (e_str[0] == 'f') ||
00359 (e_str[0] == 'N') || (e_str[0] == 'F') |
00360 (e_str[0] == '0')) {
00361 val.i = FALSE;
00362 }
00363 else {
00364 E_ERROR("Unparsed boolean value '%s'\n", str);
00365 valid = 0;
00366 }
00367 break;
00368 case ARG_STRING:
00369 case REQARG_STRING:
00370 val.ptr = ckd_salloc(e_str);
00371 break;
00372 default:
00373 E_ERROR("Unknown argument type: %d\n", t);
00374 valid = 0;
00375 }
00376
00377 ckd_free(e_str);
00378 if (valid == 0)
00379 return NULL;
00380 }
00381
00382 v = ckd_calloc(1, sizeof(*v));
00383 memcpy(v, &val, sizeof(val));
00384 v->type = t;
00385
00386 return v;
00387 }
00388
00389
00390
00391
00392
00393
00394 static cmd_ln_t *
00395 parse_options(cmd_ln_t *cmdln, const arg_t *defn, int32 argc, char* argv[], int32 strict)
00396 {
00397 cmd_ln_t *new_cmdln;
00398
00399 new_cmdln = cmd_ln_parse_r(cmdln, defn, argc, argv, strict);
00400
00401 if (new_cmdln == NULL) {
00402 int32 i;
00403 for (i = 0; i < argc; ++i)
00404 ckd_free(argv[i]);
00405 ckd_free(argv);
00406 return NULL;
00407 }
00408
00409
00410 if (new_cmdln == cmdln) {
00411
00412
00413 new_cmdln->f_argv = ckd_realloc(new_cmdln->f_argv,
00414 (new_cmdln->f_argc + argc)
00415 * sizeof(*new_cmdln->f_argv));
00416 memcpy(new_cmdln->f_argv + new_cmdln->f_argc, argv,
00417 argc * sizeof(*argv));
00418 ckd_free(argv);
00419 new_cmdln->f_argc += argc;
00420 }
00421 else {
00422
00423 new_cmdln->f_argc = argc;
00424 new_cmdln->f_argv = argv;
00425 }
00426
00427 return new_cmdln;
00428 }
00429
00430 void
00431 cmd_ln_val_free(cmd_ln_val_t *val)
00432 {
00433 if (val->type & ARG_STRING)
00434 ckd_free(val->val.ptr);
00435 ckd_free(val);
00436 }
00437
00438 cmd_ln_t *
00439 cmd_ln_get(void)
00440 {
00441 return global_cmdln;
00442 }
00443
00444 void
00445 cmd_ln_appl_enter(int argc, char *argv[],
00446 const char *default_argfn,
00447 const arg_t * defn)
00448 {
00449
00450 const char *str;
00451
00452 str = NULL;
00453
00454 if ((argc == 2) && (strcmp(argv[1], "help") == 0)) {
00455 cmd_ln_print_help(stderr, defn);
00456 exit(1);
00457 }
00458
00459 if ((argc == 2) && (argv[1][0] != '-'))
00460 str = argv[1];
00461 else if (argc == 1) {
00462 FILE *fp;
00463 E_INFO("Looking for default argument file: %s\n", default_argfn);
00464
00465 if ((fp = fopen(default_argfn, "r")) == NULL) {
00466 E_INFO("Can't find default argument file %s.\n",
00467 default_argfn);
00468 }
00469 else {
00470 str = default_argfn;
00471 }
00472 if (fp != NULL)
00473 fclose(fp);
00474 }
00475
00476
00477 if (str) {
00478
00479 E_INFO("Parsing command lines from file %s\n", str);
00480 if (cmd_ln_parse_file(defn, str, TRUE)) {
00481 E_INFOCONT("Usage:\n");
00482 E_INFOCONT("\t%s argument-list, or\n", argv[0]);
00483 E_INFOCONT("\t%s [argument-file] (default file: . %s)\n\n",
00484 argv[0], default_argfn);
00485 cmd_ln_print_help(stderr, defn);
00486 exit(1);
00487 }
00488 }
00489 else {
00490 cmd_ln_parse(defn, argc, argv, TRUE);
00491 }
00492 }
00493
00494 void
00495 cmd_ln_appl_exit()
00496 {
00497 cmd_ln_free();
00498 }
00499
00500
00501 cmd_ln_t *
00502 cmd_ln_parse_r(cmd_ln_t *inout_cmdln, const arg_t * defn, int32 argc, char *argv[], int strict)
00503 {
00504 int32 i, j, n;
00505 hash_table_t *defidx = NULL;
00506 cmd_ln_t *cmdln;
00507
00508
00509 #ifndef _WIN32_WCE
00510 E_INFO("Parsing command line:\n");
00511 for (i = 0; i < argc; i++) {
00512 if (argv[i][0] == '-')
00513 E_INFOCONT("\\\n\t");
00514 E_INFOCONT("%s ", argv[i]);
00515 }
00516 E_INFOCONT("\n\n");
00517 fflush(stderr);
00518 #endif
00519
00520
00521 if (inout_cmdln == NULL) {
00522 cmdln = ckd_calloc(1, sizeof(*cmdln));
00523 cmdln->refcount = 1;
00524 }
00525 else
00526 cmdln = inout_cmdln;
00527
00528
00529 defidx = hash_table_new(50, 0);
00530 if (defn) {
00531 for (n = 0; defn[n].name; n++) {
00532 void *v;
00533
00534 v = hash_table_enter(defidx, defn[n].name, (void *)&defn[n]);
00535 if (strict && (v != &defn[n])) {
00536 E_ERROR("Duplicate argument name in definition: %s\n", defn[n].name);
00537 goto error;
00538 }
00539 }
00540 }
00541 else {
00542
00543 n = 0;
00544 }
00545
00546
00547 if (cmdln->ht == NULL)
00548 cmdln->ht = hash_table_new(n, 0 );
00549
00550
00551 for (j = argc % 2; j < argc; j += 2) {
00552 arg_t *argdef;
00553 cmd_ln_val_t *val;
00554 void *v;
00555
00556 if (j + 1 >= argc) {
00557 cmd_ln_print_help_r(cmdln, stderr, defn);
00558 E_ERROR("Argument value for '%s' missing\n", argv[j]);
00559 goto error;
00560 }
00561 if (hash_table_lookup(defidx, argv[j], &v) < 0) {
00562 if (strict) {
00563 E_ERROR("Unknown argument name '%s'\n", argv[j]);
00564 goto error;
00565 }
00566 else if (defn == NULL)
00567 v = NULL;
00568 else
00569 continue;
00570 }
00571 argdef = v;
00572
00573
00574 if (argdef == NULL)
00575 val = cmd_ln_val_init(ARG_STRING, argv[j + 1]);
00576 else {
00577 if ((val = cmd_ln_val_init(argdef->type, argv[j + 1])) == NULL) {
00578 cmd_ln_print_help_r(cmdln, stderr, defn);
00579 E_ERROR("Bad argument value for %s: %s\n", argv[j],
00580 argv[j + 1]);
00581 goto error;
00582 }
00583 }
00584
00585 if ((v = hash_table_enter(cmdln->ht, argv[j], (void *)val)) != (void *)val) {
00586 if (strict) {
00587 cmd_ln_val_free(val);
00588 E_ERROR("Duplicate argument name in arguments: %s\n",
00589 argdef->name);
00590 goto error;
00591 }
00592 else {
00593 v = hash_table_replace(cmdln->ht, argv[j], (void *)val);
00594 cmd_ln_val_free((cmd_ln_val_t *)v);
00595 }
00596 }
00597 }
00598
00599
00600 for (i = 0; i < n; i++) {
00601 cmd_ln_val_t *val;
00602 void *v;
00603
00604 if (hash_table_lookup(cmdln->ht, defn[i].name, &v) < 0) {
00605 if ((val = cmd_ln_val_init(defn[i].type, defn[i].deflt)) == NULL) {
00606 E_ERROR
00607 ("Bad default argument value for %s: %s\n",
00608 defn[i].name, defn[i].deflt);
00609 goto error;
00610 }
00611 hash_table_enter(cmdln->ht, defn[i].name, (void *)val);
00612 }
00613 }
00614
00615
00616 j = 0;
00617 for (i = 0; i < n; i++) {
00618 if (defn[i].type & ARG_REQUIRED) {
00619 void *v;
00620 if (hash_table_lookup(cmdln->ht, defn[i].name, &v) != 0)
00621 E_ERROR("Missing required argument %s\n", defn[i].name);
00622 }
00623 }
00624 if (j > 0) {
00625 cmd_ln_print_help_r(cmdln, stderr, defn);
00626 goto error;
00627 }
00628
00629 if (strict && argc == 1) {
00630 E_ERROR("No arguments given, exiting\n");
00631 cmd_ln_print_help_r(cmdln, stderr, defn);
00632 goto error;
00633 }
00634
00635 #ifndef _WIN32_WCE
00636
00637 E_INFOCONT("Current configuration:\n");
00638 arg_dump_r(cmdln, err_get_logfp(), defn, 0);
00639 #endif
00640 hash_table_free(defidx);
00641 return cmdln;
00642
00643 error:
00644 if (defidx)
00645 hash_table_free(defidx);
00646 if (inout_cmdln == NULL)
00647 cmd_ln_free_r(cmdln);
00648 E_ERROR("cmd_ln_parse_r failed\n");
00649 return NULL;
00650 }
00651
00652 cmd_ln_t *
00653 cmd_ln_init(cmd_ln_t *inout_cmdln, const arg_t *defn, int32 strict, ...)
00654 {
00655 va_list args;
00656 const char *arg, *val;
00657 char **f_argv;
00658 int32 f_argc;
00659
00660 va_start(args, strict);
00661 f_argc = 0;
00662 while ((arg = va_arg(args, const char *))) {
00663 ++f_argc;
00664 val = va_arg(args, const char*);
00665 if (val == NULL) {
00666 E_ERROR("Number of arguments must be even!\n");
00667 return NULL;
00668 }
00669 ++f_argc;
00670 }
00671 va_end(args);
00672
00673
00674 f_argv = ckd_calloc(f_argc, sizeof(*f_argv));
00675 va_start(args, strict);
00676 f_argc = 0;
00677 while ((arg = va_arg(args, const char *))) {
00678 f_argv[f_argc] = ckd_salloc(arg);
00679 ++f_argc;
00680 val = va_arg(args, const char*);
00681 f_argv[f_argc] = ckd_salloc(val);
00682 ++f_argc;
00683 }
00684 va_end(args);
00685
00686 return parse_options(inout_cmdln, defn, f_argc, f_argv, strict);
00687 }
00688
00689 int
00690 cmd_ln_parse(const arg_t * defn, int32 argc, char *argv[], int strict)
00691 {
00692 cmd_ln_t *cmdln;
00693
00694 cmdln = cmd_ln_parse_r(global_cmdln, defn, argc, argv, strict);
00695 if (cmdln == NULL) {
00696
00697 E_ERROR("cmd_ln_parse failed, forced exit\n");
00698 exit(-1);
00699 }
00700
00701 if (global_cmdln == NULL) {
00702 global_cmdln = cmdln;
00703 }
00704 return 0;
00705 }
00706
00707 cmd_ln_t *
00708 cmd_ln_parse_file_r(cmd_ln_t *inout_cmdln, const arg_t * defn, const char *filename, int32 strict)
00709 {
00710 FILE *file;
00711 int argc;
00712 int argv_size;
00713 char *str;
00714 int arg_max_length = 512;
00715 int len = 0;
00716 int quoting, ch;
00717 char **f_argv;
00718 int rv = 0;
00719 const char separator[] = " \t\r\n";
00720
00721 if ((file = fopen(filename, "r")) == NULL) {
00722 E_ERROR("Cannot open configuration file %s for reading\n",
00723 filename);
00724 return NULL;
00725 }
00726
00727 ch = fgetc(file);
00728
00729 for (; ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
00730
00731 if (ch == EOF) {
00732 fclose(file);
00733 return NULL;
00734 }
00735
00736
00737
00738
00739 argv_size = 10;
00740 argc = 0;
00741 f_argv = ckd_calloc(argv_size, sizeof(char *));
00742
00743 str = ckd_calloc(arg_max_length + 1, sizeof(char));
00744 quoting = 0;
00745
00746 do {
00747
00748 if (len == 0 && argc % 2 == 0) {
00749 while (ch == '#') {
00750
00751 for (ch = fgetc(file); ch != EOF && ch != '\n'; ch = fgetc(file)) ;
00752
00753 for (ch = fgetc(file); ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
00754 }
00755
00756
00757 if (ch == EOF)
00758 break;
00759 }
00760
00761
00762 if (ch == '"' || ch == '\'') {
00763 if (quoting == ch)
00764 quoting = 0;
00765 else if (quoting) {
00766 E_ERROR("Nesting quotations is not supported!\n");
00767 rv = 1;
00768 break;
00769 }
00770 else
00771 quoting = ch;
00772 }
00773 else if (ch == EOF || (!quoting && strchr(separator, ch))) {
00774
00775 if (argc >= argv_size) {
00776 char **tmp_argv;
00777 if (!(tmp_argv =
00778 ckd_realloc(f_argv, argv_size * 2 * sizeof(char *)))) {
00779 rv = 1;
00780 break;
00781 }
00782 f_argv = tmp_argv;
00783 argv_size *= 2;
00784 }
00785
00786 f_argv[argc] = ckd_salloc(str);
00787 len = 0;
00788 str[0] = '\0';
00789 argc++;
00790
00791 if (quoting)
00792 E_WARN("Unclosed quotation, having EOF close it...\n");
00793
00794
00795 for (; ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
00796
00797 if (ch == EOF)
00798 break;
00799
00800
00801 continue;
00802 }
00803 else {
00804 if (len >= arg_max_length) {
00805
00806 char *tmp_str = str;
00807 if ((tmp_str = ckd_realloc(str, (1 + arg_max_length * 2) * sizeof(char))) == NULL) {
00808 rv = 1;
00809 break;
00810 }
00811 str = tmp_str;
00812 arg_max_length *= 2;
00813 }
00814
00815 str[len++] = ch;
00816
00817 str[len] = '\0';
00818 }
00819
00820 ch = fgetc(file);
00821 } while (1);
00822
00823 fclose(file);
00824
00825 ckd_free(str);
00826
00827 if (rv) {
00828 for (ch = 0; ch < argc; ++ch)
00829 ckd_free(f_argv[ch]);
00830 ckd_free(f_argv);
00831 return NULL;
00832 }
00833
00834 return parse_options(inout_cmdln, defn, argc, f_argv, strict);
00835 }
00836
00837 int
00838 cmd_ln_parse_file(const arg_t * defn, const char *filename, int32 strict)
00839 {
00840 cmd_ln_t *cmdln;
00841
00842 cmdln = cmd_ln_parse_file_r(global_cmdln, defn, filename, strict);
00843 if (cmdln == NULL) {
00844 return -1;
00845 }
00846
00847 if (global_cmdln == NULL) {
00848 global_cmdln = cmdln;
00849 }
00850 return 0;
00851 }
00852
00853 void
00854 cmd_ln_print_help_r(cmd_ln_t *cmdln, FILE * fp, arg_t const* defn)
00855 {
00856 if (defn == NULL)
00857 return;
00858 fprintf(fp, "Arguments list definition:\n");
00859 arg_dump_r(cmdln, fp, defn, 1);
00860 fflush(fp);
00861 }
00862
00863 int
00864 cmd_ln_exists_r(cmd_ln_t *cmdln, const char *name)
00865 {
00866 void *val;
00867 if (cmdln == NULL)
00868 return FALSE;
00869 return (hash_table_lookup(cmdln->ht, name, &val) == 0);
00870 }
00871
00872 anytype_t *
00873 cmd_ln_access_r(cmd_ln_t *cmdln, const char *name)
00874 {
00875 void *val;
00876 if (hash_table_lookup(cmdln->ht, name, &val) < 0) {
00877 E_ERROR("Unknown argument: %s\n", name);
00878 return NULL;
00879 }
00880 return (anytype_t *)val;
00881 }
00882
00883 char const *
00884 cmd_ln_str_r(cmd_ln_t *cmdln, char const *name)
00885 {
00886 anytype_t *val;
00887 val = cmd_ln_access_r(cmdln, name);
00888 if (val == NULL)
00889 return NULL;
00890 return (char const *)val->ptr;
00891 }
00892
00893 long
00894 cmd_ln_int_r(cmd_ln_t *cmdln, char const *name)
00895 {
00896 anytype_t *val;
00897 val = cmd_ln_access_r(cmdln, name);
00898 if (val == NULL)
00899 return 0L;
00900 return val->i;
00901 }
00902
00903 double
00904 cmd_ln_float_r(cmd_ln_t *cmdln, char const *name)
00905 {
00906 anytype_t *val;
00907 val = cmd_ln_access_r(cmdln, name);
00908 if (val == NULL)
00909 return 0.0;
00910 return val->fl;
00911 }
00912
00913 void
00914 cmd_ln_set_str_r(cmd_ln_t *cmdln, char const *name, char const *str)
00915 {
00916 anytype_t *val;
00917 val = cmd_ln_access_r(cmdln, name);
00918 if (val == NULL) {
00919 E_ERROR("Unknown argument: %s\n", name);
00920 return;
00921 }
00922 ckd_free(val->ptr);
00923 if (str == NULL)
00924 val->ptr = NULL;
00925 else
00926 val->ptr = ckd_salloc(str);
00927 }
00928
00929 void
00930 cmd_ln_set_int_r(cmd_ln_t *cmdln, char const *name, long iv)
00931 {
00932 anytype_t *val;
00933 val = cmd_ln_access_r(cmdln, name);
00934 if (val == NULL) {
00935 E_ERROR("Unknown argument: %s\n", name);
00936 return;
00937 }
00938 val->i = iv;
00939 }
00940
00941 void
00942 cmd_ln_set_float_r(cmd_ln_t *cmdln, char const *name, double fv)
00943 {
00944 anytype_t *val;
00945 val = cmd_ln_access_r(cmdln, name);
00946 if (val == NULL) {
00947 E_ERROR("Unknown argument: %s\n", name);
00948 return;
00949 }
00950 val->fl = fv;
00951 }
00952
00953 cmd_ln_t *
00954 cmd_ln_retain(cmd_ln_t *cmdln)
00955 {
00956 ++cmdln->refcount;
00957 return cmdln;
00958 }
00959
00960 int
00961 cmd_ln_free_r(cmd_ln_t *cmdln)
00962 {
00963 if (cmdln == NULL)
00964 return 0;
00965 if (--cmdln->refcount > 0)
00966 return cmdln->refcount;
00967
00968 if (cmdln->ht) {
00969 glist_t entries;
00970 gnode_t *gn;
00971 int32 n;
00972
00973 entries = hash_table_tolist(cmdln->ht, &n);
00974 for (gn = entries; gn; gn = gnode_next(gn)) {
00975 hash_entry_t *e = gnode_ptr(gn);
00976 cmd_ln_val_free((cmd_ln_val_t *)e->val);
00977 }
00978 glist_free(entries);
00979 hash_table_free(cmdln->ht);
00980 cmdln->ht = NULL;
00981 }
00982
00983 if (cmdln->f_argv) {
00984 int32 i;
00985 for (i = 0; i < cmdln->f_argc; ++i) {
00986 ckd_free(cmdln->f_argv[i]);
00987 }
00988 ckd_free(cmdln->f_argv);
00989 cmdln->f_argv = NULL;
00990 cmdln->f_argc = 0;
00991 }
00992 ckd_free(cmdln);
00993 return 0;
00994 }
00995
00996 void
00997 cmd_ln_free(void)
00998 {
00999 cmd_ln_free_r(global_cmdln);
01000 global_cmdln = NULL;
01001 }