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 in
23 * 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 void
60 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;
109 *l = anext;
110 l = &(*l)->next;
112 *l = nil;
113 return a;
116 int
117 attrnamefmt(Fmt *fmt)
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);
130 return fmtstrcpy(fmt, buf+1);
133 static int
134 hasqueries(Attr *a)
136 for(; a; a=a->next)
137 if(a->type == AttrQuery)
138 return 1;
139 return 0;
142 char *ignored[] = {
143 "role",
144 };
146 static int
147 ignoreattr(char *s)
149 int i;
151 for(i=0; i<nelem(ignored); i++)
152 if(strcmp(ignored[i], s)==0)
153 return 1;
154 return 0;
157 static int
158 hasname(Attr *a0, Attr *a1, char *name)
160 return _findattr(a0, name) || _findattr(a1, name);
163 static int
164 hasnameval(Attr *a0, Attr *a1, char *name, char *val)
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;
177 int
178 matchattr(Attr *pat, Attr *a0, Attr *a1)
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;
201 return 1;
204 Attr*
205 parseattrfmtv(char *fmt, va_list arg)
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;
218 Attr*
219 parseattrfmt(char *fmt, ...)
221 va_list arg;
222 Attr *a;
224 va_start(arg, fmt);
225 a = parseattrfmtv(fmt, arg);
226 va_end(arg);
227 return a;