67 #pragma warning (disable: 4996 4018) 104 parse_options(
cmd_ln_t *,
const arg_t *, int32,
char* [], int32);
111 arg_strlen(
const arg_t * defn, int32 * namelen, int32 * deflen)
115 *namelen = *deflen = 0;
116 for (i = 0; defn[i].name; i++) {
117 l = strlen(defn[i].name);
122 l = strlen(defn[i].deflt);
124 l = strlen(
"(null)");
135 cmp_name(
const void *a,
const void *b)
138 ((* (
arg_t**) a)->name,
139 (* (
arg_t**) b)->name));
142 static arg_t const **
143 arg_sort(
const arg_t * defn, int32 n)
149 for (i = 0; i < n; ++i)
151 qsort(pos, n,
sizeof(
arg_t *), cmp_name);
157 strnappend(
char **dest,
size_t *dest_allocation,
158 const char *source,
size_t n)
160 size_t source_len, required_allocation;
162 if (dest == NULL || dest_allocation == NULL)
164 if (*dest == NULL && *dest_allocation != 0)
167 return *dest_allocation;
169 source_len = strlen(source);
170 if (n && n < source_len)
173 required_allocation = (*dest ? strlen(*dest) : 0) + source_len + 1;
174 if (*dest_allocation < required_allocation) {
175 if (*dest_allocation == 0) {
176 *dest = (
char *)
ckd_calloc(required_allocation * 2, 1);
178 *dest = (
char *)
ckd_realloc(*dest, required_allocation * 2);
180 *dest_allocation = required_allocation * 2;
183 strncat(*dest, source, source_len);
185 return *dest_allocation;
189 strappend(
char **dest,
size_t *dest_allocation,
192 return strnappend(dest, dest_allocation, source, 0);
196 arg_resolve_env(
const char *str)
198 char *resolved_str = NULL;
202 const char *i = str, *j;
209 strnappend(&resolved_str, &alloced, i, j - i);
212 j = strchr(i + 2,
')');
214 if (j - (i + 2) < 100) {
215 strncpy(env_name, i + 2, j - (i + 2));
216 env_name[j - (i + 2)] =
'\0';
217 #if !defined(_WIN32_WCE) 218 env_val = getenv(env_name);
220 strappend(&resolved_str, &alloced, env_val);
229 strnappend(&resolved_str, &alloced, i, j - i);
233 strappend(&resolved_str, &alloced, i);
241 arg_dump_r(
cmd_ln_t *cmdln, FILE *fp,
const arg_t * defn, int32 doc)
246 int32 namelen, deflen;
251 if (defn == NULL || fp == NULL)
255 n = arg_strlen(defn, &namelen, &deflen);
257 namelen = namelen & 0xfffffff8;
258 deflen = deflen & 0xfffffff8;
260 fprintf(fp,
"[NAME]");
261 for (l = strlen(
"[NAME]"); l < namelen; l += 8)
263 fprintf(fp,
"\t[DEFLT]");
264 for (l = strlen(
"[DEFLT]"); l < deflen; l += 8)
268 fprintf(fp,
"\t[DESCR]\n");
271 fprintf(fp,
"\t[VALUE]\n");
275 pos = arg_sort(defn, n);
276 for (i = 0; i < n; i++) {
277 fprintf(fp,
"%s", pos[i]->name);
278 for (l = strlen(pos[i]->name); l < namelen; l += 8)
283 fprintf(fp,
"%s", pos[i]->deflt);
284 l = strlen(pos[i]->deflt);
288 for (; l < deflen; l += 8)
294 fprintf(fp,
"%s", pos[i]->doc);
299 switch (pos[i]->type) {
302 fprintf(fp,
"%ld", vp->i);
306 fprintf(fp,
"%e", vp->fl);
311 fprintf(fp,
"%s", (
char *)vp->ptr);
314 array = (
char const**)vp->ptr;
316 for (l = 0; array[l] != 0; l++) {
317 fprintf(fp,
"%s,", array[l]);
322 fprintf(fp,
"%s", vp->i ?
"yes" :
"no");
325 E_ERROR(
"Unknown argument type: %d\n", pos[i]->type);
338 parse_string_list(
const char *str)
352 result = (
char **)
ckd_calloc(count + 1,
sizeof(
char *));
354 for (i = 0; i < count; i++) {
355 for (j = 0; p[j] !=
',' && p[j] != 0; j++);
356 result[i] = (
char *)
ckd_calloc(j + 1,
sizeof(
char));
357 strncpy( result[i], p, j);
364 cmd_ln_val_init(
int t,
const char *str)
372 memset(&val, 0,
sizeof(val));
376 e_str = arg_resolve_env(str);
381 if (sscanf(e_str,
"%ld", &val.i) != 1)
386 if (e_str == NULL || e_str[0] == 0)
392 if ((e_str[0] ==
'y') || (e_str[0] ==
't') ||
393 (e_str[0] ==
'Y') || (e_str[0] ==
'T') || (e_str[0] ==
'1')) {
396 else if ((e_str[0] ==
'n') || (e_str[0] ==
'f') ||
397 (e_str[0] ==
'N') || (e_str[0] ==
'F') |
402 E_ERROR(
"Unparsed boolean value '%s'\n", str);
411 val.ptr = parse_string_list(e_str);
414 E_ERROR(
"Unknown argument type: %d\n", t);
424 memcpy(v, &val,
sizeof(val));
436 parse_options(
cmd_ln_t *cmdln,
const arg_t *defn, int32 argc,
char* argv[], int32 strict)
442 if (new_cmdln == NULL) {
444 for (i = 0; i < argc; ++i)
451 if (new_cmdln == cmdln) {
454 new_cmdln->f_argv = (
char **)
ckd_realloc(new_cmdln->f_argv,
455 (new_cmdln->f_argc + argc)
456 *
sizeof(*new_cmdln->f_argv));
457 memcpy(new_cmdln->f_argv + new_cmdln->f_argc, argv,
458 argc *
sizeof(*argv));
460 new_cmdln->f_argc += argc;
464 new_cmdln->f_argc = argc;
465 new_cmdln->f_argv = argv;
476 char ** array = (
char **)val->val.ptr;
478 for (i = 0; array[i] != NULL; i++) {
497 const char *default_argfn,
505 if ((argc == 2) && (strcmp(argv[1],
"help") == 0)) {
510 if ((argc == 2) && (argv[1][0] !=
'-'))
512 else if (argc == 1) {
514 E_INFO(
"Looking for default argument file: %s\n", default_argfn);
516 if ((fp = fopen(default_argfn,
"r")) == NULL) {
517 E_INFO(
"Can't find default argument file %s.\n",
530 E_INFO(
"Parsing command lines from file %s\n", str);
533 E_INFOCONT(
"\t%s argument-list, or\n", argv[0]);
534 E_INFOCONT(
"\t%s [argument-file] (default file: . %s)\n\n",
535 argv[0], default_argfn);
555 int32 i, j, n, argstart;
560 if (inout_cmdln == NULL) {
570 for (n = 0; defn[n].name; n++) {
574 if (strict && (v != &defn[n])) {
575 E_ERROR(
"Duplicate argument name in definition: %s\n", defn[n].name);
586 if (cmdln->ht == NULL)
592 if (argc > 0 && argv[0][0] !=
'-') {
597 for (j = argstart; j < argc; j += 2) {
604 E_ERROR(
"Unknown argument name '%s'\n", argv[j]);
607 else if (defn == NULL)
617 E_ERROR(
"Argument value for '%s' missing\n", argv[j]);
622 val = cmd_ln_val_init(
ARG_STRING, argv[j + 1]);
624 if ((val = cmd_ln_val_init(argdef->type, argv[j + 1])) == NULL) {
626 E_ERROR(
"Bad argument value for %s: %s\n", argv[j],
636 cmd_ln_val_free(val);
637 E_ERROR(
"Duplicate argument name in arguments: %s\n",
649 for (i = 0; i < n; i++) {
654 if ((val = cmd_ln_val_init(defn[i].type, defn[i].deflt)) == NULL) {
656 (
"Bad default argument value for %s: %s\n",
657 defn[i].name, defn[i].deflt);
666 for (i = 0; i < n; i++) {
670 E_ERROR(
"Missing required argument %s\n", defn[i].name);
678 if (strict && argc == 1) {
679 E_ERROR(
"No arguments given, available options are:\n");
683 if (inout_cmdln == NULL)
699 if (inout_cmdln == NULL)
701 E_ERROR(
"Failed to parse arguments list\n");
709 const char *arg, *val;
713 va_start(args, strict);
715 while ((arg = va_arg(args,
const char *))) {
717 val = va_arg(args,
const char*);
719 E_ERROR(
"Number of arguments must be even!\n");
727 f_argv = (
char**)
ckd_calloc(f_argc,
sizeof(*f_argv));
728 va_start(args, strict);
730 while ((arg = va_arg(args,
const char *))) {
733 val = va_arg(args,
const char*);
739 return parse_options(inout_cmdln, defn, f_argc, f_argv, strict);
750 E_ERROR(
"Failed to parse arguments list, forced exit\n");
754 if (global_cmdln == NULL) {
755 global_cmdln = cmdln;
767 int arg_max_length = 512;
772 const char separator[] =
" \t\r\n";
774 if ((file = fopen(filename,
"r")) == NULL) {
775 E_ERROR(
"Cannot open configuration file %s for reading\n",
782 for (; ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
794 f_argv = (
char **)
ckd_calloc(argv_size,
sizeof(
char *));
796 str = (
char* )
ckd_calloc(arg_max_length + 1,
sizeof(
char));
801 if (len == 0 && argc % 2 == 0) {
804 for (ch = fgetc(file); ch != EOF && ch !=
'\n'; ch = fgetc(file)) ;
806 for (ch = fgetc(file); ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
815 if (ch ==
'"' || ch ==
'\'') {
819 E_ERROR(
"Nesting quotations is not supported!\n");
826 else if (ch == EOF || (!quoting && strchr(separator, ch))) {
828 if (argc >= argv_size) {
831 (
char **)
ckd_realloc(f_argv, argv_size * 2 *
sizeof(
char *)))) {
845 E_WARN(
"Unclosed quotation, having EOF close it...\n");
848 for (; ch != EOF && strchr(separator, ch); ch = fgetc(file)) ;
857 if (len >= arg_max_length) {
860 if ((tmp_str = (
char *)
ckd_realloc(str, (1 + arg_max_length * 2) *
sizeof(
char))) == NULL) {
881 for (ch = 0; ch < argc; ++ch)
887 return parse_options(inout_cmdln, defn, argc, f_argv, strict);
900 if (global_cmdln == NULL) {
901 global_cmdln = cmdln;
911 fprintf(fp,
"Arguments list definition:\n");
912 arg_dump_r(cmdln, fp, defn, TRUE);
920 fprintf(fp,
"Current configuration:\n");
921 arg_dump_r(cmdln, fp, defn, FALSE);
938 E_ERROR(
"Unknown argument: %s\n", name);
951 return (
char const *)val->ptr;
961 return (
char const **)val->ptr;
990 E_ERROR(
"Unknown argument: %s\n", name);
1006 E_ERROR(
"Unknown argument: %s\n", name);
1018 E_ERROR(
"Unknown argument: %s\n", name);
1036 if (--cmdln->refcount > 0)
1037 return cmdln->refcount;
1045 for (gn = entries; gn; gn = gnode_next(gn)) {
1054 if (cmdln->f_argv) {
1056 for (i = 0; i < cmdln->f_argc; ++i) {
1060 cmdln->f_argv = NULL;
1071 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.
#define E_INFO(...)
Print logging information to standard error stream.
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 E_ERROR(...)
Print error message to error log.
#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.
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.
#define E_INFOCONT(...)
Continue printing the information to standard error stream.
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.
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 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...
SPHINXBASE_EXPORT void cmd_ln_print_values_r(cmd_ln_t *cmdln, FILE *fp, const arg_t *defn)
Print current configuration values and defaults.
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.
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.
#define E_WARN(...)
Print warning message to error log.
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.
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...