aux/getflags: improve flagfmt parser

This makes the flagfmt parser more robust and accepting
a looser input language — namely by allowing whitespace
around specifier fields and ignoring any empty fields.

Long flagfmts can thus be pleasingly displayed:

	flagfmt='
		a, b, c, C:cache,
		m:mtpt mountpoint,
		s:srvn srvname'
This commit is contained in:
kvik 2020-05-07 00:10:09 +02:00
parent 0dc9c8d019
commit ccf5d3fb9d
3 changed files with 35 additions and 12 deletions

View file

@ -71,7 +71,7 @@ The description of positional argument list is taken from
An example of the script generated: An example of the script generated:
.IP .IP
.EX .EX
% flagfmt='e:example,x,a:arg with args' % flagfmt='e:example, x, a:arg with args'
% aux/getflags -exa arg list positional stuff % aux/getflags -exa arg list positional stuff
example=() example=()
flagx=() flagx=()
@ -87,7 +87,7 @@ Parse the arguments for
.IR leak (1): .IR leak (1):
.IP .IP
.EX .EX
flagfmt='b:showbmp,s:acidfmt,f binary,r res,x width' flagfmt='b:showbmp, s:acidfmt, f binary, r res, x width'
args='name | pid list' args='name | pid list'
if(! ifs=() eval `{aux/getflags $*} || ~ $#* 0){ if(! ifs=() eval `{aux/getflags $*} || ~ $#* 0){
aux/usage aux/usage

View file

@ -9,13 +9,34 @@ usage(void)
exits(0); exits(0);
} }
char*
skipspace(char *p)
{
while(isspace(*p))
p++;
return p;
}
char*
nextarg(char *p)
{
char *s;
s = strchr(p, ',');
if(s == nil)
return p+strlen(p); /* to \0 */
while(*s == ',' || isspace(*s))
s++;
return s;
}
char* char*
findarg(char *flags, Rune r) findarg(char *flags, Rune r)
{ {
char *p; char *p;
Rune rr; Rune rr;
for(p=flags; p!=(char*)1; p=strchr(p, ',')+1){ for(p=skipspace(flags); *p; p=nextarg(p)){
chartorune(&rr, p); chartorune(&rr, p);
if(rr == r) if(rr == r)
return p; return p;
@ -44,10 +65,9 @@ countargs(char *p)
int n; int n;
n = 1; n = 1;
while(*p == ' ') print("%s\n", p);
p++; for(p=skipspace(p); *p && *p != ','; p++)
for(; *p && *p != ','; p++) if(isspace(*p) && !isspace(*(p-1)))
if(*p == ' ' && *(p-1) != ' ')
n++; n++;
return n; return n;
} }
@ -71,7 +91,7 @@ main(int argc, char *argv[])
} }
fmtfdinit(&fmt, 1, buf, sizeof buf); fmtfdinit(&fmt, 1, buf, sizeof buf);
for(p=flags; p!=(char*)1 && *p != 0; p=strchr(p, ',')+1){ for(p=skipspace(flags); *p; p=nextarg(p)){
s = e = nil; s = e = nil;
if(p[1] == ':'){ if(p[1] == ':'){
s = p + 2; s = p + 2;

View file

@ -1,5 +1,6 @@
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
#include <ctype.h>
void void
main(void) main(void)
@ -30,9 +31,11 @@ main(void)
if(flags[0]){ if(flags[0]){
single = 0; single = 0;
for(p=flags; *p; ){ for(p=flags; *p; ){
while(isspace(*p))
p++;
p += chartorune(&r, p); p += chartorune(&r, p);
if(*p == ':') if(*p == ':')
while(*p != '\0' && *p != ',' && *p != ' ') while(*p && *p != ',' && !isspace(*p))
p++; p++;
if(*p == ',' || *p == 0){ if(*p == ',' || *p == 0){
if(!single){ if(!single){
@ -44,7 +47,7 @@ main(void)
p++; p++;
continue; continue;
} }
while(*p == ' ') while(isspace(*p))
p++; p++;
if(single){ if(single){
fmtprint(&fmt, "]"); fmtprint(&fmt, "]");