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