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