home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / linux / backup / star-1.3.1.tar.gz / star-1.3.1.tar / star-1.3.1 / lib / getargs.c < prev    next >
C/C++ Source or Header  |  2000-12-30  |  19KB  |  773 lines

  1. /* @(#)getargs.c    2.29 00/12/30 Copyright 1985, 1988, 1995 J. Schilling */
  2. #ifndef lint
  3. static    char sccsid[] =
  4.     "@(#)getargs.c    2.29 00/12/30 Copyright 1985, 1988, 1995 J. Schilling";
  5. #endif
  6. #define    NEW
  7. /*
  8.  *    Copyright (c) 1985, 1988, 1995 J. Schilling
  9.  *
  10.  *    1.3.88     Start implementation of release 2
  11.  */
  12. /*
  13.  *    Parse arguments on a command line.
  14.  *    Format string specifier (appearing directly after flag name):
  15.  *        ''    BOOL
  16.  *        '*'    string
  17.  *        '?'    char
  18.  *        '#'    number
  19.  *        '&'    call function
  20.  *        '+'    inctype        +++ NEU +++
  21.  */
  22. /*
  23.  * This program is free software; you can redistribute it and/or modify
  24.  * it under the terms of the GNU General Public License as published by
  25.  * the Free Software Foundation; either version 2, or (at your option)
  26.  * any later version.
  27.  *
  28.  * This program is distributed in the hope that it will be useful,
  29.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  30.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  31.  * GNU General Public License for more details.
  32.  *
  33.  * You should have received a copy of the GNU General Public License
  34.  * along with this program; see the file COPYING.  If not, write to
  35.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  36.  */
  37. /* LINTLIBRARY */
  38. #include <mconfig.h>
  39. #include <standard.h>
  40. #include <utypes.h>
  41. #include <getargs.h>
  42. #include <ctype.h>
  43. #include <vadefs.h>
  44. #include <strdefs.h>
  45. #include <schily.h>
  46.  
  47. #define    NOARGS          0    /* No more args            */
  48. #define    NOTAFLAG      1    /* Not a flag type argument    */
  49. #define BADFLAG        (-1)    /* Not a valid flag argument    */
  50. #define BADFMT        (-2)    /* Error in format string    */
  51. #define NOTAFILE    (-3)    /* Seems to be a flag type arg    */
  52.  
  53.  
  54.     int    _getargs __PR((int *, char *const **, const char *,
  55.                             BOOL, va_list));
  56. LOCAL    int    dofile __PR((int *, char *const **, const char **));
  57. LOCAL    int    doflag __PR((int *, char *const **, const char *,
  58.                         const char *, BOOL, va_list));
  59. LOCAL    int    dosflags __PR((const char *, const char *, BOOL, va_list));
  60. LOCAL    int    checkfmt __PR((const char *));
  61. LOCAL    int    checkeql __PR((const char *));
  62.  
  63. LOCAL    va_list    va_dummy;
  64.  
  65. LOCAL    char    fmtspecs[] = "#?*&+"; 
  66.  
  67. #define    isfmtspec(c)        (strchr(fmtspecs, c) != NULL)
  68.  
  69. /*---------------------------------------------------------------------------
  70. |
  71. |    get flags until a non flag type argument is reached
  72. |
  73. +---------------------------------------------------------------------------*/
  74. /* VARARGS3 */
  75. #ifdef    PROTOTYPES
  76. int getargs(int *pac, char *const **pav, const char *fmt, ...)
  77. #else
  78. int getargs(pac, pav, fmt, va_alist)
  79.     int    *pac;
  80.     char    **pav[];
  81.     char    *fmt;
  82.     va_dcl
  83. #endif
  84. {
  85.     va_list    args;
  86.     int    ret;
  87.  
  88. #ifdef    PROTOTYPES
  89.     va_start(args, fmt);
  90. #else
  91.     va_start(args);
  92. #endif
  93.     ret = _getargs(pac, pav, fmt, TRUE, args);
  94.     va_end(args);
  95.     return (ret);
  96. }
  97.  
  98.  
  99. /*---------------------------------------------------------------------------
  100. |
  101. |    get all flags on the command line, do not stop on files
  102. |
  103. +---------------------------------------------------------------------------*/
  104. /* VARARGS3 */
  105. #ifdef    PROTOTYPES
  106. int getallargs(int *pac, char *const **pav, const char *fmt, ...)
  107. #else
  108. int getallargs(pac, pav, fmt, va_alist)
  109.     int    *pac;
  110.     char    **pav[];
  111.     char    *fmt;
  112.     va_dcl
  113. #endif
  114. {
  115.     va_list    args;
  116.     int    ret;
  117.  
  118. #ifdef    PROTOTYPES
  119.     va_start(args, fmt);
  120. #else
  121.     va_start(args);
  122. #endif
  123.     for (;; (*pac)--, (*pav)++) {
  124.         if ((ret = _getargs(pac, pav, fmt, TRUE, args)) != NOTAFLAG)
  125.             break;
  126.     }
  127.     va_end(args);
  128.     return (ret);
  129. }
  130.  
  131.  
  132. /*---------------------------------------------------------------------------
  133. |
  134. |    get next non flag type argument (i.e. a file)
  135. |
  136. +---------------------------------------------------------------------------*/
  137. int getfiles(pac, pav, fmt)
  138.     int        *pac;
  139.     char *const    *pav[];
  140.     const char    *fmt;
  141. {
  142.     return (_getargs(pac, pav, fmt, FALSE, va_dummy));
  143. }
  144.  
  145.  
  146. /*---------------------------------------------------------------------------
  147. |
  148. |    check args until the next non flag type argmument is reached
  149. |    *pac is decremented, *pav is incremented so that the
  150. |    non flag type argument is at *pav[0]
  151. |
  152. |    return code:
  153. |        NOARGS        no more args
  154. |        NOTAFLAG    not a flag type argument
  155. |        BADFLAG        a non-matching flag type argument
  156. |        BADFMT        bad syntax in format string
  157. |
  158. |
  159. +---------------------------------------------------------------------------*/
  160. /*LOCAL*/ int _getargs(pac, pav, fmt, setargs, args)
  161.     register int        *pac;
  162.     register char    *const    **pav;
  163.          const char    *fmt;
  164.         BOOL        setargs;
  165.         va_list        args;
  166. {
  167.     const     char    *argp;
  168.          int    ret;
  169.  
  170.  
  171.     for(; *pac > 0; (*pac)--, (*pav)++) {
  172.         argp = **pav;
  173.  
  174.         ret = dofile(pac, pav, &argp);
  175.  
  176.         if (ret != NOTAFILE)
  177.             return (ret);
  178.  
  179.         ret = doflag(pac, pav, argp, fmt, setargs, args);
  180.  
  181.         if (ret != NOTAFLAG)
  182.             return (ret);
  183.     }
  184.     return (NOARGS);
  185. }
  186.  
  187.  
  188. /*---------------------------------------------------------------------------
  189. |
  190. | check if *pargp is a file type argument
  191. |
  192. +---------------------------------------------------------------------------*/
  193. LOCAL int dofile(pac, pav, pargp)
  194.     register int        *pac;
  195.     register char *const    **pav;
  196.          const char    **pargp;
  197. {
  198.     register const char    *argp = *pargp;
  199.  
  200.  
  201.     if (argp[0] == '-') {
  202.         /*
  203.          * "-" is a special non flag type argument
  204.          *     that usually means take stdin instead of a named file
  205.          */
  206.         if (argp[1] == '\0')
  207.             return (NOTAFLAG);
  208.         /*
  209.          * "--" is a prefix to take the next argument
  210.          *    as non flag type argument
  211.          * NOTE: Posix requires "--" to indicate the end of the
  212.          *     flags on the command line. But we are currently not
  213.          *     Posix.
  214.          */
  215.         if (argp[1] == '-' && argp[2] == '\0') {
  216.             if (--(*pac) > 0) {
  217.                 (*pav)++;
  218.                 return (NOTAFLAG);
  219.             } else {
  220.                 return (NOARGS);
  221.             }
  222.         }
  223.     }
  224.  
  225.     /*
  226.      * now check if it may be flag type argument
  227.      * flag type arguments begin with a '-', a '+' or contain a '='
  228.      * i.e. -flag +flag or flag=
  229.      */
  230.     if (argp[0] != '-' && argp[0] != '+' && (!checkeql(argp)))
  231.         return (NOTAFLAG);
  232.  
  233.     return (NOTAFILE);
  234. }
  235.  
  236.  
  237. /*---------------------------------------------------------------------------
  238. |
  239. |    compare argp with the format string
  240. |    if a match is found store the result a la scanf in one of the
  241. |    arguments pointed to in the va_list
  242. |
  243. |    If setargs is FALSE, only check arguments for getfiles()
  244. |    in this case, va_list may be a dummy arg.
  245. |
  246. +---------------------------------------------------------------------------*/
  247. LOCAL int doflag(pac, pav, argp, fmt, setargs, oargs)
  248.         int        *pac;
  249.         char    *const    **pav;
  250.     register const char    *argp;
  251.     register const char    *fmt;
  252.         BOOL        setargs;
  253.         va_list        oargs;
  254. {
  255.     char    argstr[2];
  256.     long    val;
  257.     Llong    llval;
  258.     int    singlecharflag    = 0;
  259.     BOOL    isspec;
  260.     BOOL    hasdash        = FALSE;
  261.     BOOL    doubledash    = FALSE;
  262.     BOOL    haseql        = checkeql(argp);
  263.     const char    *sargp;
  264.     const char    *sfmt    = fmt;
  265.     va_list    args;
  266.     char    *const    *spav    = *pav;
  267.     int        spac    = *pac;
  268.     void        *curarg    = (void *)0;
  269.  
  270.     /*
  271.      * flags beginning with '-' don't have to include the '-' in
  272.      * the format string.
  273.      * flags beginning with '+' have to include it in the format string.
  274.      */
  275.     if (argp[0] == '-') {
  276.         argp++;
  277.         hasdash = TRUE;
  278.         /*
  279.          * Implement legacy support for --longopt
  280.          * If we find a double dash, we do not look for combinations
  281.          * of boolean single char flags.
  282.          */
  283.         if (argp[0] == '-') {
  284.             argp++;
  285.             doubledash = TRUE;
  286.             /*
  287.              * Allow -- only for long options.
  288.              */
  289.             if (argp[1] == '\0') {
  290.                 return (BADFLAG);
  291.             }
  292.         }
  293.     }
  294.     sargp = argp;
  295.  
  296.     /*
  297.      * Initialize 'args' to the start of the argument list.
  298.      * I don't know any portable way to copy an arbitrary
  299.      * C object so I use a system-specific routine
  300.      * (probably a macro) from stdarg.h.  (Remember that
  301.      * if va_list is an array, 'args' will be a pointer
  302.      * and '&args' won't be what I would need for memcpy.)
  303.      * It is a system requirement for SVr4 compatibility
  304.      * to be able to do this assgignement. If your system
  305.      * defines va_list to be an array but does not define
  306.      * va_copy() you are lost.
  307.      * This is needed to make sure, that 'oargs' will not
  308.      * be clobbered.
  309.      */
  310.     va_copy(args, oargs);
  311.  
  312.     if (setargs)
  313.         curarg = va_arg(args, void *);
  314.  
  315.     /*
  316.      * check if the first flag in format string is a singlechar flag
  317.      */
  318.     if (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0')
  319.         singlecharflag++;
  320.     /*
  321.      * check the whole format string for a match
  322.      */
  323.     for(;;) {
  324.         for(;*fmt; fmt++,argp++) {
  325.             if (*fmt == '\\') {
  326.                 /*
  327.                  * Allow "#?*&+" to appear inside a flag.
  328.                  * NOTE: they must be escaped by '\\' only
  329.                  *     inside the the format string.
  330.                  */
  331.                 fmt++;
  332.                 isspec = FALSE;
  333.             } else {
  334.                 isspec = isfmtspec(*fmt);
  335.             }
  336.             /*
  337.              * If isspec is TRUE, the arg beeing checked starts
  338.              * like a valid flag. Argp now points to the rest.
  339.              */
  340.             if (isspec) {
  341.                 /*
  342.                  * If *argp is '+' and we are on the
  343.                  * beginning of the arg that is currently
  344.                  * checked, this cannot be an inc type flag.
  345.                  */
  346.                 if (*argp == '+' && argp == sargp)
  347.                     continue;
  348.                 /*
  349.                  * skip over to arg of flag
  350.                  */
  351.                 if (*argp == '=') {
  352.                     argp++;
  353.                 } else if (*argp != '\0' && haseql) {
  354.                     /*
  355.                      * Flag and arg are not separated by a
  356.                      * space.
  357.                      * Check here for:
  358.                      * xxxxx=yyyyy    match on '&'
  359.                      * Checked before:
  360.                      * abc=yyyyy    match on 'abc&'
  361.                      *         or     'abc*' 
  362.                      *         or     'abc#' 
  363.                      * We come here if 'argp' starts with
  364.                      * the same sequence as a valid flag
  365.                      * and contains an equal sign.
  366.                      * We have tested before if the text
  367.                      * before 'argp' matches exactly.
  368.                      * At this point we have no exact match
  369.                      * and we only allow to match
  370.                      * the special pattern '&'.
  371.                      * We need this e.g. for 'make'.
  372.                      * We allow any flag type argument to
  373.                      * match the format string "&" to set
  374.                      * up a function that handles all odd
  375.                      * stuff that getargs will not grok.
  376.                      * In addition, to allow getargs to be
  377.                      * used for CPP type flags we allow to
  378.                      * match -Dabc=xyz on 'D&'. Note that
  379.                      * Dabc=xyz will not match 'D&'.
  380.                      */
  381.                     if ((!hasdash && argp != sargp) || *fmt != '&')
  382.                         goto nextarg;
  383.                 }
  384.                 /*
  385.                  * *arpp == '\0' || !haseql
  386.                  * We come here if 'argp' starts with
  387.                  * the same sequence as a valid flag.
  388.                  * This will match on the following args:
  389.                  * -farg    match on 'f*'
  390.                  * -f12        match on 'f#'
  391.                  * +12        match on '+#'
  392.                  * -12        match on '#'
  393.                  * and all args that are separated from
  394.                  * their flags.
  395.                  * In the switch statement below, we check
  396.                  * if the text after 'argp' (if *argp != 0) or
  397.                  * the next arg is a valid arg for this flag.
  398.                   */
  399.                 break;
  400.             } else if (*fmt == *argp) {
  401.                 if (argp[1] == '\0' &&
  402.                     (fmt[1] == '\0' || fmt[1] == ',')) {
  403.  
  404.                     if (setargs)
  405.                         *((int *)curarg) = TRUE;
  406.  
  407.  
  408.                     return (checkfmt(fmt));/* XXX */
  409.                 }
  410.             } else {
  411.                 /*
  412.                  * skip over to next format identifier
  413.                  * & reset arg pointer
  414.                  */
  415.             nextarg:
  416.                 while (*fmt != ',' && *fmt != '\0') {
  417.                     /* function has extra arg on stack */
  418.                     if (*fmt == '&' && setargs)
  419.                         curarg = va_arg(args, void *);
  420.                     fmt++;
  421.                 }
  422.                 argp = sargp;
  423.                 break;
  424.             }
  425.         }
  426.         switch(*fmt) {
  427.  
  428.         case '\0':
  429.             /*
  430.              * Boolean type has been tested before.
  431.              */
  432.             if (singlecharflag && !doubledash &&
  433.                (val = dosflags(sargp, sfmt, setargs, oargs)) !=
  434.                                 BADFLAG)
  435.                 return (val);
  436.  
  437.  
  438.             return (BADFLAG);
  439.  
  440.         case ',':
  441.             fmt++;
  442.             if (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0')
  443.                 singlecharflag++;
  444.             if (setargs)
  445.                 curarg = va_arg(args, void *);
  446.             continue;
  447.  
  448.         case '*':
  449.             if (*argp == '\0') {
  450.                 if (*pac > 1) {
  451.                     (*pac)--;
  452.                     (*pav)++;
  453.                     argp = **pav;
  454.                 } else {
  455.                     return (BADFLAG);
  456.                 }
  457.             }
  458.             if (setargs)
  459.                 *((const char **)curarg) = argp;
  460.  
  461.  
  462.             return (checkfmt(fmt));
  463.  
  464.         case '?':
  465.             /*
  466.              * If more than one char arg, it
  467.              * cannot be a character argument.
  468.              */
  469.             if (argp[1] != '\0')
  470.                 goto nextchance;
  471.             if (setargs)
  472.                 *((char *)curarg) = *argp;
  473.  
  474.  
  475.             return (checkfmt(fmt));
  476.  
  477.         case '+':
  478.             /*
  479.              * inc type is similar to boolean,
  480.              * there is no arg in argp to convert.
  481.              */
  482.             if (*argp != '\0')
  483.                 goto nextchance;
  484.             /*
  485.              * If *fmt is '+' and we are on the beginning
  486.              * of the format desciptor that is currently
  487.              * checked, this cannot be an inc type flag.
  488.              */
  489.             if (fmt == sfmt || fmt[-1] == ',')
  490.                 goto nextchance;
  491.  
  492.             if (fmt[1] == 'l' || fmt[1] == 'L') {
  493.                 if (fmt[2] == 'l' || fmt[2] == 'L') {
  494.                     if (setargs)
  495.                         *((Llong *)curarg) += 1;
  496.                     fmt += 2;
  497.                 } else {
  498.                     if (setargs)
  499.                         *((long *)curarg) += 1;
  500.                     fmt++;
  501.                 }
  502.             } else if (fmt[1] == 's' || fmt[1] == 'S') {
  503.                 if (setargs)
  504.                     *((short *)curarg) += 1;
  505.                 fmt++;
  506.             } else {
  507.                 if (fmt[1] == 'i' || fmt[1] == 'I')
  508.                     fmt++;
  509.                 if (setargs)
  510.                     *((int *)curarg) += 1;
  511.             }
  512.  
  513.             argstr[0] = *fmt;
  514.             argstr[1] = '\0';
  515.  
  516.             return (checkfmt(fmt));
  517.  
  518.         case '#':
  519.             if (*argp == '\0') {
  520.                 if (*pac > 1) {
  521.                     (*pac)--;
  522.                     (*pav)++;
  523.                     argp = **pav;
  524.                 } else {
  525.                     return (BADFLAG);
  526.                 }
  527.             }
  528.             if (*astoll(argp, &llval) != '\0') {
  529.                 /*
  530.                  * arg is not a valid number!
  531.                  * go to next format in the format string
  532.                  * and check if arg matches any other type
  533.                  * in the format specs.
  534.                  */
  535.             nextchance:
  536.                 while(*fmt != ',' && *fmt != '\0') {
  537.                     if (*fmt == '&' && setargs)
  538.                         curarg = va_arg(args, void *);
  539.                     fmt++;
  540.                 }
  541.                 argp = sargp;
  542.                 *pac = spac;
  543.                 *pav = spav;
  544.                 continue;
  545.             }
  546.             val = (long)llval;
  547.             if (fmt[1] == 'l' || fmt[1] == 'L') {
  548.                 if (fmt[2] == 'l' || fmt[2] == 'L') {
  549.                     if (setargs)
  550.                         *((Llong *)curarg) = llval;
  551.                     fmt += 2;
  552.                 } else {
  553.                     if (setargs)
  554.                         *((long *)curarg) = val;
  555.                     fmt++;
  556.                 }
  557.             } else if (fmt[1] == 's' || fmt[1] == 'S') {
  558.                 if (setargs)
  559.                     *((short *)curarg) = (short)val;
  560.                 fmt++;
  561.             } else {
  562.                 if (fmt[1] == 'i' || fmt[1] == 'I')
  563.                     fmt++;
  564.                 if (setargs)
  565.                     *((int *)curarg) = (int)val;
  566.             }
  567.             argstr[0] = *fmt;
  568.             argstr[1] = '\0';
  569.  
  570.             return (checkfmt(fmt));
  571.  
  572.         case '&':
  573.             if (*argp == '\0') {
  574.                 if (*pac > 1) {
  575.                     (*pac)--;
  576.                     (*pav)++;
  577.                     argp = **pav;
  578.                 } else {
  579.                     return (BADFLAG);
  580.                 }
  581.             }
  582.  
  583.             if ((val = checkfmt(fmt)) != NOTAFLAG)
  584.                 return (val);
  585.  
  586.             if (setargs) {
  587.                 int    ret;
  588.                 void    *funarg = va_arg(args, void *);
  589.  
  590.                 ret = ((*(getargfun)curarg) (argp, funarg));
  591.                 if (ret != NOTAFILE)
  592.                     return (ret);
  593.                 fmt++;
  594.             } else {
  595.                 return (val);
  596.             }
  597.             /*
  598.              * Called function returns NOTAFILE: try next format.
  599.              */
  600.         }
  601.     }
  602. }
  603.  
  604.  
  605. /*---------------------------------------------------------------------------
  606. |
  607. |    parse args for combined single char flags
  608. |
  609. +---------------------------------------------------------------------------*/
  610. typedef struct {
  611.     void    *curarg;
  612.     short    count;
  613.     char    c;
  614.     char    type;
  615. } sflags;
  616.  
  617. LOCAL int dosflags(argp, fmt, setargs, oargs)
  618.     register const char    *argp;
  619.     register const char    *fmt;
  620.         BOOL        setargs;
  621.         va_list        oargs;
  622. {
  623. #define    MAXSF    32
  624.          sflags    sf[MAXSF];
  625.          va_list args;
  626.     register sflags    *rsf    = sf;
  627.     register int    nsf    = 0;
  628.     register const char *p    = argp;
  629.     register int    i;
  630.     register void    *curarg = (void *)0;
  631.  
  632.     /*
  633.      * Initialize 'args' to the start of the argument list.
  634.      * I don't know any portable way to copy an arbitrary
  635.      * C object so I use a system-specific routine
  636.      * (probably a macro) from stdarg.h.  (Remember that
  637.      * if va_list is an array, 'args' will be a pointer
  638.      * and '&args' won't be what I would need for memcpy.)
  639.      * It is a system requirement for SVr4 compatibility
  640.      * to be able to do this assgignement. If your system
  641.      * defines va_list to be an array but does not define
  642.      * va_copy() you are lost.
  643.      * This is needed to make sure, that 'oargs' will not
  644.      * be clobbered.
  645.      */
  646.     va_copy(args, oargs);
  647.  
  648.     if (setargs)
  649.         curarg = va_arg(args, void *);
  650.  
  651.     while (*p) {
  652.         for (i=0; i < nsf; i++) {
  653.             if (rsf[i].c == *p)
  654.                 break;
  655.         }
  656.         if (i >= MAXSF)
  657.             return (BADFLAG);
  658.         if (i == nsf) {
  659.             rsf[i].curarg = (void *)0;
  660.             rsf[i].count = 0;
  661.             rsf[i].c = *p;
  662.             rsf[i].type = (char)-1;
  663.             nsf++;
  664.         }
  665.         rsf[i].count++;
  666.         p++;
  667.     }
  668.  
  669.     while (*fmt) {
  670.         if (!isfmtspec(*fmt) &&
  671.             (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0') &&
  672.              strchr(argp, *fmt)) {
  673.             for (i=0; i < nsf; i++) {
  674.                 if (rsf[i].c == *fmt) {
  675.                     if (fmt[1] == '+') {
  676.                         fmt++;
  677.                         if (fmt[1] == ',' ||
  678.                             fmt[1] == '\0') {
  679.                             rsf[i].type = 'i';
  680.                         } else if ((fmt[1] == 'l' ||
  681.                                 fmt[1] == 'L') &&
  682.                                (fmt[2] == 'l' ||
  683.                                 fmt[2] == 'L')) {
  684.                             rsf[i].type = 'Q';
  685.                             fmt++;
  686.                         } else {
  687.                             rsf[i].type = fmt[1];
  688.                         }
  689.                     } else {
  690.                         rsf[i].type = fmt[1];
  691.                     }
  692.                     rsf[i].curarg = curarg;
  693.                     break;
  694.                 }
  695.             }
  696.         }
  697.         while (*fmt != ',' && *fmt != '\0') {
  698.             /* function has extra arg on stack */
  699.             if (*fmt == '&' && setargs)
  700.                 curarg = va_arg(args, void *);
  701.             fmt++;
  702.         }
  703.         if (*fmt != '\0')
  704.             fmt++;
  705.  
  706.         if (setargs)
  707.             curarg = va_arg(args, void *);
  708.     }
  709.     for (i=0; i < nsf; i++) {
  710.         if (rsf[i].type == (char)-1)
  711.             return (BADFLAG);
  712.         if (rsf[i].curarg) {
  713.             if (rsf[i].type == ',' || rsf[i].type == '\0') {
  714.                 *((int *)rsf[i].curarg) = TRUE;
  715.             } else if (rsf[i].type == 'i' || rsf[i].type == 'I') {
  716.                 *((int *)rsf[i].curarg) += rsf[i].count;
  717.             } else if (rsf[i].type == 'l' || rsf[i].type == 'L') {
  718.                 *((long *)rsf[i].curarg) += rsf[i].count;
  719.             } else if (rsf[i].type == 'Q') {
  720.                 *((Llong *)rsf[i].curarg) += rsf[i].count;
  721.             } else if (rsf[i].type == 's' || rsf[i].type == 'S') {
  722.                 *((short *)rsf[i].curarg) += rsf[i].count;
  723.             } else {
  724.                 return (BADFLAG);
  725.             }
  726.         }
  727.     }
  728.     return (NOTAFLAG);
  729. }
  730.  
  731. /*---------------------------------------------------------------------------
  732. |
  733. |    If the next format character is a comma or the string delimiter,
  734. |    there are no invalid format specifiers. Return success.
  735. |    Otherwise raise the getarg_bad_format condition.
  736. |
  737. +---------------------------------------------------------------------------*/
  738. LOCAL int checkfmt(fmt)
  739.     const char    *fmt;
  740. {
  741.     char    c;
  742.  
  743.     c = *(++fmt);    /* non constant expression */
  744.  
  745.  
  746.     if (c == ',' || c == '\0') {
  747.         return (NOTAFLAG);
  748.     } else {
  749.         raisecond("getarg_bad_format", (long)fmt);
  750.         return (BADFMT);
  751.     }
  752. }
  753.  
  754. /*---------------------------------------------------------------------------
  755. |
  756. |    Parse the string as long as valid characters can be found.
  757. |    Valid flag identifiers are chosen from the set of
  758. |    alphanumeric characters, '-' and '_'.
  759. |    If the next character is an equal sign the string
  760. |    contains a valid flag identifier.
  761. |
  762. +---------------------------------------------------------------------------*/
  763. static int checkeql(str)
  764.     register const char *str;
  765. {
  766.     register unsigned char c;
  767.  
  768.     for (c = (unsigned char)*str;
  769.                 isalnum(c) || c == '_' || c == '-'; c = *str++)
  770.         ;
  771.     return (c == '=');
  772. }
  773.