plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }