61 #define ERROR(msg) {fprintf(stderr
, "%s\n", msg); goto error; }
66 #define NEW( type, cnt ) (type *) malloc( (cnt) * sizeof( type ) )
67 #define RENEW( type, ptr, cnt ) (type *) realloc( ptr, (cnt) * sizeof( type ) )
70 #define USE_PROTOTYPES
74 static char * prformat();
76 static int _do_scanargs();
102 CONST_DECL
char *format;
105 argc = va_arg( argl,
int );
106 argv = va_arg( argl,
char ** );
107 format = va_arg( argl, CONST_DECL
char * );
109 va_start( argl, format );
163 static char cntrl[7] =
"% %1s";
168 if (arg_used == NULL)
170 fprintf(stderr,
"malloc failed in scanargs, exiting\n");
175 for (cnt=0; cnt<argc; cnt++)
181 for ( cnt=1; cnt<argc; cnt++ )
182 if ( strcmp( argv[cnt],
"-help" ) == 0 )
196 no_usage = *(format + strlen( format ) - 1) ==
'&';
202 while ( *cp !=
' ' && *cp !=
'\t' && *cp !=
'\n' && *cp !=
'\0' )
224 while ( *cp && depth > 0 )
227 case '(': depth++;
break;
228 case ')': depth--;
break;
237 switch (typchr = *(cp++))
244 cnt_arg = va_arg( argl,
int *);
248 while ( argc > 1 && !arg_used[argc-1] )
250 *va_arg( argl,
int * ) = argc;
255 for ( nopt = cnt = 1; cnt < argc; cnt++ )
256 if ( !arg_used[cnt] )
262 strlist =
NEW(
char *, nopt + 1 );
264 strlist[0] = argv[0];
265 for ( nopt = cnt = 1; cnt < argc; cnt++ )
266 if ( !arg_used[cnt] )
268 strlist[nopt++] = argv[cnt];
272 strlist[nopt] = NULL;
278 *va_arg( argl,
int * ) = nopt;
279 *va_arg( argl,
char *** ) = strlist;
284 ERROR(
"Format error: flag conditional on flag not allowed");
289 for (excnt = exflag = 0
290 ; *cp !=
' ' && !(*cp==
'-' &&(cp[-1]==
'!'||cp[-1]==
'%'));
293 for (cnt = optarg+1; cnt < argc; cnt++)
296 if (*argv[cnt] ==
'-' && !arg_used[cnt] &&
297 !isdigit(argv[cnt][1]))
298 if (*(argv[cnt] + 1) == *cp)
300 if (*(argv[cnt] + 2) != 0)
301 ERROR (
"extra flags ignored");
303 ERROR (
"more than one exclusive flag chosen");
309 *va_arg( argl,
int *) |= (1 << excnt);
315 ERROR (
"flag argument missing");
323 (
void)va_arg( argl,
int * );
324 while (*++cp && ! isspace(*cp))
325 if (*cp ==
'!' || *cp ==
'%')
327 if ( *++cp ==
'*' || *cp ==
',' )
330 (
void)va_arg( argl,
int * );
338 (
void)va_arg( argl,
char * );
340 (
void)va_arg( argl,
ptr );
362 #if defined(sgi) && !defined(mips)
364 if ( typchr ==
'F' ) typchr =
'f';
366 for (cnt = optarg+1; cnt < argc; cnt++)
374 else if ( *argp ==
'-' && argp[1] !=
'\0' )
378 if ( list_cnt == 0 ) {
380 (
void)va_arg( argl,
char * );
382 (
void)va_arg( argl,
ptr );
388 else if ( typchr !=
's' )
396 if (arg_used[cnt])
continue;
411 s =
NEW(
char, strlen(argp)+1 );
419 for ( pass = 0; pass <= 1; pass++ )
421 for ( s = argp; *s !=
'\0'; )
424 strlist[list_cnt] = s;
425 while ( (c = *s) !=
'\0' && c !=
' ' &&
426 c !=
'\t' && c !=
',' )
439 while ( *++s ==
' ' || *s ==
'\t' )
444 strlist =
NEW(
char *, list_cnt );
459 if ( list_cnt == 1 || comma_list )
464 strlist =
NEW(
char *, 1 );
465 aptr = (
ptr) &strlist[0];
471 intlist =
NEW(
int, list_cnt );
472 aptr = (
ptr) &intlist[0];
478 longlist =
NEW(
long, list_cnt );
479 aptr = (
ptr) &longlist[0];
482 fltlist =
NEW(
float, list_cnt );
483 aptr = (
ptr) &fltlist[0];
486 dbllist =
NEW(
double, list_cnt );
487 aptr = (
ptr) &dbllist[0];
494 strlist =
RENEW(
char *, strlist,
496 aptr = (
ptr) &strlist[list_cnt-1];
502 intlist =
RENEW(
int, intlist,
504 aptr = (
ptr) &intlist[list_cnt-1];
510 longlist =
RENEW(
long, longlist,
512 aptr = (
ptr) &longlist[list_cnt-1];
515 fltlist =
RENEW(
float, fltlist,
517 aptr = (
ptr) &fltlist[list_cnt-1];
520 dbllist =
RENEW(
double, dbllist,
522 aptr = (
ptr) &dbllist[list_cnt-1];
527 aptr = va_arg( argl,
ptr );
532 *(
char **)aptr = argp;
542 if ( comma_list && nopt > 0 )
544 argp = strlist[nopt];
551 aptr = (
ptr) &intlist[nopt];
557 aptr = (
ptr) &longlist[nopt];
560 aptr = (
ptr) &fltlist[nopt];
563 aptr = (
ptr) &dbllist[nopt];
571 if (typchr ==
'n' || typchr ==
'N' ) {
574 else if (*(argp+1) ==
'x' ||
584 tmpflg = toupper( tmpflg );
588 if ( isupper( tmpflg ) )
591 cntrl[2] = tolower( tmpflg );
598 if (sscanf (argp, cntrl, aptr, junk) != 1)
599 ERROR (
"Bad numeric argument");
600 }
while ( comma_list && ++nopt < list_cnt );
609 if ( !( list_of && !comma_list ) )
619 ERROR (
"missing hexadecimal argument");
621 ERROR (
"missing string argument");
624 ERROR (
"missing octal argument");
627 ERROR (
"missing decimal argument");
630 ERROR (
"missing floating argument");
633 ERROR (
"missing numeric argument");
641 *va_arg( argl,
char *** ) = strlist;
647 *va_arg( argl,
int ** ) = intlist;
653 *va_arg( argl,
long ** ) = longlist;
656 *va_arg( argl,
float ** ) = fltlist;
659 *va_arg( argl,
double **) = dbllist;
662 if ( typchr !=
's' && comma_list )
663 free( (
char *) strlist );
665 else if ( cnt >= argc )
669 (
void)va_arg( argl,
char * );
671 (
void)va_arg( argl,
ptr );
676 "scanargs: Corrupt or invalid format spec\n");
683 for (cnt=1; cnt<argc; cnt++)
684 if (argv[cnt][0] ==
'-' && argv[cnt][1] ==
'-' && argv[cnt][2] == 0
689 if (check != (((argc - 1) * argc) / 2))
690 ERROR (
"extra arguments not processed");
713 fprintf (stderr,
"usage : ");
714 if (*(cp = format) !=
' ')
722 for ( cp = argv[0]; *cp !=
'\0'; cp++ )
724 for ( ; cp > argv[0] && *cp !=
'/'; cp-- )
728 fprintf( stderr,
"%s", cp );
732 while (putc (*cp++, stderr) !=
' ');
735 fprintf (stderr,
"?? ");
747 bool required, comma_list;
768 for ( ; format < cp; format++ )
769 putc( *format, stderr );
778 for ( ; format < cp; format++ )
779 putc( *format, stderr );
780 for ( cp++, depth = 1; *cp && depth > 0; )
783 if ( *cp !=
')' || depth > 1 )
787 case '(': depth++;
break;
788 case ')': depth--;
break;
809 for (; format < cp - 1 - list_of; format++)
810 putc (*format, stderr);
811 fputs(
" ...", stderr );
821 if (cp - format > 2 + list_of)
824 while (*cp !=
'%' && *cp !=
'!')
825 putc (*cp++, stderr);
826 if (cp - format > 1 + list_of)
829 if (*cp && !isspace(*cp))
851 for (; format < cp - 1 - list_of; format++)
852 putc (*format, stderr);
859 fputs(
"...", stderr );
872 if (*cp && !isspace(*cp))
875 if (recurse && isspace(*cp))
880 for ( ; format < cp; format++ )
881 putc( *format, stderr );
899 register CONST_DECL char *allowed, *digits, *cp;
906 allowed =
" \t,+-x0123456789abcdefABCDEF";
910 allowed =
" \t,+-0123456789";
914 allowed =
" \t,01234567";
918 allowed =
" \t,0123456789abcdefABCDEF";
922 allowed =
" \t,+-eE.0123456789";
926 allowed =
" \t,+-.0123456789";
930 while ( *digits !=
'0' )
935 while ( *str !=
'\0' )
937 for ( cp = allowed; *cp !=
'\0' && *cp != *str; cp++ )
941 if ( cp - digits >= 0 )
static int _do_scanargs(int argc, char **argv, const char *format, va_list argl)
static const char * prformat(char *format, int recurse) const
int scanargs(int argc, char **argv, const char *format,...)
static int isnum(const char *str, int typchr, int comma_list)
#define RENEW(type, ptr, cnt)