Blob
1 #include "std.h"2 #include "dat.h"4 Attr*5 addattr(Attr *a, char *fmt, ...)6 {7 char buf[1024];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[1024], *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 static int134 hasqueries(Attr *a)135 {136 for(; a; a=a->next)137 if(a->type == AttrQuery)138 return 1;139 return 0;140 }142 char *ignored[] = {143 "role",144 };146 static int147 ignoreattr(char *s)148 {149 int i;151 for(i=0; i<nelem(ignored); i++)152 if(strcmp(ignored[i], s)==0)153 return 1;154 return 0;155 }157 static int158 hasname(Attr *a0, Attr *a1, char *name)159 {160 return _findattr(a0, name) || _findattr(a1, name);161 }163 static int164 hasnameval(Attr *a0, Attr *a1, char *name, char *val)165 {166 Attr *a;168 for(a=_findattr(a0, name); a; a=_findattr(a->next, name))169 if(strcmp(a->val, val) == 0)170 return 1;171 for(a=_findattr(a1, name); a; a=_findattr(a->next, name))172 if(strcmp(a->val, val) == 0)173 return 1;174 return 0;175 }177 int178 matchattr(Attr *pat, Attr *a0, Attr *a1)179 {180 int type;182 for(; pat; pat=pat->next){183 type = pat->type;184 if(ignoreattr(pat->name))185 type = AttrDefault;186 switch(type){187 case AttrQuery: /* name=something be present */188 if(!hasname(a0, a1, pat->name))189 return 0;190 break;191 case AttrNameval: /* name=val must be present */192 if(!hasnameval(a0, a1, pat->name, pat->val))193 return 0;194 break;195 case AttrDefault: /* name=val must be present if name=anything is present */196 if(hasname(a0, a1, pat->name) && !hasnameval(a0, a1, pat->name, pat->val))197 return 0;198 break;199 }200 }201 return 1;202 }204 Attr*205 parseattrfmtv(char *fmt, va_list arg)206 {207 char *s;208 Attr *a;210 s = vsmprint(fmt, arg);211 if(s == nil)212 sysfatal("vsmprint: out of memory");213 a = parseattr(s);214 free(s);215 return a;216 }218 Attr*219 parseattrfmt(char *fmt, ...)220 {221 va_list arg;222 Attr *a;224 va_start(arg, fmt);225 a = parseattrfmtv(fmt, arg);226 va_end(arg);227 return a;228 }