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 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[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);
130 return fmtstrcpy(fmt, buf+1);
133 /*
134 static int
135 hasqueries(Attr *a)
137 for(; a; a=a->next)
138 if(a->type == AttrQuery)
139 return 1;
140 return 0;
142 */
144 char *ignored[] = {
145 "role",
146 "disabled"
147 };
149 static int
150 ignoreattr(char *s)
152 int i;
154 for(i=0; i<nelem(ignored); i++)
155 if(strcmp(ignored[i], s)==0)
156 return 1;
157 return 0;
160 static int
161 hasname(Attr *a0, Attr *a1, char *name)
163 return _findattr(a0, name) || _findattr(a1, name);
166 static int
167 hasnameval(Attr *a0, Attr *a1, char *name, char *val)
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;
180 int
181 matchattr(Attr *pat, Attr *a0, Attr *a1)
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;
204 return 1;
207 Attr*
208 parseattrfmtv(char *fmt, va_list arg)
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;
221 Attr*
222 parseattrfmt(char *fmt, ...)
224 va_list arg;
225 Attr *a;
227 va_start(arg, fmt);
228 a = parseattrfmtv(fmt, arg);
229 va_end(arg);
230 return a;