home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / lib / parsargu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-15  |  11.6 KB  |  434 lines

  1. /*    ParseARGUment . C
  2. #
  3. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  4.  
  5. This software is copyright (C) by the Lawrence Berkeley Laboratory.
  6. Permission is granted to reproduce this software for non-commercial
  7. purposes provided that this notice is left intact.
  8.  
  9. It is acknowledged that the U.S. Government has rights to this software
  10. under Contract DE-AC03-765F00098 between the U.S.  Department of Energy
  11. and the University of California.
  12.  
  13. This software is provided as a professional and academic contribution
  14. for joint exchange. Thus, it is experimental, and is provided ``as is'',
  15. with no warranties of any kind whatsoever, no support, no promise of
  16. updates, or printed documentation. By using this software, you
  17. acknowledge that the Lawrence Berkeley Laboratory and Regents of the
  18. University of California shall have no liability with respect to the
  19. infringement of other copyrights by any part of this software.
  20.  
  21. For further information about this notice, contact William Johnston,
  22. Bld. 50B, Rm. 2239, Lawrence Berkeley Laboratory, Berkeley, CA, 94720.
  23. (wejohnston@lbl.gov)
  24.  
  25. For further information about this software, contact:
  26.     Jin Guojun
  27.     Bld. 50B, Rm. 2275, Lawrence Berkeley Laboratory, Berkeley, CA, 94720.
  28.     g_jin@lbl.gov
  29.  
  30. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  31. %
  32. % Restrictions:
  33. %    <1>    with extension mode:
  34. %            (1) only one variable can be passed
  35. %            (2) format string can not be reused
  36. %    <2>    For fast processing:
  37. %        If same flag is given more than once, only the first one
  38. %        is used, and no warning will be given.
  39. %
  40. % Author:    Jin Guojun - LBL    10/01/92
  41. */
  42.  
  43. #ifndef    TC_Need
  44. #    include    <varargs.h>
  45. #endif
  46. #include <ctype.h>
  47. #include <math.h>
  48. #include <string.h>
  49. #include "stdef.h"
  50.  
  51. #ifndef    msg
  52. #define    msg(f, s)    fprintf(stderr, f, s)
  53. #define    mesg( s )    fprintf(stderr, s)
  54. #endif
  55.  
  56. #define    SIZEOF    (MType)sizeof
  57.  
  58. #ifdef    USE_STRING_ARGU_DEF
  59. #define    USAD
  60. #endif
  61. #define    isARGU_B(a)    (a<ARGU_BOOL || a>=ARGU_BORDEF)
  62.  
  63. static    int    use_pounds;
  64.  
  65. void
  66. p_use_pound_sign(bool y_or_n)
  67. {
  68.     use_pounds = y_or_n;
  69. }
  70.  
  71. void
  72. free_arg_fmt_list(int num_list, register arg_fmt_lists*    fmt_list)
  73. {
  74. register int    i, n;
  75.     for (n=num_list; n--; fmt_list++)    {
  76.         i = fmt_list->extended_flags;
  77.         while (i--)
  78.             free(fmt_list->extend[i].v),
  79.             free(fmt_list->extend[i].fls);
  80.         if (fmt_list->extended_flags)
  81.             free(fmt_list->extend);
  82.         free(fmt_list->v);
  83.     }
  84.     free(fmt_list - num_list);
  85. }
  86.  
  87. arg_fmt_lists*
  88. build_arg_fmt_list(int    *retn, arg_fmt_list_string* fmt, va_list ap)
  89. {
  90. int    tBE, na=1;
  91. register int    n, ne;
  92. register arg_fmt_lists*    aflp;
  93. char    *cp, *cpr, *fmtp;
  94. #define    nv    ne
  95.  
  96.     while ((++fmt)->flag)    na++;
  97.     if (retn)    *retn = na;
  98.     aflp = ZALLOC((MType)na, SIZEOF(*aflp), "arg_fmt_list");
  99.  
  100.     for (fmt-=na, n=0; n<na; fmt++, n++)    {
  101.     aflp[n].fls = fmt;
  102.     cp = fmt->flag;
  103.     fmtp = fmt->in_fmt;
  104.     aflp[n].v = ZALLOC((MType)(tBE=fmt->num_vars), SIZEOF(convs), "aconvs");
  105.     for (nv=aflp[n].ext_level=0; nv < tBE; nv++)
  106.         aflp[n].u_l_s = find_input_type(&fmtp, fmt->def_val,
  107.                 nv < fmt->min_inps, aflp[n].v+nv, &ap);
  108.     if (nv)    {    /*    if not comment, build extensions    */
  109.         tBE = isARGU_B(aflp[n].v->type);
  110.         while (cpr = strchr(cp, '['))    {
  111.         register arg_fmt_lists*    eaflp;
  112.         *cpr = NULL;
  113.         cp = ++cpr;
  114.         ne = aflp[n].extended_flags++;
  115.         verify_buffer_size(&aflp[n].extend, -ne-1, SIZEOF(*eaflp), "exaflp");
  116.         eaflp = aflp[n].extend + ne;
  117.         eaflp->ext_level = ++ne;
  118.         eaflp->extended_flags = 0;
  119.         eaflp->fls = ZALLOC(1L, SIZEOF(*eaflp->fls), "efls");
  120.         eaflp->fls->flag = cp;
  121.         if (!(cpr = strchr(cp, ']')))    return    (arg_fmt_lists*)
  122.             prgmerr(-1, "extension not match %s", cp);
  123.         *cpr = NULL;
  124.         eaflp->flag_len = *cp == '#' ? 0 : strlen(cp);
  125.         cp = ++cpr;
  126.         eaflp->v = ZALLOC(1L + tBE, SIZEOF(convs), "econvs");
  127.         eaflp->fls->num_vars = 1 + tBE;
  128.         eaflp->u_l_s = find_input_type(&fmtp, eaflp->fls->def_val =
  129.                 aflp[n].fls->def_val, No, eaflp->v + tBE, &ap);
  130.         if (tBE)    *eaflp->v = *aflp[n].v;
  131.         }
  132.     }
  133.     ne = strlen(fmt->flag);
  134.     aflp[n].flag_len = ne - (fmt->flag[ne-1] == '#');/* for -# */
  135.     }
  136. return    aflp;
  137. }
  138.  
  139.  
  140. /*    return    0 for OK; otherwise for unknown type    */
  141. find_input_type(fmtp, dvsp, setv, v, ap)
  142. register char**    fmtp;
  143. #ifdef    USAD
  144.     char*
  145. #else
  146.     float
  147. #endif
  148.         dvsp;
  149. bool    setv;
  150. convs    *v;
  151. va_list    *ap;
  152. {
  153. static argu_type    last_arg_t=ARGU_NONE;
  154. argu_type    arg_t, et;
  155. register float    dv =
  156. #ifdef    USAD
  157.         atof
  158. #endif
  159.             (dvsp);
  160.  
  161.     while (**fmtp && *(*fmtp)++ != '%');
  162.     v->p.v_p = va_arg(*ap, void*);
  163.  
  164.     et = (*fmtp)[1];
  165.     switch (arg_t = **fmtp)    {
  166.     case 'c':    if (setv) *v->p.c_p = dv;    break;
  167.     case 'd':    arg_t = ARGU_INT;    goto    long_set;
  168.     case 'X':    arg_t = ARGU_HEX;
  169.     case 'x':
  170.     case 's':
  171.     case '-': case '+':if (et==ARGU_SHORT)    goto    sht_set;
  172.     long_set:
  173.     case 'i':    if (setv) *v->p.i_p = dv;    break;
  174.     case 'S':    arg_t = ARGU_SHORT;
  175.     sht_set:
  176.     case 'h':    if (setv) *v->p.s_p = dv;    break;
  177.     case 'f':    if (setv) *v->p.f_p = dv;    break;
  178.     case 'D':    arg_t = ARGU_DOUBLE;
  179.     case 'g':    if (setv) *v->p.d_p = dv;    break;
  180.     case '%':    arg_t = ARGU_ADDPARAM;    /* flag = "?-*"    */
  181.     case 'N': case 'E': case 'B':    case 'b':    case '*':
  182.     case '&':    case '|':    case '^':
  183.     case '#':    case '!':    case '~':    break;
  184.     default:if (isdigit(**fmtp))
  185.             arg_t = (argu_type) atoi(*fmtp);
  186.         else    arg_t = last_arg_t;
  187.     }
  188.     while (*(++*fmtp) && **fmtp != '%');
  189.     v->type = last_arg_t = arg_t;
  190. return    arg_t==ARGU_NONE ? arg_t : et;    /* extended integer type    */
  191. }
  192.  
  193. get_args(int nflags, arg_fmt_lists* fmt_list,
  194.     int argc, char* *argv, int *n, int f)
  195. {
  196. int    dbl_arg, e, noarg = ARGU_NONE;
  197. char    *val;
  198. float    scale;    /* make things a little bit slower, but may be useful    */
  199.  
  200. #define    NUMber()    NS_TSET(n, &f, 0)
  201. #define    NextArg()    NS_TSET(n, &f, 1)
  202.  
  203.     while (nflags--)    {
  204.     register arg_fmt_lists* aflp = fmt_list+nflags;
  205.     register int    cmn = aflp->flag_len, nvs = argv[*n][f+cmn];
  206.     if (cmn)    {
  207.         if (strncmp(argv[*n] + f, aflp->fls->flag, cmn) ||
  208.         ((e=aflp->extended_flags) && nvs &&    /* extension */
  209.         ((noarg=get_args(e, aflp->extend, argc, argv, n, cmn)) >= 0) ||
  210.     /* "-#" */    cmn==1 && *aflp->fls->flag=='-' && !isfloat(nvs)))
  211.         continue;    /* maybe faster than    return    0;    */
  212.             f += cmn;
  213.     }
  214.  
  215.     e =
  216. #ifdef    USAD
  217.         atoi
  218. #endif
  219.             (aflp->fls->def_val);
  220.  
  221.     cmn = aflp->v->type;
  222.     dbl_arg = isARGU_B(cmn);
  223.     if (cmn < ARGU_BNEG)
  224.         *aflp->v->p.a_p = cmn;
  225.  
  226. #define    advf    f = strlen(argv[*n])
  227. #define    vp    aflp->v->p
  228. #define    doSHORT    if (aflp->u_l_s==ARGU_SHORT)
  229.     scale = 0;
  230.     switch (cmn)    {    /*    process ARGU_Bxxxx    */
  231.     case ARGU_BDEF:    doSHORT    *vp.s_p = e;
  232.             else    *vp.i_p = e;    break;
  233.     case ARGU_BANDEF:    doSHORT    *vp.s_p &= e;
  234.                 else    *vp.i_p &= e;    break;
  235.     case ARGU_BORDEF:    doSHORT    *vp.s_p |= e;
  236.                 else    *vp.i_p |= e;    break;
  237.     case ARGU_BXORDEF:    doSHORT    *vp.s_p ^= e;
  238.                 else    *vp.i_p ^= e;    break;
  239.     case ARGU_BEXTYPE:
  240.         if (cmn=aflp->ext_level)    {
  241.             val = aflp->fls->in_fmt;
  242.             while (cmn--)    while (*val && *++val == '%');
  243.             *vp.i_p = *val;
  244.         }
  245.         break;
  246.     case ARGU_BEXT:
  247.         if (aflp->ext_level)
  248.             *vp.i_p = *aflp->fls->flag;
  249.         break;
  250.     case ARGU_BNUM:
  251.     case ARGU_BNEGI:
  252.         *vp.b_p = NUMber();
  253.         if (cmn == ARGU_BNEGI)
  254.     case ARGU_BNEG:    *vp.b_p = !*vp.b_p;
  255.         break;
  256.     case ARGU_BPLUS:
  257.         ++*vp.b_p;    break;
  258.     case ARGU_BMINUS:
  259.         --*vp.b_p;    break;
  260.     case ARGU_SCALE:    scale = *vp.f_p;
  261.     }
  262.  
  263.     if (dbl_arg < aflp->fls->num_vars)    /* safety checking    */
  264.     switch (aflp->v[dbl_arg].type)    {    /* for input argus    */
  265.     case ARGU_BOOL:
  266.         *aflp->v[dbl_arg].p.b_p =
  267. #ifdef    USAD
  268.             strcmp(aflp->fls->def_val, "False") != 0;
  269. #else
  270.             aflp->fls->def_val;
  271. #endif
  272.         break;
  273.     case ARGU_ADDPARAM:
  274.     case ARGU_STRING:
  275.         cmn = aflp->v[dbl_arg].type == ARGU_ADDPARAM;
  276.         for (nvs=dbl_arg; nvs < aflp->fls->num_vars; nvs++)    {
  277. #ifndef    TC_Need
  278.     register    /* Turbo C bug: cant handle single word union.    */
  279. #endif
  280.         convs_p    sp = aflp->v[nvs].p;
  281.         if (cmn)    /* add paramter flag; no argus control    */
  282.             strcat(sp.c_p, argv[*n] + 1),
  283.             strcat(sp.c_p, " "),    advf;
  284.  
  285.         if (!NextArg())    return    f;    /* end of argv list    */
  286.  
  287.         if (!cmn)
  288.             *sp.stp = argv[*n] + f;    /* == *vp.i_p; but != *vp.c_p */
  289.         else    strcat(sp.c_p, argv[*n]), /* add paramter element */
  290.             strcat(sp.c_p, " ");
  291.         advf;
  292.         }    break;
  293.     default:
  294.         if (!aflp->fls->sscan)
  295.         for (nvs=dbl_arg; nvs < aflp->fls->num_vars; nvs++)    {
  296.         double    vd;
  297.             if (!NUMber())
  298.                 if ((e = nvs-aflp->fls->min_inps) < dbl_arg) {
  299.                     if (isdigit(*argv[*n]))    NextArg();
  300.                     return    e-1;
  301.                 } else    {
  302. #ifdef    USAD
  303.                     val = aflp->fls->def_val;
  304. #else
  305.                     val = NULL;
  306.                     vd = aflp->fls->def_val;
  307. #endif
  308.                 }
  309.             else    val = argv[*n] + f,    advf;    /* fast process    */
  310.  
  311.             if (val)    vd = atof(val);
  312.             if (scale)    vd *= scale;
  313.             e = vd;
  314.  
  315.             switch (aflp->v[nvs].type)    {
  316.             case ARGU_HEX:    if (val) {
  317.                 sscanf(val, "%x", aflp->v[nvs].p.i_p);    break;
  318.             }
  319.             case ARGU_INT:    *aflp->v[nvs].p.i_p = e;    break;
  320.             case ARGU_SHORT:*aflp->v[nvs].p.s_p = e;    break;
  321.             case ARGU_FLOAT:*aflp->v[nvs].p.f_p = vd;    break;
  322.             case ARGU_DOUBLE:*aflp->v[nvs].p.d_p = vd;    break;
  323.             default:
  324.                 if (nvs+1 < aflp->fls->min_inps)    return    EOF;
  325.             }
  326.         } else    if (NUMber())    {
  327.         void *tempp[8];    /* max = 8 vars    */
  328.             for (nvs = MIN(8, aflp->fls->num_vars); nvs-->=dbl_arg;)
  329.             tempp[nvs-dbl_arg] = aflp->v[nvs].p.v_p;
  330.             sscanf(argv[*n] + f, aflp->fls->in_fmt + (dbl_arg << 1),
  331.                 tempp[0], tempp[1],
  332.                 tempp[2], tempp[3], tempp[4],
  333.                 tempp[5], tempp[6], tempp[7]);
  334.             advf;
  335.         }
  336.     }
  337.     NextArg();
  338. /*    noarg = abs(noarg) - *n;    if (noarg)    noarg = *n;    */
  339.     noarg = f;
  340.     if (aflp->ext_level && !aflp->extended_flags)    break;
  341.     }
  342. return    noarg;
  343. }
  344.  
  345.  
  346. /*    Independent session. If can be in another file    */
  347. parserr(arg_fmt_lists*    fmt, int items, int vless, int argerr, char**    argv)
  348. {
  349. int    i;
  350. register char*    flagp=argv[argerr];
  351.  
  352.     if (vless=abs(vless)-1)
  353.         prgmerr(0, "option %s less %d argu\n", flagp, vless);
  354.     else    prgmerr(0, "wrong option [%d] %s\n", argerr, flagp);
  355.  
  356.     for (;items-- && *(flagp=fmt[items].fls->flag);)
  357.         if (fmt[items].fls->num_vars)    /* don't change comments */
  358.         /*    recover the extensions    */
  359.         for (i=fmt[items].extended_flags; i--;)    {
  360.             while(*++flagp);    *flagp = '[';
  361.             while(*++flagp);    *flagp = ']';
  362.         }
  363.     parse_usage(fmt->fls);
  364. }
  365.  
  366. parse_usage(register arg_fmt_list_string*    fmt)    /* public entry    */
  367. {
  368. int    i, tBE;
  369. char    msgfmt[128];
  370. register char*    flagp;
  371.  
  372.     for (; flagp=fmt->flag; fmt++)    {
  373.     msg("%s", fmt->flag);
  374.     if (flagp=fmt->in_fmt)
  375.      for (i=0, tBE=isARGU_B(flagp[1]); i<fmt->num_vars || *++flagp; i++) {
  376.     register char    *finfo, c;
  377.         while (*flagp && *flagp++ != '%');
  378.         c = *flagp;
  379.         if (use_pounds && c > ARGU_CHAR && c < ARGU_STRING)
  380.         finfo = "#";
  381.         else switch (c)    {
  382.         default:while (flagp[1] && flagp[1] != Space)    flagp++;
  383.             if (fmt->num_vars > 1)
  384.                 finfo = "";
  385.             else
  386.         case 'b':    finfo = "\t";    break;
  387.         case 'd': case 'i':    finfo = "INTEGER";    break;
  388.         case 'f':    finfo = "FLOAT";    break;
  389.         case 'g': case 'D':    finfo = "DOUBLE";    break;
  390.         case 'h':    finfo = "SHORT";    break;
  391.         case 'c': case 's':    finfo = "STRING";    break;
  392.         case 'X': case 'x':    finfo = "Hex";    break;
  393.         }
  394.         msg(i-tBE<fmt->min_inps || *finfo=='\t'? "  %s" : " [%s]", finfo);
  395.     }
  396.     if (flagp=fmt->info)    {
  397.         while (iscntrl(*flagp))    msg("%c", *flagp++);
  398.         if (strlen(flagp) > sizeof(msgfmt) - 8)
  399.             msg("\t{ %s }\n", flagp);
  400.         else    sprintf(msgfmt, "\t{ %s }\n", flagp),
  401.             msg(msgfmt, fmt->def_val);
  402.     } else    mesg("\t{ < ? > }\n");
  403.     }
  404. }
  405.  
  406. parse_argus(    /* public entry    */
  407.     char**    flistp[],
  408.     int    argc,
  409.     char**    argv,
  410.     arg_fmt_list_string*    fmt,
  411.     va_list    va_alist    )
  412. {
  413. int    i, nf=0, nvars, v;
  414. arg_fmt_lists*    fmt_list = build_arg_fmt_list(&nvars, fmt, (va_list)&va_alist);
  415.  
  416. if (flistp)    *flistp = NULL;
  417.  
  418.     for (i=0; ++i < argc;)    {
  419. retry:    v = get_args(nvars, fmt_list, argc, argv, &i, 0);
  420.     if (v > 0 && !argv[i][v])
  421.         continue;
  422.     else if (*argv[i] != '-' && flistp)    { /*    add_file_list    */
  423.         verify_buffer_size(flistp, -SIZEOF(int), nf+1, "nf");
  424.         (*flistp)[nf++] = argv[i];
  425.     } else if (v < 0)    {
  426.         nf = -i;
  427.         parserr(fmt_list, nvars, v, i, argv);
  428.         break;
  429.     } else     if (!v)    goto    retry;    /*    fast process result    */
  430.     }
  431. free_arg_fmt_list(nvars, fmt_list);
  432. return    nf;
  433. }
  434.