#include "std.h" #include "dat.h" Attr* addattr(Attr *a, char *fmt, ...) { char buf[8192]; va_list arg; Attr *b; needstack(256); /* guess */ 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[8192], *ebuf; Attr *a; needstack(256); /* guess */ 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", "disabled" }; static int ignoreattr(char *s) { int i; for(i=0; inext, 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; }