Autah-cs.209 net.sources utzoo!decvax!ucbvax!mhtsa!harpo!utah-cs!thomas Mon Feb 22 10:09:16 1982 scanargs /* Version 7 compatible Argument scanner, scans argv style argument list. Some stuff is a kludge because sscanf screws up Gary Newman - 10/4/1979 - Ampex Corp. Modified by Spencer W. Thomas, Univ. of Utah, 5/81 to add args introduced by a flag, add qscanargs call, allow empty flags. Compiling with QUICK defined generates 'qscanargs' == scanargs w/o floating point support; avoids huge size of scanf. If you make improvements we'd like to get them too. Jay Lepreau lepreau@utah-20, decvax!{harpo,randvax}!utah-cs!lepreau Spencer Thomas thomas@utah-20, decvax!{harpo,randvax}!utah-cs!thomas (There seems to be a bug here in that if the last option you have is a flag, and the user enters args incorrectly, sometimes the usage message printed will miss the null and go flying off thru core...) --jay for spencer */ #include #include #define YES 1 #define NO 0 #define ERROR(msg) {fprintf(stderr, "msg\n"); goto error; } #ifndef QUICK scanargs (argc, argv, format, arglist) #else qscanargs (argc, argv, format, arglist) #endif int argc; char **argv; char *format; int arglist[]; { #ifndef QUICK _scanargs (argc, argv, format, &arglist); #else _qscanargs (argc, argv, format, &arglist); #endif } #ifndef QUICK _scanargs (argc, argv, format, arglist) #else _qscanargs (argc, argv, format, arglist) #endif int argc; char **argv; char *format; int *arglist[]; { register check; /* check counter to be sure all argvs are processed */ register char *cp; register cnt; char tmpflg; /* temp flag */ char c; char numnum; /* number of numbers already processed */ char numstr; /* count # of strings already processed */ char tmpcnt; /* temp count of # things already processed */ char required; char exflag; /* when set, one of a set of exclusive flags is set */ char excnt; /* count of which exclusive flag is being processed */ char *ncp; /* remember cp during flag scanning */ #ifndef QUICK char *cntrl; /* control string for scanf's */ char junk[2]; /* junk buffer for scanf's */ cntrl = "% %1s"; /* control string initialization for scanf's */ #endif check = numnum = numstr = 0; cp = format; while (*cp) { required = NO; switch (*(cp++)) { default: /* all other chars */ break; case '!': /* required argument */ required = YES; case '%': /* not required argument */ switch (tmpflg = *(cp++)) { case '-': /* argument is flag */ /* go back to label */ ncp = cp-1; /* remember */ cp -= 3; for (excnt = exflag = 0 ; *cp != ' ' && !(*cp=='-' &&(cp[-1]=='!'||cp[-1]=='%')); (--cp, excnt++)) { for (cnt = 1; cnt < argc; cnt++) { /* flags all start with - */ if (*argv[cnt] == '-' && !isdigit(argv[cnt][1])) if (*(argv[cnt] + 1) == *cp) { if (*(argv[cnt] + 2) != 0) ERROR (extra flags ignored); if (exflag) ERROR (more than one exclusive flag chosen); exflag++; required = NO; check += cnt; **arglist |= (1 << excnt); break; } } } if (required) ERROR (flag argument missing); cp = ncp; if (!exflag) /* if no flags scanned, skip */ { while (*++cp != ' ' && *cp) if (*cp == '!' || *cp == '%') arglist++; } else cp++; /* skip over - */ while (*cp == ' ') cp++; arglist++; break; case 's': /* char string */ case 'd': /* decimal # */ case 'o': /* octal # */ case 'x': /* hexadecimal # */ #ifndef QUICK case 'f': /* floating # */ #endif case 'D': /* long decimal # */ case 'O': /* long octal # */ case 'X': /* long hexadecimal # */ #ifndef QUICK case 'F': /* double precision floating # */ #endif tmpcnt = tmpflg == 's' ? numstr : numnum; for (cnt = 1; cnt < argc; cnt++) { if (tmpflg == 's')/* string */ { if ((c = *argv[cnt]) == '-') continue; if (c >= '0' && c <= '9') continue; if (tmpcnt-- != 0) continue; **arglist = argv[cnt]; check += cnt; numstr++; required = NO; break; } if (*argv[cnt] == '-') { if(!isdigit (*(argv[cnt] + 1))) continue; } else if (!isdigit(*argv[cnt])) continue; if (tmpcnt-- != 0)/* skip to new one */ continue; #ifndef QUICK /* kludge for sscanf */ if ((tmpflg == 'o' || tmpflg == 'O') && *argv[cnt] > '7') ERROR (Bad numeric argument); cntrl[1] = tmpflg;/* put in conversion */ if (sscanf (argv[cnt], cntrl, *arglist ,junk) != 1) #else if (numcvt(argv[cnt], tmpflg, *arglist) != 1) #endif ERROR (Bad numeric argument); check += cnt; numnum++; required = NO; break; } if (required) switch (tmpflg) { case 'x': case 'X': ERROR (missing hexadecimal argument); case 's': ERROR (missing string argument); case 'o': case 'O': ERROR (missing octal argument); case 'd': case 'D': ERROR (missing decimal argument); case 'f': case 'F': ERROR (missing floating argument); } arglist++; while (*cp == ' ') cp++; break; default: /* error */ fprintf (stderr, "error in call to scanargs\n"); return (0); } } } /* Count up empty flags */ for (cnt=1; cnt= '0' && *str < '0'+base) d = *str - '0'; else if (base == 16 && *str >= 'a' && *str <= 'f') d = 10 + *str - 'a'; else if (base == 16 && *str >= 'A' && *str <= 'F') d = 10 + *str - 'A'; else return 0; retval = retval*base + d; str++; } if (neg) retval = -retval; if (conv == 'D' || conv == 'O' || conv == 'X') *(long *) val = retval; else *val = (int) retval; return 1; } #endif QUICK