| #include <u.h> |
| #include <libc.h> |
| #include <auth.h> |
| |
| int |
| _attrfmt(Fmt *fmt) |
| { |
| char *b, buf[1024], *ebuf; |
| Attr *a; |
| |
| ebuf = buf+sizeof buf; |
| b = buf; |
| strcpy(buf, " "); |
| for(a=va_arg(fmt->args, Attr*); a; a=a->next){ |
| if(a->name == nil) |
| continue; |
| switch(a->type){ |
| case AttrQuery: |
| b = seprint(b, ebuf, " %q?", a->name); |
| break; |
| case AttrNameval: |
| b = seprint(b, ebuf, " %q=%q", a->name, a->val); |
| break; |
| case AttrDefault: |
| b = seprint(b, ebuf, " %q:=%q", a->name, a->val); |
| break; |
| } |
| } |
| return fmtstrcpy(fmt, buf+1); |
| } |
| |
| Attr* |
| _copyattr(Attr *a) |
| { |
| Attr **la, *na; |
| |
| na = nil; |
| la = &na; |
| for(; a; a=a->next){ |
| *la = _mkattr(a->type, a->name, a->val, nil); |
| setmalloctag(*la, getcallerpc(&a)); |
| la = &(*la)->next; |
| } |
| *la = nil; |
| return na; |
| } |
| |
| Attr* |
| _delattr(Attr *a, char *name) |
| { |
| Attr *fa; |
| Attr **la; |
| |
| for(la=&a; *la; ){ |
| if(strcmp((*la)->name, name) == 0){ |
| fa = *la; |
| *la = (*la)->next; |
| fa->next = nil; |
| _freeattr(fa); |
| }else |
| la=&(*la)->next; |
| } |
| return a; |
| } |
| |
| Attr* |
| _findattr(Attr *a, char *n) |
| { |
| for(; a; a=a->next) |
| if(strcmp(a->name, n) == 0 && a->type != AttrQuery) |
| return a; |
| return nil; |
| } |
| |
| void |
| _freeattr(Attr *a) |
| { |
| Attr *anext; |
| |
| for(; a; a=anext){ |
| anext = a->next; |
| free(a->name); |
| free(a->val); |
| a->name = (void*)~0; |
| a->val = (void*)~0; |
| a->next = (void*)~0; |
| free(a); |
| } |
| } |
| |
| Attr* |
| _mkattr(int type, char *name, char *val, Attr *next) |
| { |
| Attr *a; |
| |
| a = malloc(sizeof(*a)); |
| if(a==nil) |
| sysfatal("_mkattr malloc: %r"); |
| a->type = type; |
| a->name = strdup(name); |
| a->val = strdup(val); |
| if(a->name==nil || a->val==nil) |
| sysfatal("_mkattr malloc: %r"); |
| a->next = next; |
| setmalloctag(a, getcallerpc(&type)); |
| return a; |
| } |
| |
| static Attr* |
| cleanattr(Attr *a) |
| { |
| Attr *fa; |
| Attr **la; |
| |
| for(la=&a; *la; ){ |
| if((*la)->type==AttrQuery && _findattr(a, (*la)->name)){ |
| fa = *la; |
| *la = (*la)->next; |
| fa->next = nil; |
| _freeattr(fa); |
| }else |
| la=&(*la)->next; |
| } |
| return a; |
| } |
| |
| Attr* |
| _parseattr(char *s) |
| { |
| char *p, *t, *tok[256]; |
| int i, ntok, type; |
| Attr *a; |
| |
| if(s == nil) |
| return nil; |
| |
| s = strdup(s); |
| if(s == nil) |
| sysfatal("_parseattr strdup: %r"); |
| |
| ntok = tokenize(s, tok, nelem(tok)); |
| a = nil; |
| for(i=ntok-1; i>=0; i--){ |
| t = tok[i]; |
| if(p = strchr(t, '=')){ |
| *p++ = '\0'; |
| /* if(p-2 >= t && p[-2] == ':'){ */ |
| /* p[-2] = '\0'; */ |
| /* type = AttrDefault; */ |
| /* }else */ |
| type = AttrNameval; |
| a = _mkattr(type, t, p, a); |
| setmalloctag(a, getcallerpc(&s)); |
| } |
| else if(t[strlen(t)-1] == '?'){ |
| t[strlen(t)-1] = '\0'; |
| a = _mkattr(AttrQuery, t, "", a); |
| setmalloctag(a, getcallerpc(&s)); |
| }else{ |
| /* really a syntax error, but better to provide some indication */ |
| a = _mkattr(AttrNameval, t, "", a); |
| setmalloctag(a, getcallerpc(&s)); |
| } |
| } |
| free(s); |
| return cleanattr(a); |
| } |
| |
| char* |
| _strfindattr(Attr *a, char *n) |
| { |
| a = _findattr(a, n); |
| if(a == nil) |
| return nil; |
| return a->val; |
| } |
| |