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)
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 ** array = (
char **)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;
558 if (inout_cmdln == NULL) {
568 for (n = 0; defn[n].name; n++) {
572 if (strict && (v != &defn[n])) {
573 E_ERROR(
"Duplicate argument name in definition: %s\n", defn[n].name);
584 if (cmdln->ht == NULL)
590 if (argc > 0 && argv[0][0] !=
'-') {
595 for (j = argstart; j < argc; j += 2) {
602 E_ERROR(
"Unknown argument name '%s'\n", argv[j]);
605 else if (defn == NULL)
615 E_ERROR(
"Argument value for '%s' missing\n", argv[j]);
620 val = cmd_ln_val_init(
ARG_STRING, argv[j + 1]);
622 if ((val = cmd_ln_val_init(argdef->type, argv[j + 1])) == NULL) {
624 E_ERROR(
"Bad argument value for %s: %s\n", argv[j],
630 if ((v =
hash_table_enter(cmdln->ht, argv[j], (
void *)val)) != (
void *)val) {
632 cmd_ln_val_free(val);
633 E_ERROR(
"Duplicate argument name in arguments: %s\n",
645 for (i = 0; i < n; i++) {
650 if ((val = cmd_ln_val_init(defn[i].type, defn[i].deflt)) == NULL) {
652 (
"Bad default argument value for %s: %s\n",
653 defn[i].name, defn[i].deflt);
662 for (i = 0; i < n; i++) {
666 E_ERROR(
"Missing required argument %s\n", defn[i].name);
674 if (strict && argc == 1) {
675 E_ERROR(
"No arguments given, available options are:\n");
679 if (inout_cmdln == NULL)
691 E_INFO(
"Parsing command line:\n");
692 for (i = 0; i < argc; i++) {
693 if (argv[i][0] ==
'-')
711 if (inout_cmdln == NULL)
713 E_ERROR(
"Failed to parse arguments list\n");
721 const char *arg, *val;
725 va_start(args, strict);
727 while ((arg = va_arg(args,
const char *))) {
729 val = va_arg(args,
const char*);
731 E_ERROR(
"Number of arguments must be even!\n");
740 va_start(args, strict);
742 while ((arg = va_arg(args,
const char *))) {
745 val = va_arg(args,
const char*);
751 return parse_options(inout_cmdln, defn, f_argc, f_argv, strict);
762 E_ERROR(
"Failed to parse arguments list, forced exit\n");
766 if (global_cmdln == NULL) {
767 global_cmdln = cmdln;
779 int arg_max_length = 512;
784 const char separator[] =
" \t\r\n";
786 if ((file = fopen(filename,
"r")) == NULL) {
787 E_ERROR(
"Cannot open configuration file %s for reading\n",
794 for (; ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
806 f_argv =
ckd_calloc(argv_size,
sizeof(
char *));
808 str =
ckd_calloc(arg_max_length + 1,
sizeof(
char));
813 if (len == 0 && argc % 2 == 0) {
816 for (ch = fgetc(file); ch != EOF && ch !=
'\n'; ch = fgetc(file)) ;
818 for (ch = fgetc(file); ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
827 if (ch ==
'"' || ch ==
'\'') {
831 E_ERROR(
"Nesting quotations is not supported!\n");
838 else if (ch == EOF || (!quoting && strchr(separator, ch))) {
840 if (argc >= argv_size) {
843 ckd_realloc(f_argv, argv_size * 2 *
sizeof(
char *)))) {
857 E_WARN(
"Unclosed quotation, having EOF close it...\n");
860 for (; ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
869 if (len >= arg_max_length) {
872 if ((tmp_str =
ckd_realloc(str, (1 + arg_max_length * 2) *
sizeof(
char))) == NULL) {
893 for (ch = 0; ch < argc; ++ch)
899 return parse_options(inout_cmdln, defn, argc, f_argv, strict);
912 if (global_cmdln == NULL) {
913 global_cmdln = cmdln;
923 fprintf(fp,
"Arguments list definition:\n");
924 arg_dump_r(cmdln, fp, defn, 1);
942 E_ERROR(
"Unknown argument: %s\n", name);
955 return (
char const *)val->ptr;
965 return (
char const **)val->ptr;
994 E_ERROR(
"Unknown argument: %s\n", name);
1010 E_ERROR(
"Unknown argument: %s\n", name);
1022 E_ERROR(
"Unknown argument: %s\n", name);
1040 if (--cmdln->refcount > 0)
1041 return cmdln->refcount;
1049 for (gn = entries; gn; gn = gnode_next(gn)) {
1058 if (cmdln->f_argv) {
1060 for (i = 0; i < cmdln->f_argc; ++i) {
1064 cmdln->f_argv = NULL;
1075 global_cmdln = NULL;
#define REQARG_BOOLEAN
Required boolean argument.
Command-line and other configurationparsing and handling.
SPHINXBASE_EXPORT cmd_ln_t * cmd_ln_retain(cmd_ln_t *cmdln)
Retain ownership of a command-line argument set.
Miscellaneous useful string functions.
SPHINXBASE_EXPORT double cmd_ln_float_r(cmd_ln_t *cmdln, char const *name)
Retrieve a floating-point number from a command-line object.
SPHINXBASE_EXPORT long cmd_ln_int_r(cmd_ln_t *cmdln, char const *name)
Retrieve an integer from a command-line object.
SPHINXBASE_EXPORT int32 hash_table_lookup(hash_table_t *h, const char *key, void **val)
Look up a key in a hash table and optionally return the associated value.
#define ckd_calloc(n, sz)
Macros to simplify the use of above functions.
SPHINXBASE_EXPORT FILE * err_get_logfp(void)
Get the current logging filehandle.
#define REQARG_INTEGER
Required integer argument.
#define ARG_REQUIRED
Bit indicating a required argument.
#define ARG_STRING_LIST
Boolean (true/false) argument (optional).
SPHINXBASE_EXPORT anytype_t * cmd_ln_access_r(cmd_ln_t *cmdln, char const *name)
Access the generic type union for a command line argument.
SPHINXBASE_EXPORT void * hash_table_replace(hash_table_t *h, const char *key, void *val)
Add a new entry with given key and value to hash table h.
#define E_INFO
Print logging information to standard error stream.
Sphinx's memory allocation/deallocation routines.
SPHINXBASE_EXPORT void cmd_ln_set_int_r(cmd_ln_t *cmdln, char const *name, long iv)
Set an integer in a command-line object.
SPHINXBASE_EXPORT glist_t hash_table_tolist(hash_table_t *h, int32 *count)
Build a glist of valid hash_entry_t pointers from the given hash table.
#define REQARG_FLOATING
Required floating point argument.
SPHINXBASE_EXPORT int cmd_ln_free_r(cmd_ln_t *cmdln)
Release a command-line argument set and all associated strings.
SPHINXBASE_EXPORT int cmd_ln_exists_r(cmd_ln_t *cmdln, char const *name)
Re-entrant version of cmd_ln_exists().
SPHINXBASE_EXPORT cmd_ln_t * cmd_ln_parse_r(cmd_ln_t *inout_cmdln, arg_t const *defn, int32 argc, char *argv[], int32 strict)
Parse a list of strings into argumetns.
#define ARG_STRING
String argument (optional).
A node in a generic list.
#define ckd_salloc(ptr)
Macro for ckd_salloc
SPHINXBASE_EXPORT char const * cmd_ln_str_r(cmd_ln_t *cmdln, char const *name)
Retrieve a string from a command-line object.
SPHINXBASE_EXPORT hash_table_t * hash_table_new(int32 size, int32 casearg)
Allocate a new hash table for a given expected size.
SPHINXBASE_EXPORT char const ** cmd_ln_str_list_r(cmd_ln_t *cmdln, char const *name)
Retrieve an array of strings from a command-line object.
#define REQARG_STRING
Required string argument.
SPHINXBASE_EXPORT void ckd_free(void *ptr)
Test and free a 1-D array.
SPHINXBASE_EXPORT cmd_ln_t * cmd_ln_get(void)
Retrieve the global cmd_ln_t object used by non-re-entrant functions.
#define E_WARN
Print warning information to standard error stream.
SPHINXBASE_EXPORT int32 strcmp_nocase(const char *str1, const char *str2)
(FIXME! The implementation is incorrect!) Case insensitive string compare.
#define cmd_ln_print_help(f, d)
Print a help message listing the valid argument names, and the associated attributes as given in defn...
SPHINXBASE_EXPORT int err_set_logfile(char const *file)
Append all log messages to a given file.
SPHINXBASE_EXPORT void cmd_ln_print_help_r(cmd_ln_t *cmdln, FILE *fp, const arg_t *defn)
Print a help message listing the valid argument names, and the associated attributes as given in defn...
SPHINXBASE_EXPORT void hash_table_free(hash_table_t *h)
Free the specified hash table; the caller is responsible for freeing the key strings pointed to by th...
A note by ARCHAN at 20050510: Technically what we use is so-called "hash table with buckets" which is...
SPHINXBASE_EXPORT double atof_c(char const *str)
Locale independent version of atof().
SPHINXBASE_EXPORT void glist_free(glist_t g)
Free the given generic list; user-defined data contained within is not automatically freed...
SPHINXBASE_EXPORT cmd_ln_t * cmd_ln_init(cmd_ln_t *inout_cmdln, arg_t const *defn, int32 strict,...)
Create a cmd_ln_t from NULL-terminated list of arguments.
SPHINXBASE_EXPORT void cmd_ln_appl_exit(void)
Finalization routine corresponding to cmd_ln_appl_enter().
#define gnode_ptr(g)
Head of a list of gnodes.
#define E_INFOCONT
Print logging information without header, to standard error stream.
Implementation of logging routines.
#define ARG_BOOLEAN
Boolean (true/false) argument (optional).
SPHINXBASE_EXPORT void * hash_table_enter(hash_table_t *h, const char *key, void *val)
Try to add a new entry with given key and associated value to hash table h.
SPHINXBASE_EXPORT cmd_ln_t * cmd_ln_parse_file_r(cmd_ln_t *inout_cmdln, arg_t const *defn, char const *filename, int32 strict)
Parse an arguments file by deliminating on " \r\t\n" and putting each tokens into an argv[] for cmd_l...
Argument definition structure.
Opaque structure used to hold the results of command-line parsing.
SPHINXBASE_EXPORT void cmd_ln_set_float_r(cmd_ln_t *cmdln, char const *name, double fv)
Set a floating-point number in a command-line object.
#define E_ERROR
Print error message to standard error stream.
Hash table implementation.
SPHINXBASE_EXPORT int32 cmd_ln_parse(const arg_t *defn, int32 argc, char *argv[], int32 strict)
Non-reentrant version of cmd_ln_parse().
SPHINXBASE_EXPORT void cmd_ln_set_str_r(cmd_ln_t *cmdln, char const *name, char const *str)
Set a string in a command-line object.
#define ARG_FLOATING
Floating point argument (optional).
void * val
Key-length; the key string does not have to be a C-style NULL terminated string; it can have arbitrar...
SPHINXBASE_EXPORT void cmd_ln_free(void)
Free the global command line, if any exists.
#define ckd_realloc(ptr, sz)
Macro for ckd_realloc
#define ARG_INTEGER
Integer argument (optional).
SPHINXBASE_EXPORT void cmd_ln_appl_enter(int argc, char *argv[], char const *default_argfn, const arg_t *defn)
Old application initialization routine for Sphinx3 code.
Locale-independent implementation of case swapping operation.
SPHINXBASE_EXPORT int32 cmd_ln_parse_file(const arg_t *defn, char const *filename, int32 strict)
Parse an arguments file by deliminating on " \r\t\n" and putting each tokens into an argv[] for cmd_l...