Blob
1 #include "std.h"2 #include "dat.h"4 Attr*5 addattr(Attr *a, char *fmt, ...)6 {7 char buf[8192];8 va_list arg;9 Attr *b;11 va_start(arg, fmt);12 vseprint(buf, buf+sizeof buf, fmt, arg);13 va_end(arg);14 b = _parseattr(buf);15 a = addattrs(a, b);16 setmalloctag(a, getcallerpc(&a));17 _freeattr(b);18 return a;19 }21 /*22 * add attributes in list b to list a. If any attributes are in23 * both lists, replace those in a by those in b.24 */25 Attr*26 addattrs(Attr *a, Attr *b)27 {28 int found;29 Attr **l, *aa;31 for(; b; b=b->next){32 switch(b->type){33 case AttrNameval:34 for(l=&a; *l; ){35 if(strcmp((*l)->name, b->name) != 0){36 l=&(*l)->next;37 continue;38 }39 aa = *l;40 *l = aa->next;41 aa->next = nil;42 freeattr(aa);43 }44 *l = mkattr(AttrNameval, b->name, b->val, nil);45 break;46 case AttrQuery:47 found = 0;48 for(l=&a; *l; l=&(*l)->next)49 if((*l)->type==AttrNameval && strcmp((*l)->name, b->name) == 0)50 found++;51 if(!found)52 *l = mkattr(AttrQuery, b->name, b->val, nil);53 break;54 }55 }56 return a;57 }59 void60 setmalloctaghere(void *v)61 {62 setmalloctag(v, getcallerpc(&v));63 }65 Attr*66 sortattr(Attr *a)67 {68 int i;69 Attr *anext, *a0, *a1, **l;71 if(a == nil || a->next == nil)72 return a;74 /* cut list in halves */75 a0 = nil;76 a1 = nil;77 i = 0;78 for(; a; a=anext){79 anext = a->next;80 if(i++%2){81 a->next = a0;82 a0 = a;83 }else{84 a->next = a1;85 a1 = a;86 }87 }89 /* sort */90 a0 = sortattr(a0);91 a1 = sortattr(a1);93 /* merge */94 l = &a;95 while(a0 || a1){96 if(a1==nil){97 anext = a0;98 a0 = a0->next;99 }else if(a0==nil){100 anext = a1;101 a1 = a1->next;102 }else if(strcmp(a0->name, a1->name) < 0){103 anext = a0;104 a0 = a0->next;105 }else{106 anext = a1;107 a1 = a1->next;108 }109 *l = anext;110 l = &(*l)->next;111 }112 *l = nil;113 return a;114 }116 int117 attrnamefmt(Fmt *fmt)118 {119 char *b, buf[8192], *ebuf;120 Attr *a;122 ebuf = buf+sizeof buf;123 b = buf;124 strcpy(buf, " ");125 for(a=va_arg(fmt->args, Attr*); a; a=a->next){126 if(a->name == nil)127 continue;128 b = seprint(b, ebuf, " %q?", a->name);129 }130 return fmtstrcpy(fmt, buf+1);131 }133 /*134 static int135 hasqueries(Attr *a)136 {137 for(; a; a=a->next)138 if(a->type == AttrQuery)139 return 1;140 return 0;141 }142 */144 char *ignored[] = {145 "role",146 "disabled"147 };149 static int150 ignoreattr(char *s)151 {152 int i;154 for(i=0; i<nelem(ignored); i++)155 if(strcmp(ignored[i], s)==0)156 return 1;157 return 0;158 }160 static int161 hasname(Attr *a0, Attr *a1, char *name)162 {163 return _findattr(a0, name) || _findattr(a1, name);164 }166 static int167 hasnameval(Attr *a0, Attr *a1, char *name, char *val)168 {169 Attr *a;171 for(a=_findattr(a0, name); a; a=_findattr(a->next, name))172 if(strcmp(a->val, val) == 0)173 return 1;174 for(a=_findattr(a1, name); a; a=_findattr(a->next, name))175 if(strcmp(a->val, val) == 0)176 return 1;177 return 0;178 }180 int181 matchattr(Attr *pat, Attr *a0, Attr *a1)182 {183 int type;185 for(; pat; pat=pat->next){186 type = pat->type;187 if(ignoreattr(pat->name))188 type = AttrDefault;189 switch(type){190 case AttrQuery: /* name=something be present */191 if(!hasname(a0, a1, pat->name))192 return 0;193 break;194 case AttrNameval: /* name=val must be present */195 if(!hasnameval(a0, a1, pat->name, pat->val))196 return 0;197 break;198 case AttrDefault: /* name=val must be present if name=anything is present */199 if(hasname(a0, a1, pat->name) && !hasnameval(a0, a1, pat->name, pat->val))200 return 0;201 break;202 }203 }204 return 1;205 }207 Attr*208 parseattrfmtv(char *fmt, va_list arg)209 {210 char *s;211 Attr *a;213 s = vsmprint(fmt, arg);214 if(s == nil)215 sysfatal("vsmprint: out of memory");216 a = parseattr(s);217 free(s);218 return a;219 }221 Attr*222 parseattrfmt(char *fmt, ...)223 {224 va_list arg;225 Attr *a;227 va_start(arg, fmt);228 a = parseattrfmtv(fmt, arg);229 va_end(arg);230 return a;231 }