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 env_val = getenv(env_name);
00213 if (env_val)
00214 strappend(&resolved_str, &alloced, env_val);
00215 }
00216 i = j + 1;
00217 } else {
00218
00219 j = i + 2;
00220 strnappend(&resolved_str, &alloced, i, j - i);
00221 i = j;
00222 }
00223 } else {
00224 strappend(&resolved_str, &alloced, i);
00225 }
00226 } while(j != NULL);
00227
00228 return resolved_str;
00229 }
00230
00231 static void
00232 arg_dump_r(cmd_ln_t *cmdln, FILE * fp, const arg_t * defn, int32 doc)
00233 {
00234 const arg_t **pos;
00235 int32 i, l, n;
00236 int32 namelen, deflen;
00237 anytype_t *vp;
00238
00239
00240 if (defn == NULL)
00241 return;
00242 if (fp == NULL)
00243 return;
00244
00245
00246 n = arg_strlen(defn, &namelen, &deflen);
00247
00248 namelen = namelen & 0xfffffff8;
00249 deflen = deflen & 0xfffffff8;
00250
00251 fprintf(fp, "[NAME]");
00252 for (l = strlen("[NAME]"); l < namelen; l += 8)
00253 fprintf(fp, "\t");
00254 fprintf(fp, "\t[DEFLT]");
00255 for (l = strlen("[DEFLT]"); l < deflen; l += 8)
00256 fprintf(fp, "\t");
00257
00258 if (doc) {
00259 fprintf(fp, "\t[DESCR]\n");
00260 }
00261 else {
00262 fprintf(fp, "\t[VALUE]\n");
00263 }
00264
00265
00266 pos = arg_sort(defn, n);
00267 for (i = 0; i < n; i++) {
00268 fprintf(fp, "%s", pos[i]->name);
00269 for (l = strlen(pos[i]->name); l < namelen; l += 8)
00270 fprintf(fp, "\t");
00271
00272 fprintf(fp, "\t");
00273 if (pos[i]->deflt) {
00274 fprintf(fp, "%s", pos[i]->deflt);
00275 l = strlen(pos[i]->deflt);
00276 }
00277 else
00278 l = 0;
00279 for (; l < deflen; l += 8)
00280 fprintf(fp, "\t");
00281
00282 fprintf(fp, "\t");
00283 if (doc) {
00284 if (pos[i]->doc)
00285 fprintf(fp, "%s", pos[i]->doc);
00286 }
00287 else {
00288 vp = cmd_ln_access_r(cmdln, pos[i]->name);
00289 if (vp) {
00290 switch (pos[i]->type) {
00291 case ARG_INTEGER:
00292 case REQARG_INTEGER:
00293 fprintf(fp, "%ld", vp->i);
00294 break;
00295 case ARG_FLOATING:
00296 case REQARG_FLOATING:
00297 fprintf(fp, "%e", vp->fl);
00298 break;
00299 case ARG_STRING:
00300 case REQARG_STRING:
00301 if (vp->ptr)
00302 fprintf(fp, "%s", (char *)vp->ptr);
00303 break;
00304 case ARG_BOOLEAN:
00305 case REQARG_BOOLEAN:
00306 fprintf(fp, "%s", vp->i ? "yes" : "no");
00307 break;
00308 default:
00309 E_ERROR("Unknown argument type: %d\n", pos[i]->type);
00310 }
00311 }
00312 }
00313
00314 fprintf(fp, "\n");
00315 }
00316 ckd_free(pos);
00317
00318 fprintf(fp, "\n");
00319 fflush(fp);
00320 }
00321
00322 static cmd_ln_val_t *
00323 cmd_ln_val_init(int t, const char *str)
00324 {
00325 cmd_ln_val_t *v;
00326 anytype_t val;
00327 char *e_str;
00328
00329 if (!str) {
00330
00331 memset(&val, 0, sizeof(val));
00332 }
00333 else {
00334 int valid = 1;
00335 e_str = arg_resolve_env(str);
00336
00337 switch (t) {
00338 case ARG_INTEGER:
00339 case REQARG_INTEGER:
00340 if (sscanf(e_str, "%ld", &val.i) != 1)
00341 valid = 0;
00342 break;
00343 case ARG_FLOATING:
00344 case REQARG_FLOATING:
00345 if (sscanf(e_str, "%lf", &val.fl) != 1)
00346 valid = 0;
00347 break;
00348 case ARG_BOOLEAN:
00349 case REQARG_BOOLEAN:
00350 if ((e_str[0] == 'y') || (e_str[0] == 't') ||
00351 (e_str[0] == 'Y') || (e_str[0] == 'T') || (e_str[0] == '1')) {
00352 val.i = TRUE;
00353 }
00354 else if ((e_str[0] == 'n') || (e_str[0] == 'f') ||
00355 (e_str[0] == 'N') || (e_str[0] == 'F') |
00356 (e_str[0] == '0')) {
00357 val.i = FALSE;
00358 }
00359 else {
00360 E_ERROR("Unparsed boolean value '%s'\n", str);
00361 valid = 0;
00362 }
00363 break;
00364 case ARG_STRING:
00365 case REQARG_STRING:
00366 val.ptr = ckd_salloc(e_str);
00367 break;
00368 default:
00369 E_ERROR("Unknown argument type: %d\n", t);
00370 valid = 0;
00371 }
00372
00373 ckd_free(e_str);
00374 if (valid == 0)
00375 return NULL;
00376 }
00377
00378 v = ckd_calloc(1, sizeof(*v));
00379 memcpy(v, &val, sizeof(val));
00380 v->type = t;
00381
00382 return v;
00383 }
00384
00385
00386
00387
00388
00389
00390 static cmd_ln_t *
00391 parse_options(cmd_ln_t *cmdln, const arg_t *defn, int32 argc, char* argv[], int32 strict)
00392 {
00393 cmd_ln_t *new_cmdln;
00394
00395 new_cmdln = cmd_ln_parse_r(cmdln, defn, argc, argv, strict);
00396
00397 if (new_cmdln == NULL) {
00398 int32 i;
00399 for (i = 0; i < argc; ++i)
00400 ckd_free(argv[i]);
00401 ckd_free(argv);
00402 return NULL;
00403 }
00404
00405
00406 if (new_cmdln == cmdln) {
00407
00408
00409 new_cmdln->f_argv = ckd_realloc(new_cmdln->f_argv,
00410 (new_cmdln->f_argc + argc)
00411 * sizeof(*new_cmdln->f_argv));
00412 memcpy(new_cmdln->f_argv + new_cmdln->f_argc, argv,
00413 argc * sizeof(*argv));
00414 ckd_free(argv);
00415 new_cmdln->f_argc += argc;
00416 }
00417 else {
00418
00419 new_cmdln->f_argc = argc;
00420 new_cmdln->f_argv = argv;
00421 }
00422
00423 return new_cmdln;
00424 }
00425
00426 void
00427 cmd_ln_val_free(cmd_ln_val_t *val)
00428 {
00429 if (val->type & ARG_STRING)
00430 ckd_free(val->val.ptr);
00431 ckd_free(val);
00432 }
00433
00434 cmd_ln_t *
00435 cmd_ln_get(void)
00436 {
00437 return global_cmdln;
00438 }
00439
00440 void
00441 cmd_ln_appl_enter(int argc, char *argv[],
00442 const char *default_argfn,
00443 const arg_t * defn)
00444 {
00445
00446 const char *str;
00447
00448 str = NULL;
00449
00450 if ((argc == 2) && (strcmp(argv[1], "help") == 0)) {
00451 cmd_ln_print_help(stderr, defn);
00452 exit(1);
00453 }
00454
00455 if ((argc == 2) && (argv[1][0] != '-'))
00456 str = argv[1];
00457 else if (argc == 1) {
00458 FILE *fp;
00459 E_INFO("Looking for default argument file: %s\n", default_argfn);
00460
00461 if ((fp = fopen(default_argfn, "r")) == NULL) {
00462 E_INFO("Can't find default argument file %s.\n",
00463 default_argfn);
00464 }
00465 else {
00466 str = default_argfn;
00467 }
00468 if (fp != NULL)
00469 fclose(fp);
00470 }
00471
00472
00473 if (str) {
00474
00475 E_INFO("Parsing command lines from file %s\n", str);
00476 if (cmd_ln_parse_file(defn, str, TRUE)) {
00477 E_INFOCONT("Usage:\n");
00478 E_INFOCONT("\t%s argument-list, or\n", argv[0]);
00479 E_INFOCONT("\t%s [argument-file] (default file: . %s)\n\n",
00480 argv[0], default_argfn);
00481 cmd_ln_print_help(stderr, defn);
00482 exit(1);
00483 }
00484 }
00485 else {
00486 cmd_ln_parse(defn, argc, argv, TRUE);
00487 }
00488 }
00489
00490 void
00491 cmd_ln_appl_exit()
00492 {
00493 cmd_ln_free();
00494 }
00495
00496
00497 cmd_ln_t *
00498 cmd_ln_parse_r(cmd_ln_t *inout_cmdln, const arg_t * defn, int32 argc, char *argv[], int strict)
00499 {
00500 int32 i, j, n;
00501 hash_table_t *defidx = NULL;
00502 cmd_ln_t *cmdln;
00503
00504
00505 #ifndef _WIN32_WCE
00506 E_INFO("Parsing command line:\n");
00507 for (i = 0; i < argc; i++) {
00508 if (argv[i][0] == '-')
00509 E_INFOCONT("\\\n\t");
00510 E_INFOCONT("%s ", argv[i]);
00511 }
00512 E_INFOCONT("\n\n");
00513 fflush(stderr);
00514 #endif
00515
00516
00517 if (inout_cmdln == NULL) {
00518 cmdln = ckd_calloc(1, sizeof(*cmdln));
00519 cmdln->refcount = 1;
00520 }
00521 else
00522 cmdln = inout_cmdln;
00523
00524
00525 defidx = hash_table_new(50, 0);
00526 if (defn) {
00527 for (n = 0; defn[n].name; n++) {
00528 void *v;
00529
00530 v = hash_table_enter(defidx, defn[n].name, (void *)&defn[n]);
00531 if (strict && (v != &defn[n])) {
00532 E_ERROR("Duplicate argument name in definition: %s\n", defn[n].name);
00533 goto error;
00534 }
00535 }
00536 }
00537 else {
00538
00539 n = 0;
00540 }
00541
00542
00543 if (cmdln->ht == NULL)
00544 cmdln->ht = hash_table_new(n, 0 );
00545
00546
00547 for (j = argc % 2; j < argc; j += 2) {
00548 arg_t *argdef;
00549 cmd_ln_val_t *val;
00550 void *v;
00551
00552 if (j + 1 >= argc) {
00553 cmd_ln_print_help_r(cmdln, stderr, defn);
00554 E_ERROR("Argument value for '%s' missing\n", argv[j]);
00555 goto error;
00556 }
00557 if (hash_table_lookup(defidx, argv[j], &v) < 0) {
00558 if (strict) {
00559 E_ERROR("Unknown argument name '%s'\n", argv[j]);
00560 goto error;
00561 }
00562 else if (defn == NULL)
00563 v = NULL;
00564 else
00565 continue;
00566 }
00567 argdef = v;
00568
00569
00570 if (argdef == NULL)
00571 val = cmd_ln_val_init(ARG_STRING, argv[j + 1]);
00572 else {
00573 if ((val = cmd_ln_val_init(argdef->type, argv[j + 1])) == NULL) {
00574 cmd_ln_print_help_r(cmdln, stderr, defn);
00575 E_ERROR("Bad argument value for %s: %s\n", argv[j],
00576 argv[j + 1]);
00577 goto error;
00578 }
00579 }
00580
00581 if ((v = hash_table_enter(cmdln->ht, argv[j], (void *)val)) != (void *)val) {
00582 if (strict) {
00583 cmd_ln_val_free(val);
00584 E_ERROR("Duplicate argument name in arguments: %s\n",
00585 argdef->name);
00586 goto error;
00587 }
00588 else {
00589 v = hash_table_replace(cmdln->ht, argv[j], (void *)val);
00590 cmd_ln_val_free((cmd_ln_val_t *)v);
00591 }
00592 }
00593 }
00594
00595
00596 for (i = 0; i < n; i++) {
00597 cmd_ln_val_t *val;
00598 void *v;
00599
00600 if (hash_table_lookup(cmdln->ht, defn[i].name, &v) < 0) {
00601 if ((val = cmd_ln_val_init(defn[i].type, defn[i].deflt)) == NULL) {
00602 E_ERROR
00603 ("Bad default argument value for %s: %s\n",
00604 defn[i].name, defn[i].deflt);
00605 goto error;
00606 }
00607 hash_table_enter(cmdln->ht, defn[i].name, (void *)val);
00608 }
00609 }
00610
00611
00612 j = 0;
00613 for (i = 0; i < n; i++) {
00614 if (defn[i].type & ARG_REQUIRED) {
00615 void *v;
00616 if (hash_table_lookup(cmdln->ht, defn[i].name, &v) != 0)
00617 E_ERROR("Missing required argument %s\n", defn[i].name);
00618 }
00619 }
00620 if (j > 0) {
00621 cmd_ln_print_help_r(cmdln, stderr, defn);
00622 goto error;
00623 }
00624
00625 if (strict && argc == 1) {
00626 E_ERROR("No arguments given, exiting\n");
00627 cmd_ln_print_help_r(cmdln, stderr, defn);
00628 goto error;
00629 }
00630
00631 #ifndef _WIN32_WCE
00632
00633 E_INFOCONT("Current configuration:\n");
00634 arg_dump_r(cmdln, err_get_logfp(), defn, 0);
00635 #endif
00636 hash_table_free(defidx);
00637 return cmdln;
00638
00639 error:
00640 if (defidx)
00641 hash_table_free(defidx);
00642 if (inout_cmdln == NULL)
00643 cmd_ln_free_r(cmdln);
00644 E_ERROR("cmd_ln_parse_r failed\n");
00645 return NULL;
00646 }
00647
00648 cmd_ln_t *
00649 cmd_ln_init(cmd_ln_t *inout_cmdln, const arg_t *defn, int32 strict, ...)
00650 {
00651 va_list args;
00652 const char *arg, *val;
00653 char **f_argv;
00654 int32 f_argc;
00655
00656 va_start(args, strict);
00657 f_argc = 0;
00658 while ((arg = va_arg(args, const char *))) {
00659 ++f_argc;
00660 val = va_arg(args, const char*);
00661 if (val == NULL) {
00662 E_ERROR("Number of arguments must be even!\n");
00663 return NULL;
00664 }
00665 ++f_argc;
00666 }
00667 va_end(args);
00668
00669
00670 f_argv = ckd_calloc(f_argc, sizeof(*f_argv));
00671 va_start(args, strict);
00672 f_argc = 0;
00673 while ((arg = va_arg(args, const char *))) {
00674 f_argv[f_argc] = ckd_salloc(arg);
00675 ++f_argc;
00676 val = va_arg(args, const char*);
00677 f_argv[f_argc] = ckd_salloc(val);
00678 ++f_argc;
00679 }
00680 va_end(args);
00681
00682 return parse_options(inout_cmdln, defn, f_argc, f_argv, strict);
00683 }
00684
00685 int
00686 cmd_ln_parse(const arg_t * defn, int32 argc, char *argv[], int strict)
00687 {
00688 cmd_ln_t *cmdln;
00689
00690 cmdln = cmd_ln_parse_r(global_cmdln, defn, argc, argv, strict);
00691 if (cmdln == NULL) {
00692
00693 E_ERROR("cmd_ln_parse failed, forced exit\n");
00694 exit(-1);
00695 }
00696
00697 if (global_cmdln == NULL) {
00698 global_cmdln = cmdln;
00699 }
00700 return 0;
00701 }
00702
00703 cmd_ln_t *
00704 cmd_ln_parse_file_r(cmd_ln_t *inout_cmdln, const arg_t * defn, const char *filename, int32 strict)
00705 {
00706 FILE *file;
00707 int argc;
00708 int argv_size;
00709 char *str;
00710 int arg_max_length = 512;
00711 int len = 0;
00712 int quoting, ch;
00713 char **f_argv;
00714 int rv = 0;
00715 const char separator[] = " \t\r\n";
00716
00717 if ((file = fopen(filename, "r")) == NULL) {
00718 E_ERROR("Cannot open configuration file %s for reading\n",
00719 filename);
00720 return NULL;
00721 }
00722
00723 ch = fgetc(file);
00724
00725 for (; ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
00726
00727 if (ch == EOF) {
00728 fclose(file);
00729 return NULL;
00730 }
00731
00732
00733
00734
00735 argv_size = 10;
00736 argc = 0;
00737 f_argv = ckd_calloc(argv_size, sizeof(char *));
00738
00739 str = ckd_calloc(arg_max_length + 1, sizeof(char));
00740 quoting = 0;
00741
00742 do {
00743
00744 if (len == 0 && ch == '#' && argc % 2 == 0) {
00745
00746 for (ch = fgetc(file); ch != EOF && ch != '\n'; ch = fgetc(file)) ;
00747
00748 for (ch = fgetc(file); ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
00749 if (ch == EOF)
00750 break;
00751 }
00752
00753
00754 if (ch == '"' || ch == '\'') {
00755 if (quoting == ch)
00756 quoting = 0;
00757 else if (quoting) {
00758 E_ERROR("Nesting quotations is not supported!\n");
00759 rv = 1;
00760 break;
00761 }
00762 else
00763 quoting = ch;
00764 }
00765 else if (ch == EOF || (!quoting && strchr(separator, ch))) {
00766
00767 if (argc >= argv_size) {
00768 char **tmp_argv;
00769 if (!(tmp_argv =
00770 ckd_realloc(f_argv, argv_size * 2 * sizeof(char *)))) {
00771 rv = 1;
00772 break;
00773 }
00774 f_argv = tmp_argv;
00775 argv_size *= 2;
00776 }
00777
00778 f_argv[argc] = ckd_salloc(str);
00779 len = 0;
00780 argc++;
00781
00782 if (quoting)
00783 E_WARN("Unclosed quotation, having EOF close it...\n");
00784
00785
00786 for (; ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
00787
00788 if (ch == EOF)
00789 break;
00790
00791
00792 continue;
00793 }
00794 else {
00795 if (len >= arg_max_length) {
00796
00797 char *tmp_str = str;
00798 if ((tmp_str = ckd_realloc(str, (1 + arg_max_length * 2) * sizeof(char))) == NULL) {
00799 rv = 1;
00800 break;
00801 }
00802 str = tmp_str;
00803 arg_max_length *= 2;
00804 }
00805
00806 str[len++] = ch;
00807
00808 str[len] = '\0';
00809 }
00810
00811 ch = fgetc(file);
00812 } while (1);
00813
00814 fclose(file);
00815
00816 ckd_free(str);
00817
00818 if (rv) {
00819 for (ch = 0; ch < argc; ++ch)
00820 ckd_free(f_argv[ch]);
00821 ckd_free(f_argv);
00822 return NULL;
00823 }
00824
00825 return parse_options(inout_cmdln, defn, argc, f_argv, strict);
00826 }
00827
00828 int
00829 cmd_ln_parse_file(const arg_t * defn, const char *filename, int32 strict)
00830 {
00831 cmd_ln_t *cmdln;
00832
00833 cmdln = cmd_ln_parse_file_r(global_cmdln, defn, filename, strict);
00834 if (cmdln == NULL) {
00835 return -1;
00836 }
00837
00838 if (global_cmdln == NULL) {
00839 global_cmdln = cmdln;
00840 }
00841 return 0;
00842 }
00843
00844 void
00845 cmd_ln_print_help_r(cmd_ln_t *cmdln, FILE * fp, arg_t const* defn)
00846 {
00847 if (defn == NULL)
00848 return;
00849 fprintf(fp, "Arguments list definition:\n");
00850 arg_dump_r(cmdln, fp, defn, 1);
00851 fflush(fp);
00852 }
00853
00854 int
00855 cmd_ln_exists_r(cmd_ln_t *cmdln, const char *name)
00856 {
00857 void *val;
00858 if (cmdln == NULL)
00859 return FALSE;
00860 return (hash_table_lookup(cmdln->ht, name, &val) == 0);
00861 }
00862
00863 anytype_t *
00864 cmd_ln_access_r(cmd_ln_t *cmdln, const char *name)
00865 {
00866 void *val;
00867 if (hash_table_lookup(cmdln->ht, name, &val) < 0) {
00868 E_ERROR("Unknown argument: %s\n", name);
00869 return NULL;
00870 }
00871 return (anytype_t *)val;
00872 }
00873
00874 char const *
00875 cmd_ln_str_r(cmd_ln_t *cmdln, char const *name)
00876 {
00877 anytype_t *val;
00878 val = cmd_ln_access_r(cmdln, name);
00879 if (val == NULL)
00880 return NULL;
00881 return (char const *)val->ptr;
00882 }
00883
00884 long
00885 cmd_ln_int_r(cmd_ln_t *cmdln, char const *name)
00886 {
00887 anytype_t *val;
00888 val = cmd_ln_access_r(cmdln, name);
00889 if (val == NULL)
00890 return 0L;
00891 return val->i;
00892 }
00893
00894 double
00895 cmd_ln_float_r(cmd_ln_t *cmdln, char const *name)
00896 {
00897 anytype_t *val;
00898 val = cmd_ln_access_r(cmdln, name);
00899 if (val == NULL)
00900 return 0.0;
00901 return val->fl;
00902 }
00903
00904 void
00905 cmd_ln_set_str_r(cmd_ln_t *cmdln, char const *name, char const *str)
00906 {
00907 anytype_t *val;
00908 val = cmd_ln_access_r(cmdln, name);
00909 if (val == NULL) {
00910 E_ERROR("Unknown argument: %s\n", name);
00911 return;
00912 }
00913 ckd_free(val->ptr);
00914 if (str == NULL)
00915 val->ptr = NULL;
00916 else
00917 val->ptr = ckd_salloc(str);
00918 }
00919
00920 void
00921 cmd_ln_set_int_r(cmd_ln_t *cmdln, char const *name, long iv)
00922 {
00923 anytype_t *val;
00924 val = cmd_ln_access_r(cmdln, name);
00925 if (val == NULL) {
00926 E_ERROR("Unknown argument: %s\n", name);
00927 return;
00928 }
00929 val->i = iv;
00930 }
00931
00932 void
00933 cmd_ln_set_float_r(cmd_ln_t *cmdln, char const *name, double fv)
00934 {
00935 anytype_t *val;
00936 val = cmd_ln_access_r(cmdln, name);
00937 if (val == NULL) {
00938 E_ERROR("Unknown argument: %s\n", name);
00939 return;
00940 }
00941 val->fl = fv;
00942 }
00943
00944 cmd_ln_t *
00945 cmd_ln_retain(cmd_ln_t *cmdln)
00946 {
00947 ++cmdln->refcount;
00948 return cmdln;
00949 }
00950
00951 int
00952 cmd_ln_free_r(cmd_ln_t *cmdln)
00953 {
00954 if (cmdln == NULL)
00955 return 0;
00956 if (--cmdln->refcount > 0)
00957 return cmdln->refcount;
00958
00959 if (cmdln->ht) {
00960 glist_t entries;
00961 gnode_t *gn;
00962 int32 n;
00963
00964 entries = hash_table_tolist(cmdln->ht, &n);
00965 for (gn = entries; gn; gn = gnode_next(gn)) {
00966 hash_entry_t *e = gnode_ptr(gn);
00967 cmd_ln_val_free((cmd_ln_val_t *)e->val);
00968 }
00969 glist_free(entries);
00970 hash_table_free(cmdln->ht);
00971 cmdln->ht = NULL;
00972 }
00973
00974 if (cmdln->f_argv) {
00975 int32 i;
00976 for (i = 0; i < cmdln->f_argc; ++i) {
00977 ckd_free(cmdln->f_argv[i]);
00978 }
00979 ckd_free(cmdln->f_argv);
00980 cmdln->f_argv = NULL;
00981 cmdln->f_argc = 0;
00982 }
00983 ckd_free(cmdln);
00984 return 0;
00985 }
00986
00987 void
00988 cmd_ln_free(void)
00989 {
00990 cmd_ln_free_r(global_cmdln);
00991 global_cmdln = NULL;
00992 }