📄 opt.c
字号:
ARGVECTOR *ag;{ extern double atof(); return( atof(argnext(ag)) );}/* opt_reg.c *//************************ register options ******************************** * * options are stored in an array, * each element of which is a structure * * The members of the structure contain information about * 1) the variable which is altered * 2) the type of variable * 3) a character by which the variable is invoked * 4) a brief description of the variable's role in the program * 5) a longer help message * * The structure elements are not assigned directly, but are * "registered" with a call to the function opt_register(). * * In this file are the routines which access the structure of * registered options. * * I) Register options and help strings * II) Get number corresponding to name of option * III) Print options out * a) to a file which can be used as an input command line * b) to the screen as part of a usage message * c) to the screen as part of an interactive menu * IV) Process single delimited and undelimited options */#ifndef SINGLEFILE#include <stdio.h>#ifdef convex#include <strings.h>#else#include <string.h>#endif#ifdef __TURBOC__#include <alloc.h>#endif#include "ag.h"#include "opt_p.h"static char gstr[160]; /* global string for general use */#endif /* -------------------------- */ /* List of Registered Options */ /* -------------------------- */#define MAXOPTS 62 /* one for each upper and lower case letter */typedef struct { char *value; /* pointer to value of option */ opt_TYPE type; /* will be cast according to type */ char name; /* name by which option is invoked */ char *brief; /* a brief description */ char *help; /* longer help message */ } EACH_OPT;static EACH_OPT optlist[MAXOPTS]; /* array of options */int nregopts=0; /* number of registered opts */ /* ---------- */ /* OPT macros */ /* ---------- */#define OPT_isflagtype(o) \ ((o)==FLAG || (o)==NEGFLAG || (o)==ABSFLAG || (o)==ABSNEGFLAG)#define OPT_isundelimtype(o) ((o)==UNDELIMV || (o)==UNDELIMC) /* ----------------------------------------------- */ /* OPTVALUE: a macro to get the value of an option */ /* ----------------------------------------------- */#define OPTVALUE(typ,i) ((typ)(*((typ *)(optlist[i].value))))#define SETOPTVALUE(typ,i,val) { typ *xptr; \ xptr = (typ *)(optlist[i].value); \ *xptr = val; \ } /* ------------------------------- */ /* Routine to register each option */ /* ------------------------------- */intopt_register(val,otype,name,brief)char *val;opt_TYPE otype;char name;char *brief;{ if( nregopts >= MAXOPTS ) opt_fatal("opt_register: too many options"); if( name != '\0' && opt_number(name) != -1 ) { char gstr[80]; sprintf(gstr,"opt_register: Duplicate option name \'%c\'",name), opt_warning(gstr); } /* Programmer may specify that an option is to be an * undelimted option by setting the name to '\0' */ if(name=='\0') { if(otype==VSTRING) otype=UNDELIMV; if(otype==CSTRING) otype=UNDELIMC; } /* Having checked for various warnings, now register the options */ optlist[nregopts].value = val; optlist[nregopts].type = otype; optlist[nregopts].name = name; optlist[nregopts].brief = brief; optlist[nregopts].help = NULL; /* UN-delimited strings are set to NULL when registered */ /* This enables them to be invoked on the command line */ if(otype==UNDELIMC) *(optlist[nregopts].value)='\0'; if(otype==UNDELIMV) SETOPTVALUE(char *,nregopts,NULL) ++nregopts; return(nregopts);}voidopt_help_set(c,help)char c, *help;{ int n; n = opt_number(c); if (n>=0 && n<nregopts) optlist[n].help = help; else sprintf(gstr,"opt_help_set: Unregistered option name \'%c\'",c), opt_warning(gstr);}voidopt_get_help(c)char c;{ int n; n = opt_number(c); if (n>=0 && n<nregopts && optlist[n].help != NULL) sprintf(gstr,"%c: %s\n",c,optlist[n].help), opt_message(gstr); else sprintf(gstr,"Help unavailable for \'%c\'\n",c), opt_message(gstr);} /* --------------------------------------- */ /* Get number corresponding to option name */ /* --------------------------------------- *//* opt_number returns the number of a named option. * if c=='\0', signifying an undelimited option, * then the number of the FIRST undelimited option is returned */intopt_number(c)char c;{ int i=0; /* see which registered option */ for(i=0; i<nregopts; ++i) { if( c == optlist[i].name ) return(i); } return(-1); /* to signify not an option */} /* -------------------------------------------- */ /* Print value of registered option to a string */ /* -------------------------------------------- *//* optstrval: * returns the value of the ith registered option as a string * Thus if x = 12.6, this returns the string "12.6" * The return value is a pointer to a static string which is * overwritten with each call * FLAG values are returned as "+" or "-" * INTLEVEL values are returned as "- -xxxx..." depending on value */char *optstrval(i)int i;{ int maybe; static char stval_buf[80]; switch( optlist[i].type ) { case INT: sprintf(stval_buf,"%d", OPTVALUE(int,i) ); break; case UNSINT: sprintf(stval_buf,"%u", OPTVALUE(unsigned int,i) ); break; case LONG: sprintf(stval_buf,"%ld", OPTVALUE(long,i) ); break; case FLOAT: sprintf(stval_buf,"%g", OPTVALUE(float,i) ); break; case DOUBLE: sprintf(stval_buf,"%lg", OPTVALUE(double,i) ); break; case CHAR: sprintf(stval_buf,"%c", OPTVALUE(char,i)); break; case INTLEVEL: { int j; char buff[80]; strcpy(stval_buf,"-"); /* Begin with level==OFF */ for(j=0; j< OPTVALUE(int,i); ++j) { sprintf(buff,(j==0?" -%c":"%c"),optlist[i].name); strcat(stval_buf,buff); } } break; case FLAG: case ABSFLAG: maybe = OPTVALUE(int,i); sprintf(stval_buf,"%c", (maybe==TRUE ? '+' : '-') ); break; case NEGFLAG: case ABSNEGFLAG: maybe = OPTVALUE(int,i); sprintf(stval_buf,"%c", (maybe==TRUE ? '-' : '+') ); break; case CSTRING: case UNDELIMC: sprintf(stval_buf,"\"%s\"",optlist[i].value); break; case VSTRING: case UNDELIMV: if( optlist[i].value == NULL ) /* this should never happen */ sprintf(stval_buf,"\"\""); else if( OPTVALUE(char *,i) == NULL ) sprintf(stval_buf,"\"\""); else sprintf(stval_buf,"\"%s\"",OPTVALUE(char *,i)); break; default: opt_fatal("optstrval: Undefined o-type"); break; } /* ---- Return value is static buffer ---- */ return(stval_buf);}/*optstrval*//* optstrtyp: * returns the type of the ith registered option as a string * Thus if x = 12.6 is a float , this returns the string "<real>" * The return value is a pointer to a static string which is * overwritten with each call */char *optstrtyp(i)int i;{ static char sttyp_buf[80]; switch( optlist[i].type ) { case INT: case UNSINT: case LONG: strcpy(sttyp_buf,"<integer>"); break; case FLOAT: case DOUBLE: strcpy(sttyp_buf,"<real>"); break; case CHAR: strcpy(sttyp_buf,"<character>"); break; case INTLEVEL: case FLAG: case NEGFLAG: case ABSFLAG: case ABSNEGFLAG: strcpy(sttyp_buf,"<flag>"); break; case VSTRING: case CSTRING: case UNDELIMV: case UNDELIMC: strcpy(sttyp_buf,"<string>"); break; default: opt_fatal("usage: undefined o-type"); } return(sttyp_buf);} /* ------------------------------ */ /* Put registered options to file */ /* ------------------------------ */intopt_tofile(fp)FILE *fp;{ int i; char *format; char *fnumstr="-%c %-38s %c%s\n"; /* numbers and strings */ char *fflgchr="-%c%-38s %c%s\n"; /* flags and characters */ void opt_fileheader(); opt_fileheader(fp); for(i=0; i<nregopts; ++i) { if( OPT_isundelimtype( optlist[i].type ) ) continue; if( OPT_isflagtype( optlist[i].type ) || optlist[i].type == INTLEVEL || optlist[i].type == CHAR ) format = fflgchr; else format = fnumstr; fprintf(fp,format,optlist[i].name, optstrval(i),IGNOREEOL,optlist[i].brief); }}voidopt_fileheader(fp)FILE *fp;{ extern char *opt_program_name; int i,n; char buf[80]; sprintf(buf,"Options file created by: [%.30s]",opt_program_name); n = strlen(buf); fputc(IGNOREEOL,fp); fprintf(fp,"%s",buf); fputc(IGNOREEOL,fp); fputc('\n',fp); fputc(IGNOREEOL,fp); for(i=0;i<n;++i) fprintf(fp,"-"); fputc(IGNOREEOL,fp); fputc('\n',fp);} /* ----------------------------------------- */ /* write options out to the interactive menu */ /* ----------------------------------------- */char *opt_mstring(i)int i;{ static char mstring[180]; char flgstr[10]; char *s; char *optstrval(); char *format = "%c %-40s %s"; if( OPT_isundelimtype( optlist[i].type ) ) return(NULL); s = optstrval(i); if( optlist[i].type == INTLEVEL ) { int f; f = OPTVALUE(int,i); if(f==0) strcpy(flgstr,"OFF"); else if (f==1) strcpy(flgstr,"ON"); else sprintf(flgstr,"ON:%d",f); s=flgstr; } else if( optlist[i].type == CHAR ) { switch (s[0]) { case '\0': sprintf(flgstr,"\'\\0\'"); break; case '\n': sprintf(flgstr,"\'\\n\'"); break; case '\t': sprintf(flgstr,"\'\\t\'"); break; case ' ': sprintf(flgstr,"\' \'"); break; default: sprintf(flgstr,"%c",s[0]); break; } s = flgstr; } else if( OPT_isflagtype( optlist[i].type ) ) { if( *s == '+' ) strcpy(flgstr,"TRUE"); if( *s == '-' ) strcpy(flgstr,"FALSE"); s=flgstr; } sprintf(mstring,format,optlist[i].name,optlist[i].brief,s); return(mstring);}intopt_fprint(fp,i)FILE *fp;int i;{ char *optstrval(); fprintf(fp,"-%c%-17s %c%s\n",optlist[i].name, optstrval(i),IGNOREEOL,optlist[i].brief); return(i);} /* ----------------------------------------------------- */ /* write a usage statement describing registered options */ /* ----------------------------------------------------- */voidopt_usage(){ char buf[100]; char *dformat = " -%c %-12s\t%s\n"; char *uformat = " %-12s\t%s\n"; int i; for(i=0; i<nregopts; ++i) { if( OPT_isundelimtype( optlist[i].type ) ) { sprintf(buf,uformat, optstrtyp(i),optlist[i].brief); opt_message(buf); } else { sprintf(buf,dformat,optlist[i].name, optstrtyp(i),optlist[i].brief); opt_message(buf); } }} /* ----------------------- */ /* Get and process options */ /* ----------------------- */ /* * The routines below make use of the ARGVECTOR structure * defined in "ag.h" to process the command line options */ /* -------------------------------------- */ /* get and process an UN-delimited option */ /* -------------------------------------- */intopt_undelim(ag)ARGVECTOR *ag;{ int i; char *s; if(1) { /* This is the hook that the programmer can install * to filter undelimited strings from the command line */ extern PFI ufilter_fcn; if( ufilter_fcn != NULL ) if( (*ufilter_fcn)(ag_s(ag),ag) != 0 ) return(1); } if(DEBUG) { opt_message("opt_udelim: "); ag_fprint(ag); } /* Find the first un-initialized undelimited option */ /* and set that to the argument string */ /* Note that once an undelimited option has been initialized */ /* it cannot be reset to a new value unless it is somehow */ /* set back to NULL or blank */ s = ag_s_advance(ag); for(i=0; i<nregopts; ++i) { if( optlist[i].type==UNDELIMC && *(optlist[i].value)=='\0' ) { strcpy( optlist[i].value, s ); return(1); } if( optlist[i].type==UNDELIMV && OPTVALUE(char *,i)==NULL ) { SETOPTVALUE(char *,i,(char *)malloc(strlen(s)+1)); strcpy( OPTVALUE(char *,i), s );/* ?? */ return(1); } } return(0);} /* ---------------------------------- */ /* get and process a delimited option */ /* ---------------------------------- */opt_delim(ag)ARGVECTOR *ag;{ int i; opt_TYPE o; char c; char *s; int yes,no,maybe,toggle; /* flag values */ /************************************************** * first, check to see if the programmer wants to * interrupt this delimited option: if so, it will * be done by the routine (*dfilter_fcn)(), which * the programmer has provided and a * nonzero value will be returned. ***************************************************/ if(1) { extern PFI dfilter_fcn; if( dfilter_fcn != NULL ) if( (*dfilter_fcn)(ag_s(ag),ag) != 0 ) return(1); } c = ag_c_advance(ag); /* first character gives name of option */ i = opt_number(c); /* this is number of option w/ name 'c' */ if(i<0) /* if invalid option name */ { char s[80]; sprintf(s,"%c not a registered option name\n",c); opt_warning(s); return(0); } /* ------------- */ /* act on option */ /* ------------- */ switch( o=optlist[i].type ) { case INT: SETOPTVALUE(int,i, argnextnum(ag)); break; case UNSINT: SETOPTVALUE(unsigned int,i, argnextnum(ag)); break; case LONG: SETOPTVALUE(long,i, argnextnum(ag)); break; case FLOAT: SETOPTVALUE(float,i, argnextnum(ag)); break; case DOUBLE: SETOPTVALUE(double,i, argnextnum(ag)); break; case CHAR: SETOPTVALUE(char,i, ag_c_advance(ag)); break; case FLAG: case NEGFLAG: case ABSFLAG: case ABSNEGFLAG: /* define terms: * yes: value of flag when ON * no: value of flag when OFF * maybe: present value of flag * toggle: negative of maybe */ maybe = OPTVALUE(int,i); toggle = (maybe==TRUE ? FALSE : TRUE); if( o==FLAG || o==ABSFLAG ) yes=TRUE; else yes=FALSE; no = (yes==TRUE ? FALSE : TRUE); c = ag_c(ag); /* character following 'c' */ switch(c) { case '+': *((int *)(optlist[i].value)) = yes; ag_c_advance(ag); /* eat the '+' */ break; case '-': *((int *)(optlist[i].value)) = no; ag_c_advance(ag); /* eat the '-' */ break; default: if( o==ABSFLAG || o==ABSNEGFLAG ) *((int *)(optlist[i].value)) = maybe; else /* otherwise toggle value */ *((int *)(optlist[i].value)) = toggle; break; } break; case INTLEVEL: SETOPTVALUE(int,i,OPTVALUE(int,i) + 1); /* default is to increment */ c = ag_c(ag); switch(c) { case '+': /* we've already incremented */ ag_c_advance(ag); break; case '-': SETOPTVALUE(int,i,0); ag_c_advance(ag); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': SETOPTVALUE(int,i,c-'0'); ag_c_advance(ag); default: break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -