attr.c (3685B)
1 #include "std.h" 2 #include "dat.h" 3 4 Attr* 5 addattr(Attr *a, char *fmt, ...) 6 { 7 char buf[8192]; 8 va_list arg; 9 Attr *b; 10 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 } 20 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; 30 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 } 58 59 void 60 setmalloctaghere(void *v) 61 { 62 setmalloctag(v, getcallerpc(&v)); 63 } 64 65 Attr* 66 sortattr(Attr *a) 67 { 68 int i; 69 Attr *anext, *a0, *a1, **l; 70 71 if(a == nil || a->next == nil) 72 return a; 73 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 } 88 89 /* sort */ 90 a0 = sortattr(a0); 91 a1 = sortattr(a1); 92 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 } 115 116 int 117 attrnamefmt(Fmt *fmt) 118 { 119 char *b, buf[8192], *ebuf; 120 Attr *a; 121 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 } 132 133 /* 134 static int 135 hasqueries(Attr *a) 136 { 137 for(; a; a=a->next) 138 if(a->type == AttrQuery) 139 return 1; 140 return 0; 141 } 142 */ 143 144 char *ignored[] = { 145 "role", 146 "disabled" 147 }; 148 149 static int 150 ignoreattr(char *s) 151 { 152 int i; 153 154 for(i=0; i<nelem(ignored); i++) 155 if(strcmp(ignored[i], s)==0) 156 return 1; 157 return 0; 158 } 159 160 static int 161 hasname(Attr *a0, Attr *a1, char *name) 162 { 163 return _findattr(a0, name) || _findattr(a1, name); 164 } 165 166 static int 167 hasnameval(Attr *a0, Attr *a1, char *name, char *val) 168 { 169 Attr *a; 170 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 } 179 180 int 181 matchattr(Attr *pat, Attr *a0, Attr *a1) 182 { 183 int type; 184 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 } 206 207 Attr* 208 parseattrfmtv(char *fmt, va_list arg) 209 { 210 char *s; 211 Attr *a; 212 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 } 220 221 Attr* 222 parseattrfmt(char *fmt, ...) 223 { 224 va_list arg; 225 Attr *a; 226 227 va_start(arg, fmt); 228 a = parseattrfmtv(fmt, arg); 229 va_end(arg); 230 return a; 231 }