Small tweaks
Lots of new code imported.
This commit is contained in:
parent
a770daa795
commit
2277c5d7bb
86 changed files with 12444 additions and 91 deletions
228
src/cmd/factotum/attr.c
Normal file
228
src/cmd/factotum/attr.c
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
#include "std.h"
|
||||
#include "dat.h"
|
||||
|
||||
Attr*
|
||||
addattr(Attr *a, char *fmt, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list arg;
|
||||
Attr *b;
|
||||
|
||||
va_start(arg, fmt);
|
||||
vseprint(buf, buf+sizeof buf, fmt, arg);
|
||||
va_end(arg);
|
||||
b = _parseattr(buf);
|
||||
a = addattrs(a, b);
|
||||
setmalloctag(a, getcallerpc(&a));
|
||||
_freeattr(b);
|
||||
return a;
|
||||
}
|
||||
|
||||
/*
|
||||
* add attributes in list b to list a. If any attributes are in
|
||||
* both lists, replace those in a by those in b.
|
||||
*/
|
||||
Attr*
|
||||
addattrs(Attr *a, Attr *b)
|
||||
{
|
||||
int found;
|
||||
Attr **l, *aa;
|
||||
|
||||
for(; b; b=b->next){
|
||||
switch(b->type){
|
||||
case AttrNameval:
|
||||
for(l=&a; *l; ){
|
||||
if(strcmp((*l)->name, b->name) != 0){
|
||||
l=&(*l)->next;
|
||||
continue;
|
||||
}
|
||||
aa = *l;
|
||||
*l = aa->next;
|
||||
aa->next = nil;
|
||||
freeattr(aa);
|
||||
}
|
||||
*l = mkattr(AttrNameval, b->name, b->val, nil);
|
||||
break;
|
||||
case AttrQuery:
|
||||
found = 0;
|
||||
for(l=&a; *l; l=&(*l)->next)
|
||||
if((*l)->type==AttrNameval && strcmp((*l)->name, b->name) == 0)
|
||||
found++;
|
||||
if(!found)
|
||||
*l = mkattr(AttrQuery, b->name, b->val, nil);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
setmalloctaghere(void *v)
|
||||
{
|
||||
setmalloctag(v, getcallerpc(&v));
|
||||
}
|
||||
|
||||
Attr*
|
||||
sortattr(Attr *a)
|
||||
{
|
||||
int i;
|
||||
Attr *anext, *a0, *a1, **l;
|
||||
|
||||
if(a == nil || a->next == nil)
|
||||
return a;
|
||||
|
||||
/* cut list in halves */
|
||||
a0 = nil;
|
||||
a1 = nil;
|
||||
i = 0;
|
||||
for(; a; a=anext){
|
||||
anext = a->next;
|
||||
if(i++%2){
|
||||
a->next = a0;
|
||||
a0 = a;
|
||||
}else{
|
||||
a->next = a1;
|
||||
a1 = a;
|
||||
}
|
||||
}
|
||||
|
||||
/* sort */
|
||||
a0 = sortattr(a0);
|
||||
a1 = sortattr(a1);
|
||||
|
||||
/* merge */
|
||||
l = &a;
|
||||
while(a0 || a1){
|
||||
if(a1==nil){
|
||||
anext = a0;
|
||||
a0 = a0->next;
|
||||
}else if(a0==nil){
|
||||
anext = a1;
|
||||
a1 = a1->next;
|
||||
}else if(strcmp(a0->name, a1->name) < 0){
|
||||
anext = a0;
|
||||
a0 = a0->next;
|
||||
}else{
|
||||
anext = a1;
|
||||
a1 = a1->next;
|
||||
}
|
||||
*l = anext;
|
||||
l = &(*l)->next;
|
||||
}
|
||||
*l = nil;
|
||||
return a;
|
||||
}
|
||||
|
||||
int
|
||||
attrnamefmt(Fmt *fmt)
|
||||
{
|
||||
char *b, buf[1024], *ebuf;
|
||||
Attr *a;
|
||||
|
||||
ebuf = buf+sizeof buf;
|
||||
b = buf;
|
||||
strcpy(buf, " ");
|
||||
for(a=va_arg(fmt->args, Attr*); a; a=a->next){
|
||||
if(a->name == nil)
|
||||
continue;
|
||||
b = seprint(b, ebuf, " %q?", a->name);
|
||||
}
|
||||
return fmtstrcpy(fmt, buf+1);
|
||||
}
|
||||
|
||||
static int
|
||||
hasqueries(Attr *a)
|
||||
{
|
||||
for(; a; a=a->next)
|
||||
if(a->type == AttrQuery)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *ignored[] = {
|
||||
"role",
|
||||
};
|
||||
|
||||
static int
|
||||
ignoreattr(char *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<nelem(ignored); i++)
|
||||
if(strcmp(ignored[i], s)==0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hasname(Attr *a0, Attr *a1, char *name)
|
||||
{
|
||||
return _findattr(a0, name) || _findattr(a1, name);
|
||||
}
|
||||
|
||||
static int
|
||||
hasnameval(Attr *a0, Attr *a1, char *name, char *val)
|
||||
{
|
||||
Attr *a;
|
||||
|
||||
for(a=_findattr(a0, name); a; a=_findattr(a->next, name))
|
||||
if(strcmp(a->val, val) == 0)
|
||||
return 1;
|
||||
for(a=_findattr(a1, name); a; a=_findattr(a->next, name))
|
||||
if(strcmp(a->val, val) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
matchattr(Attr *pat, Attr *a0, Attr *a1)
|
||||
{
|
||||
int type;
|
||||
|
||||
for(; pat; pat=pat->next){
|
||||
type = pat->type;
|
||||
if(ignoreattr(pat->name))
|
||||
type = AttrDefault;
|
||||
switch(type){
|
||||
case AttrQuery: /* name=something be present */
|
||||
if(!hasname(a0, a1, pat->name))
|
||||
return 0;
|
||||
break;
|
||||
case AttrNameval: /* name=val must be present */
|
||||
if(!hasnameval(a0, a1, pat->name, pat->val))
|
||||
return 0;
|
||||
break;
|
||||
case AttrDefault: /* name=val must be present if name=anything is present */
|
||||
if(hasname(a0, a1, pat->name) && !hasnameval(a0, a1, pat->name, pat->val))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Attr*
|
||||
parseattrfmtv(char *fmt, va_list arg)
|
||||
{
|
||||
char *s;
|
||||
Attr *a;
|
||||
|
||||
s = vsmprint(fmt, arg);
|
||||
if(s == nil)
|
||||
sysfatal("vsmprint: out of memory");
|
||||
a = parseattr(s);
|
||||
free(s);
|
||||
return a;
|
||||
}
|
||||
|
||||
Attr*
|
||||
parseattrfmt(char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
Attr *a;
|
||||
|
||||
va_start(arg, fmt);
|
||||
a = parseattrfmtv(fmt, arg);
|
||||
va_end(arg);
|
||||
return a;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue