⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmd_ln.c

📁 CMU大名鼎鼎的SPHINX-3大词汇量连续语音识别系统
💻 C
字号:
/* ==================================================================== * Copyright (c) 1999-2004 Carnegie Mellon University.  All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * * This work was supported in part by funding from the Defense Advanced  * Research Projects Agency and the National Science Foundation of the  * United States of America, and the CMU Sphinx Speech Consortium. * * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ==================================================================== * *//* * cmd_ln.c -- Command line argument parsing. * * ********************************************** * CMU ARPA Speech Project * * Copyright (c) 1999 Carnegie Mellon University. * ALL RIGHTS RESERVED. * ********************************************** *  * HISTORY *  * 10-Sep-1998	M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University * 		Changed strcasecmp() call in cmp_name() to strcmp_nocase() call. *  * 15-Jul-1997	M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University * 		Added required arguments handling. *  * 07-Dec-96	M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University * 		Created, based on Eric's implementation.  Basically, combined several *		functions into one, eliminated validation, and simplified the interface. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#if !defined(WIN32)
#include <unistd.h>#endif#include "cmd_ln.h"#include "err.h"#include "ckd_alloc.h"#include "hash.h"#include "case.h"#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>

/* Storage for argument values */typedef struct argval_s {    anytype_t val;    const void *ptr;	/* Needed (with NULL value) in case there is no default */} argval_t;static argval_t *argval = NULL;static hash_table_t *ht;	/* Hash table *//*variables that allow redirecting all files to a log file */static FILE orig_stdout, orig_stderr;static FILE *logfp;#if 0static const char *arg_type2str (argtype_t t){    switch (t) {    case ARG_INT32:    case REQARG_int32:	return ("int32");	break;    case ARG_FLOAT32:    case REQARG_FLOAT32:	return ("float32");	break;    case ARG_FLOAT64:    case REQARG_FLOAT64:	return ("float64");	break;    case ARG_STRING:    case REQARG_STRING:	return ("string");	break;    default: E_FATAL("Unknown argument type: %d\n", t);    }}#endif/* * Find max length of name and default fields in the given defn array. * Return #items in defn array. */static int32 arg_strlen (arg_t *defn, int32 *namelen, int32 *deflen){    int32 i, l;        *namelen = *deflen = 0;    for (i = 0; defn[i].name; i++) {	l = strlen (defn[i].name);	if (*namelen < l)	    *namelen = l;		if (defn[i].deflt) {	    l = strlen (defn[i].deflt);	    if (*deflen < l)		*deflen = l;	}    }    return i;}/* For sorting argument definition list by name */static arg_t *tmp_defn;static int32 cmp_name (const void *a, const void *b){    return (strcmp_nocase (tmp_defn[*((int32 *)a)].name, tmp_defn[*((int32 *)b)].name));}static int32 *arg_sort (arg_t *defn, int32 n){    int32 *pos;    int32 i;        pos = (int32 *) ckd_calloc (n, sizeof(int32));    for (i = 0; i < n; i++)	pos[i] = i;    tmp_defn = defn;    qsort (pos, n, sizeof(int32), cmp_name);    tmp_defn = NULL;    return pos;}static int32 arg_str2val (argval_t *v, argtype_t t, char *str){    if (! str)	v->ptr = NULL;    else {	switch (t) {	case ARG_INT32:	case REQARG_INT32:	  if (sscanf (str, "%d", &(v->val.i_32)) != 1)		return -1;	  v->ptr = (void *) &(v->val.i_32);	    break;	case ARG_FLOAT32:	case REQARG_FLOAT32:	  if (sscanf (str, "%f", &(v->val.fl_32)) != 1)	    return -1;	  v->ptr = (void *) &(v->val.fl_32);	    break;	case ARG_FLOAT64:	case REQARG_FLOAT64:	  if (sscanf (str, "%lf", &(v->val.fl_64)) != 1)	    return -1;	  v->ptr = (void *) &(v->val.fl_64);	    break;	case ARG_STRING:	case REQARG_STRING:	    v->ptr = (void *) str;	    break;	default: E_FATAL("Unknown argument type: %d\n", t);	}    }        return 0;}void cmd_ln_appl_enter(int argc, char *argv[], char* default_argfn, arg_t *defn){  /* Look for default or specified arguments file */  char *str;  int32 i;  char *logfile;  struct stat statbuf;    str = NULL;  if ((argc == 2) && (strcmp (argv[1], "help") == 0)) {    cmd_ln_print_help(stderr, defn);    exit(1);   }  if ((argc == 2) && (argv[1][0] != '-'))    str = argv[1];  else if (argc == 1) {    E_INFO("Looking for default argument file: %s\n",default_argfn);    if(stat(default_argfn,&statbuf)==0){      str=default_argfn;    }else{      E_INFO("Can't find default argument file %s.\n",default_argfn);    }  }  if (str) {    /* Build command line argument list from file */    E_INFO("Parsing command lines from file %s\n",str);    if (cmd_ln_parse_file(defn, str)){      fprintf (stderr, "Usage:\n");      fprintf (stderr, "\t%s argument-list, or\n", argv[0]);      fprintf (stderr, "\t%s [argument-file] (default file: . %s)\n\n",	       argv[0],default_argfn);      cmd_ln_print_help(stderr, defn);      exit(1);    }  }else{    cmd_ln_parse (defn, argc, argv);  }  logfp = NULL;  if ((logfile = (char *)cmd_ln_access("-logfn")) != NULL) {    if ((logfp = fopen(logfile, "w")) == NULL) {      E_ERROR("fopen(%s,w) failed; logging to stdout/stderr\n", logfile);    } else {      /* ARCHAN: Do we still need this hack nowadays? */      orig_stdout = *stdout;	/* Hack!! To avoid hanging problem under Linux */      orig_stderr = *stderr;	/* Hack!! To avoid hanging problem under Linux */      *stdout = *logfp;      *stderr = *logfp;            E_INFO("Command line:\n");      for (i = 0; i < argc; i++) {	if (argv[i][0] == '-')	  printf ("\\\n\t");	printf ("%s ", argv[i]);      }      printf ("\n\n");      fflush (stdout);    }  }  /*   * Repeated in cmd_ln_access()   */  /*  E_INFO("Default configuration (superseded by the above):\n");  cmd_ln_print_help(stderr, defn);  printf ("\n");  fflush(stdout);  */}void cmd_ln_appl_exit(){  if (logfp) {    fclose (logfp);    *stdout = orig_stdout;    *stderr = orig_stderr;  }}static void arg_dump (FILE *fp, arg_t *defn, int32 doc){    int32 *pos;    int32 i, j, l, n;    int32 namelen, deflen;    const void *vp;        /* Find max lengths of name and default value fields, and #entries in defn */    n = arg_strlen (defn, &namelen, &deflen);    namelen = namelen & 0xfffffff8;	/* Previous tab position */    deflen = deflen & 0xfffffff8;	/* Previous tab position */    fprintf (fp, "[NAME]");    for (l = 6; l < namelen; l += 8)	/* strlen("[NAME]") */	fprintf (fp, "\t");    fprintf (fp, "\t[DEFLT]");    for (l = 6; l < deflen; l += 8)	/* strlen("[DEFLT]") */	fprintf (fp, "\t");    if(doc){      fprintf (fp, "\t[DESCR]\n");    }else{      fprintf (fp, "\t[VALUE]\n");    }        /* Print current configuration, sorted by name */    pos = arg_sort (defn, n);    for (i = 0; i < n; i++) {	j = pos[i];		fprintf (fp, "%s", defn[j].name);	for (l = strlen(defn[j].name); l < namelen; l += 8)	    fprintf (fp, "\t");	fprintf (fp, "\t");	if (defn[j].deflt) {	    fprintf (fp, "%s", defn[j].deflt);	    l = strlen (defn[j].deflt);	} else	    l = 0;	for (; l < deflen; l += 8)	    fprintf (fp, "\t");		fprintf (fp, "\t");	if (doc) {	    if (defn[j].doc)		fprintf (fp, "%s", defn[j].doc);	} else {	    vp = cmd_ln_access (defn[j].name);	    if (vp) {		switch (defn[j].type) {		case ARG_INT32:		case REQARG_INT32:		    fprintf (fp, "%d", *((int32 *) vp));		    break;		case ARG_FLOAT32:		case REQARG_FLOAT32:		    fprintf (fp, "%e", *((float32 *) vp));		    break;		case ARG_FLOAT64:		case REQARG_FLOAT64:		    fprintf (fp, "%e", *((float64 *) vp));		    break;		case ARG_STRING:		case REQARG_STRING:		    fprintf (fp, "%s", (char *)vp);		    break;		default: E_FATAL("Unknown argument type: %d\n", defn[j].type);		}	    }	}		fprintf (fp, "\n");    }    ckd_free (pos);        fprintf (fp, "\n");    fflush (fp);}int32 cmd_ln_parse (arg_t *defn, int32 argc, char *argv[]){    int32 i, j, n;        if (argval)	E_FATAL("Multiple sets of argument definitions not supported\n");        /* Echo command line */    E_INFO("Parsing command line:\n");    for (i = 0; i < argc; i++) {	if (argv[i][0] == '-')	    fprintf (stderr, "\\\n\t");	fprintf (stderr, "%s ", argv[i]);    }    fprintf (stderr, "\n\n");    fflush (stderr);        /* Find number of argument names in definition */    for (n = 0; defn[n].name; n++);        /* Allocate memory for argument values */    ht = hash_new (n, 0 /* argument names are case-sensitive */);    argval = (argval_t *) ckd_calloc (n, sizeof(argval_t));        /* Enter argument names into hash table */    for (i = 0; i < n; i++) {	/* Associate argument name with index i */	if (hash_enter (ht, defn[i].name, i) != i)	    E_FATAL("Duplicate argument name: %s\n", defn[i].name);    }        /* Parse command line arguments (name-value pairs); skip argv[0] if argc is odd */    for (j = 1; j < argc; j += 2) {	if (hash_lookup(ht, argv[j], &i) < 0) {	    cmd_ln_print_help (stderr, defn);	    E_FATAL("Unknown argument: %s\n", argv[j]);	}		/* Check if argument has already been parsed before */	if (argval[i].ptr)	    E_FATAL("Multiple occurrences of argument %s\n", argv[j]);		if (j+1 >= argc) {	    cmd_ln_print_help (stderr, defn);	    E_FATAL("Argument value for '%s' missing\n", argv[j]);	}		/* Enter argument value */	if (arg_str2val (argval+i, defn[i].type, argv[j+1]) < 0) {	    cmd_ln_print_help (stderr, defn);	    E_FATAL("Bad argument value for %s: %s\n", argv[j], argv[j+1]);	}	assert (argval[i].ptr);    }        /* Fill in default values, if any, for unspecified arguments */    for (i = 0; i < n; i++) {      if (! argval[i].ptr) {	if (arg_str2val (argval+i, defn[i].type, defn[i].deflt) < 0)	  E_FATAL("Bad default argument value for %s: %s\n",		  defn[i].name, defn[i].deflt);      }    }        /* Check for required arguments; exit if any missing */    j = 0;    for (i = 0; i < n; i++) {	if ((defn[i].type & ARG_REQUIRED) && (! argval[i].ptr)) {	    E_ERROR("Missing required argument %s\n", defn[i].name);	    j++;	}    }    if (j > 0) {	cmd_ln_print_help (stderr, defn);	exit(-1);    }    if (argc == 1){	cmd_ln_print_help (stderr, defn);	exit(-1);    }    /* Print configuration */    fprintf (stderr, "Current configuration:\n");    arg_dump (stderr, defn, 0);        return 0;}int32 cmd_ln_parse_file(arg_t *defn, char *filename){  FILE *file;  char **tmp_argv;  char **argv;  int argc;  int argv_size;  char str[ARG_MAX_LENGTH];  int len = 0;  int ch;  int rv = 0;  if ((file = fopen(filename, "r")) == NULL) {    return -1;  }  /*   * initialize default argv, argc, and argv_size.  note that argv[0] is set to   * a null-string.  basically we don't care about argv[0].  typically, that is   * set as invoked program name.   */  argv_size = 10;  argc = 1;  argv = ckd_calloc(argv_size, sizeof(char *));  argv[0] = ckd_calloc(1, sizeof(char *));  argv[0][0] = '\0';  do {    ch = fgetc(file);    if (ch == EOF || strchr(" \t\r\n", ch)) {      /* reallocate argv so it is big enough to contain all the arguments */      if (argc >= argv_size) {	if (!(tmp_argv = ckd_calloc(argv_size * 2, sizeof(char *)))) {	  rv = 1;	  break;	}	memcpy(tmp_argv, argv, argv_size * sizeof(char *));	ckd_free(argv);	argv = tmp_argv;	argv_size *= 2;      }      /* add the string to the list of arguments */      argv[argc] = ckd_calloc(len + 1, sizeof(char));      strncpy(argv[argc], str, len);      argv[argc][len] = '\0';      len = 0;      argc++;      for (; ch != EOF && strchr(" \t\r\n", ch); ch = fgetc(file));      if (ch != EOF) {	str[len++] = ch;      }    }    else if (len < ARG_MAX_LENGTH) {      /* add the char to the argument string */      str[len++] = ch;    }    else {      /* hmmm, we've had an argument that exceeded ARG_MAX_LENGTH */      rv = 1;      break;    }  } while (ch != EOF);    if (rv == 0) {    rv = cmd_ln_parse(defn, argc, argv);  }  ckd_free(argv);  return rv;}void cmd_ln_print_help (FILE *fp, arg_t *defn){    fprintf (fp, "Arguments list definition:\n");    arg_dump (fp, defn, 1);}const void *cmd_ln_access (char *name){    int32 i;        if (! argval)	E_FATAL("cmd_ln_access invoked before cmd_ln_parse\n");        if (hash_lookup (ht, name, &i) < 0)	E_FATAL("Unknown argument: %s\n", name);        return (argval[i].ptr);}/* RAH, 4.17.01, free memory allocated above  */void cmd_ln_free (){  hash_free (ht);  ht=NULL;  ckd_free ((void *) argval);  argval = NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -