home *** CD-ROM | disk | FTP | other *** search
- /* ParseARGUment . C
- #
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- This software is copyright (C) by the Lawrence Berkeley Laboratory.
- Permission is granted to reproduce this software for non-commercial
- purposes provided that this notice is left intact.
-
- It is acknowledged that the U.S. Government has rights to this software
- under Contract DE-AC03-765F00098 between the U.S. Department of Energy
- and the University of California.
-
- This software is provided as a professional and academic contribution
- for joint exchange. Thus, it is experimental, and is provided ``as is'',
- with no warranties of any kind whatsoever, no support, no promise of
- updates, or printed documentation. By using this software, you
- acknowledge that the Lawrence Berkeley Laboratory and Regents of the
- University of California shall have no liability with respect to the
- infringement of other copyrights by any part of this software.
-
- For further information about this notice, contact William Johnston,
- Bld. 50B, Rm. 2239, Lawrence Berkeley Laboratory, Berkeley, CA, 94720.
- (wejohnston@lbl.gov)
-
- For further information about this software, contact:
- Jin Guojun
- Bld. 50B, Rm. 2275, Lawrence Berkeley Laboratory, Berkeley, CA, 94720.
- g_jin@lbl.gov
-
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %
- % Restrictions:
- % <1> with extension mode:
- % (1) only one variable can be passed
- % (2) format string can not be reused
- % <2> For fast processing:
- % If same flag is given more than once, only the first one
- % is used, and no warning will be given.
- %
- % Author: Jin Guojun - LBL 10/01/92
- */
-
- #ifndef TC_Need
- # include <varargs.h>
- #endif
- #include <ctype.h>
- #include <math.h>
- #include <string.h>
- #include "stdef.h"
-
- #ifndef msg
- #define msg(f, s) fprintf(stderr, f, s)
- #define mesg( s ) fprintf(stderr, s)
- #endif
-
- #define SIZEOF (MType)sizeof
-
- #ifdef USE_STRING_ARGU_DEF
- #define USAD
- #endif
- #define isARGU_B(a) (a<ARGU_BOOL || a>=ARGU_BORDEF)
-
- static int use_pounds;
-
- void
- p_use_pound_sign(bool y_or_n)
- {
- use_pounds = y_or_n;
- }
-
- void
- free_arg_fmt_list(int num_list, register arg_fmt_lists* fmt_list)
- {
- register int i, n;
- for (n=num_list; n--; fmt_list++) {
- i = fmt_list->extended_flags;
- while (i--)
- free(fmt_list->extend[i].v),
- free(fmt_list->extend[i].fls);
- if (fmt_list->extended_flags)
- free(fmt_list->extend);
- free(fmt_list->v);
- }
- free(fmt_list - num_list);
- }
-
- arg_fmt_lists*
- build_arg_fmt_list(int *retn, arg_fmt_list_string* fmt, va_list ap)
- {
- int tBE, na=1;
- register int n, ne;
- register arg_fmt_lists* aflp;
- char *cp, *cpr, *fmtp;
- #define nv ne
-
- while ((++fmt)->flag) na++;
- if (retn) *retn = na;
- aflp = ZALLOC((MType)na, SIZEOF(*aflp), "arg_fmt_list");
-
- for (fmt-=na, n=0; n<na; fmt++, n++) {
- aflp[n].fls = fmt;
- cp = fmt->flag;
- fmtp = fmt->in_fmt;
- aflp[n].v = ZALLOC((MType)(tBE=fmt->num_vars), SIZEOF(convs), "aconvs");
- for (nv=aflp[n].ext_level=0; nv < tBE; nv++)
- aflp[n].u_l_s = find_input_type(&fmtp, fmt->def_val,
- nv < fmt->min_inps, aflp[n].v+nv, &ap);
- if (nv) { /* if not comment, build extensions */
- tBE = isARGU_B(aflp[n].v->type);
- while (cpr = strchr(cp, '[')) {
- register arg_fmt_lists* eaflp;
- *cpr = NULL;
- cp = ++cpr;
- ne = aflp[n].extended_flags++;
- verify_buffer_size(&aflp[n].extend, -ne-1, SIZEOF(*eaflp), "exaflp");
- eaflp = aflp[n].extend + ne;
- eaflp->ext_level = ++ne;
- eaflp->extended_flags = 0;
- eaflp->fls = ZALLOC(1L, SIZEOF(*eaflp->fls), "efls");
- eaflp->fls->flag = cp;
- if (!(cpr = strchr(cp, ']'))) return (arg_fmt_lists*)
- prgmerr(-1, "extension not match %s", cp);
- *cpr = NULL;
- eaflp->flag_len = *cp == '#' ? 0 : strlen(cp);
- cp = ++cpr;
- eaflp->v = ZALLOC(1L + tBE, SIZEOF(convs), "econvs");
- eaflp->fls->num_vars = 1 + tBE;
- eaflp->u_l_s = find_input_type(&fmtp, eaflp->fls->def_val =
- aflp[n].fls->def_val, No, eaflp->v + tBE, &ap);
- if (tBE) *eaflp->v = *aflp[n].v;
- }
- }
- ne = strlen(fmt->flag);
- aflp[n].flag_len = ne - (fmt->flag[ne-1] == '#');/* for -# */
- }
- return aflp;
- }
-
-
- /* return 0 for OK; otherwise for unknown type */
- find_input_type(fmtp, dvsp, setv, v, ap)
- register char** fmtp;
- #ifdef USAD
- char*
- #else
- float
- #endif
- dvsp;
- bool setv;
- convs *v;
- va_list *ap;
- {
- static argu_type last_arg_t=ARGU_NONE;
- argu_type arg_t, et;
- register float dv =
- #ifdef USAD
- atof
- #endif
- (dvsp);
-
- while (**fmtp && *(*fmtp)++ != '%');
- v->p.v_p = va_arg(*ap, void*);
-
- et = (*fmtp)[1];
- switch (arg_t = **fmtp) {
- case 'c': if (setv) *v->p.c_p = dv; break;
- case 'd': arg_t = ARGU_INT; goto long_set;
- case 'X': arg_t = ARGU_HEX;
- case 'x':
- case 's':
- case '-': case '+':if (et==ARGU_SHORT) goto sht_set;
- long_set:
- case 'i': if (setv) *v->p.i_p = dv; break;
- case 'S': arg_t = ARGU_SHORT;
- sht_set:
- case 'h': if (setv) *v->p.s_p = dv; break;
- case 'f': if (setv) *v->p.f_p = dv; break;
- case 'D': arg_t = ARGU_DOUBLE;
- case 'g': if (setv) *v->p.d_p = dv; break;
- case '%': arg_t = ARGU_ADDPARAM; /* flag = "?-*" */
- case 'N': case 'E': case 'B': case 'b': case '*':
- case '&': case '|': case '^':
- case '#': case '!': case '~': break;
- default:if (isdigit(**fmtp))
- arg_t = (argu_type) atoi(*fmtp);
- else arg_t = last_arg_t;
- }
- while (*(++*fmtp) && **fmtp != '%');
- v->type = last_arg_t = arg_t;
- return arg_t==ARGU_NONE ? arg_t : et; /* extended integer type */
- }
-
- get_args(int nflags, arg_fmt_lists* fmt_list,
- int argc, char* *argv, int *n, int f)
- {
- int dbl_arg, e, noarg = ARGU_NONE;
- char *val;
- float scale; /* make things a little bit slower, but may be useful */
-
- #define NUMber() NS_TSET(n, &f, 0)
- #define NextArg() NS_TSET(n, &f, 1)
-
- while (nflags--) {
- register arg_fmt_lists* aflp = fmt_list+nflags;
- register int cmn = aflp->flag_len, nvs = argv[*n][f+cmn];
- if (cmn) {
- if (strncmp(argv[*n] + f, aflp->fls->flag, cmn) ||
- ((e=aflp->extended_flags) && nvs && /* extension */
- ((noarg=get_args(e, aflp->extend, argc, argv, n, cmn)) >= 0) ||
- /* "-#" */ cmn==1 && *aflp->fls->flag=='-' && !isfloat(nvs)))
- continue; /* maybe faster than return 0; */
- f += cmn;
- }
-
- e =
- #ifdef USAD
- atoi
- #endif
- (aflp->fls->def_val);
-
- cmn = aflp->v->type;
- dbl_arg = isARGU_B(cmn);
- if (cmn < ARGU_BNEG)
- *aflp->v->p.a_p = cmn;
-
- #define advf f = strlen(argv[*n])
- #define vp aflp->v->p
- #define doSHORT if (aflp->u_l_s==ARGU_SHORT)
- scale = 0;
- switch (cmn) { /* process ARGU_Bxxxx */
- case ARGU_BDEF: doSHORT *vp.s_p = e;
- else *vp.i_p = e; break;
- case ARGU_BANDEF: doSHORT *vp.s_p &= e;
- else *vp.i_p &= e; break;
- case ARGU_BORDEF: doSHORT *vp.s_p |= e;
- else *vp.i_p |= e; break;
- case ARGU_BXORDEF: doSHORT *vp.s_p ^= e;
- else *vp.i_p ^= e; break;
- case ARGU_BEXTYPE:
- if (cmn=aflp->ext_level) {
- val = aflp->fls->in_fmt;
- while (cmn--) while (*val && *++val == '%');
- *vp.i_p = *val;
- }
- break;
- case ARGU_BEXT:
- if (aflp->ext_level)
- *vp.i_p = *aflp->fls->flag;
- break;
- case ARGU_BNUM:
- case ARGU_BNEGI:
- *vp.b_p = NUMber();
- if (cmn == ARGU_BNEGI)
- case ARGU_BNEG: *vp.b_p = !*vp.b_p;
- break;
- case ARGU_BPLUS:
- ++*vp.b_p; break;
- case ARGU_BMINUS:
- --*vp.b_p; break;
- case ARGU_SCALE: scale = *vp.f_p;
- }
-
- if (dbl_arg < aflp->fls->num_vars) /* safety checking */
- switch (aflp->v[dbl_arg].type) { /* for input argus */
- case ARGU_BOOL:
- *aflp->v[dbl_arg].p.b_p =
- #ifdef USAD
- strcmp(aflp->fls->def_val, "False") != 0;
- #else
- aflp->fls->def_val;
- #endif
- break;
- case ARGU_ADDPARAM:
- case ARGU_STRING:
- cmn = aflp->v[dbl_arg].type == ARGU_ADDPARAM;
- for (nvs=dbl_arg; nvs < aflp->fls->num_vars; nvs++) {
- #ifndef TC_Need
- register /* Turbo C bug: cant handle single word union. */
- #endif
- convs_p sp = aflp->v[nvs].p;
- if (cmn) /* add paramter flag; no argus control */
- strcat(sp.c_p, argv[*n] + 1),
- strcat(sp.c_p, " "), advf;
-
- if (!NextArg()) return f; /* end of argv list */
-
- if (!cmn)
- *sp.stp = argv[*n] + f; /* == *vp.i_p; but != *vp.c_p */
- else strcat(sp.c_p, argv[*n]), /* add paramter element */
- strcat(sp.c_p, " ");
- advf;
- } break;
- default:
- if (!aflp->fls->sscan)
- for (nvs=dbl_arg; nvs < aflp->fls->num_vars; nvs++) {
- double vd;
- if (!NUMber())
- if ((e = nvs-aflp->fls->min_inps) < dbl_arg) {
- if (isdigit(*argv[*n])) NextArg();
- return e-1;
- } else {
- #ifdef USAD
- val = aflp->fls->def_val;
- #else
- val = NULL;
- vd = aflp->fls->def_val;
- #endif
- }
- else val = argv[*n] + f, advf; /* fast process */
-
- if (val) vd = atof(val);
- if (scale) vd *= scale;
- e = vd;
-
- switch (aflp->v[nvs].type) {
- case ARGU_HEX: if (val) {
- sscanf(val, "%x", aflp->v[nvs].p.i_p); break;
- }
- case ARGU_INT: *aflp->v[nvs].p.i_p = e; break;
- case ARGU_SHORT:*aflp->v[nvs].p.s_p = e; break;
- case ARGU_FLOAT:*aflp->v[nvs].p.f_p = vd; break;
- case ARGU_DOUBLE:*aflp->v[nvs].p.d_p = vd; break;
- default:
- if (nvs+1 < aflp->fls->min_inps) return EOF;
- }
- } else if (NUMber()) {
- void *tempp[8]; /* max = 8 vars */
- for (nvs = MIN(8, aflp->fls->num_vars); nvs-->=dbl_arg;)
- tempp[nvs-dbl_arg] = aflp->v[nvs].p.v_p;
- sscanf(argv[*n] + f, aflp->fls->in_fmt + (dbl_arg << 1),
- tempp[0], tempp[1],
- tempp[2], tempp[3], tempp[4],
- tempp[5], tempp[6], tempp[7]);
- advf;
- }
- }
- NextArg();
- /* noarg = abs(noarg) - *n; if (noarg) noarg = *n; */
- noarg = f;
- if (aflp->ext_level && !aflp->extended_flags) break;
- }
- return noarg;
- }
-
-
- /* Independent session. If can be in another file */
- parserr(arg_fmt_lists* fmt, int items, int vless, int argerr, char** argv)
- {
- int i;
- register char* flagp=argv[argerr];
-
- if (vless=abs(vless)-1)
- prgmerr(0, "option %s less %d argu\n", flagp, vless);
- else prgmerr(0, "wrong option [%d] %s\n", argerr, flagp);
-
- for (;items-- && *(flagp=fmt[items].fls->flag);)
- if (fmt[items].fls->num_vars) /* don't change comments */
- /* recover the extensions */
- for (i=fmt[items].extended_flags; i--;) {
- while(*++flagp); *flagp = '[';
- while(*++flagp); *flagp = ']';
- }
- parse_usage(fmt->fls);
- }
-
- parse_usage(register arg_fmt_list_string* fmt) /* public entry */
- {
- int i, tBE;
- char msgfmt[128];
- register char* flagp;
-
- for (; flagp=fmt->flag; fmt++) {
- msg("%s", fmt->flag);
- if (flagp=fmt->in_fmt)
- for (i=0, tBE=isARGU_B(flagp[1]); i<fmt->num_vars || *++flagp; i++) {
- register char *finfo, c;
- while (*flagp && *flagp++ != '%');
- c = *flagp;
- if (use_pounds && c > ARGU_CHAR && c < ARGU_STRING)
- finfo = "#";
- else switch (c) {
- default:while (flagp[1] && flagp[1] != Space) flagp++;
- if (fmt->num_vars > 1)
- finfo = "";
- else
- case 'b': finfo = "\t"; break;
- case 'd': case 'i': finfo = "INTEGER"; break;
- case 'f': finfo = "FLOAT"; break;
- case 'g': case 'D': finfo = "DOUBLE"; break;
- case 'h': finfo = "SHORT"; break;
- case 'c': case 's': finfo = "STRING"; break;
- case 'X': case 'x': finfo = "Hex"; break;
- }
- msg(i-tBE<fmt->min_inps || *finfo=='\t'? " %s" : " [%s]", finfo);
- }
- if (flagp=fmt->info) {
- while (iscntrl(*flagp)) msg("%c", *flagp++);
- if (strlen(flagp) > sizeof(msgfmt) - 8)
- msg("\t{ %s }\n", flagp);
- else sprintf(msgfmt, "\t{ %s }\n", flagp),
- msg(msgfmt, fmt->def_val);
- } else mesg("\t{ < ? > }\n");
- }
- }
-
- parse_argus( /* public entry */
- char** flistp[],
- int argc,
- char** argv,
- arg_fmt_list_string* fmt,
- va_list va_alist )
- {
- int i, nf=0, nvars, v;
- arg_fmt_lists* fmt_list = build_arg_fmt_list(&nvars, fmt, (va_list)&va_alist);
-
- if (flistp) *flistp = NULL;
-
- for (i=0; ++i < argc;) {
- retry: v = get_args(nvars, fmt_list, argc, argv, &i, 0);
- if (v > 0 && !argv[i][v])
- continue;
- else if (*argv[i] != '-' && flistp) { /* add_file_list */
- verify_buffer_size(flistp, -SIZEOF(int), nf+1, "nf");
- (*flistp)[nf++] = argv[i];
- } else if (v < 0) {
- nf = -i;
- parserr(fmt_list, nvars, v, i, argv);
- break;
- } else if (!v) goto retry; /* fast process result */
- }
- free_arg_fmt_list(nvars, fmt_list);
- return nf;
- }
-