diff options
author | aiju <devnull@localhost> | 2018-12-13 10:42:49 +0000 |
---|---|---|
committer | aiju <devnull@localhost> | 2018-12-13 10:42:49 +0000 |
commit | c7304ea03caf68cf035d14f50f6e24e0c16ccdfe (patch) | |
tree | f4b5e8047078c41caa0d98cc0ea3d5012c4d17f9 /sys/src/libdtracy/prov.c | |
parent | dae5a44111dfb21a714824a5cec2abee4f9f9080 (diff) |
dtracy: get rid of DTName struct, support more than three parts in a probe name, wildcard matching
Diffstat (limited to 'sys/src/libdtracy/prov.c')
-rw-r--r-- | sys/src/libdtracy/prov.c | 126 |
1 files changed, 106 insertions, 20 deletions
diff --git a/sys/src/libdtracy/prov.c b/sys/src/libdtracy/prov.c index 8becbc756..c9e4f822c 100644 --- a/sys/src/libdtracy/prov.c +++ b/sys/src/libdtracy/prov.c @@ -14,14 +14,12 @@ dtstrdup(char *n) } DTProbe * -dtpnew(DTName name, DTProvider *prov, void *aux) +dtpnew(char *name, DTProvider *prov, void *aux) { DTProbe *p, **pp; p = dtmalloc(sizeof(DTProbe)); - p->provider = dtstrdup(name.provider); - p->function = dtstrdup(name.function); - p->name = dtstrdup(name.name); + p->name = dtstrdup(name); p->prov = prov; p->aux = aux; p->enablist.probnext = p->enablist.probprev = &p->enablist; @@ -31,46 +29,134 @@ dtpnew(DTName name, DTProvider *prov, void *aux) return p; } +/* does the pattern match at most one probe (or provider if provonly)? */ +static int +patunique(char *pat, int provonly) +{ + for(;; pat++) + switch(*pat){ + case ':': + if(provonly){ + case 0: + return 1; + } + break; + case '?': + case '*': + return 0; + } +} + +static char * +partmatch(char *pat, char *str, int provonly) +{ + for(;; pat++, str++){ + if(*pat == '*') + return pat; + if(*pat != *str && (*pat != '?' || *str == ':') && (!provonly || *pat != ':' || *str != 0)) + return nil; + if(*pat == 0 || *pat == ':' && provonly) + return (void*)-1; + } +} + +/* + do a wildcard match with * and ?, but don't match : against a wildcard + if provonly, stop at the first : + + replacing empty parts with * is done in user space +*/ int -dtstrmatch(char *a, char *b) +dtnamematch(char *pat, char *str, int provonly) { - if(a == nil || *a == 0) return 1; - if(b == nil) return 0; - return strcmp(a, b) == 0; + char *patp, *strp, *p; + + patp = partmatch(pat, str, provonly); + if(patp == nil) return 0; + if(patp == (void*)-1) return 1; + /* reached a * */ + strp = str + (patp - pat); + patp++; + for(;;){ + /* try the rest of the pattern against each position */ + p = partmatch(patp, strp, provonly); + if(p == nil){ + if(*strp == 0 || *strp == ':') return 0; + strp++; + continue; + } + if(p == (void*)-1) + return 1; + /* reached another * */ + strp += p - patp; + patp = p + 1; + } } int -dtpmatch(DTName name, DTProbe ***ret) +dtpmatch(char *name, DTProbe ***ret) { DTProbe **l; int nl; DTProvider **provp, *prov; DTProbe **pp, *p; + int unique, uniqueprov; l = nil; nl = 0; + unique = patunique(name, 0); + uniqueprov = patunique(name, 1); for(provp = dtproviders; prov = *provp, prov != nil; provp++){ - if(!dtstrmatch(name.provider, prov->name)) + if(!dtnamematch(name, prov->name, 1)) continue; - for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext) - if(dtstrmatch(name.function, p->function) && dtstrmatch(name.name, p->name)){ + if(!prov->provided){ + prov->provided = 1; + prov->provide(prov); + } + for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext){ + if(dtnamematch(name, p->name, 0)){ if(ret != nil){ l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *)); l[nl] = p; } nl++; + if(unique) goto out; } - prov->provide(prov, name); - for(; p = *pp, p != nil; pp = &p->provnext) - if(dtstrmatch(name.function, p->function) && dtstrmatch(name.name, p->name)){ - if(ret != nil){ - l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *)); - l[nl] = p; - } - nl++; + } + if(uniqueprov) goto out; + } +out: + if(ret != nil) + *ret = l; + return nl; +} + +int +dtplist(DTProbe ***ret) +{ + DTProbe **l; + int nl; + DTProvider **provp, *prov; + DTProbe **pp, *p; + + l = nil; + nl = 0; + for(provp = dtproviders; prov = *provp, prov != nil; provp++){ + if(!prov->provided){ + prov->provided = 1; + prov->provide(prov); + } + for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext){ + if(ret != nil){ + l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *)); + l[nl] = p; } + nl++; + } } if(ret != nil) *ret = l; + else + dtfree(l); return nl; } |