dtracy: get rid of DTName struct, support more than three parts in a probe name, wildcard matching
This commit is contained in:
parent
dae5a44111
commit
c7304ea03c
9 changed files with 207 additions and 111 deletions
|
@ -18,7 +18,6 @@ enum {
|
||||||
};
|
};
|
||||||
#define DTANIL ((u32int)-1)
|
#define DTANIL ((u32int)-1)
|
||||||
|
|
||||||
typedef struct DTName DTName;
|
|
||||||
typedef struct DTProbe DTProbe;
|
typedef struct DTProbe DTProbe;
|
||||||
typedef struct DTExprState DTExprState;
|
typedef struct DTExprState DTExprState;
|
||||||
typedef struct DTAct DTAct;
|
typedef struct DTAct DTAct;
|
||||||
|
@ -32,12 +31,6 @@ typedef struct DTAgg DTAgg;
|
||||||
typedef struct DTBuf DTBuf;
|
typedef struct DTBuf DTBuf;
|
||||||
typedef struct DTTrigInfo DTTrigInfo;
|
typedef struct DTTrigInfo DTTrigInfo;
|
||||||
|
|
||||||
struct DTName {
|
|
||||||
char *provider;
|
|
||||||
char *function;
|
|
||||||
char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
we assign all pairs (probe,action-group) (called an enabling or DTEnab) a unique ID called EPID.
|
we assign all pairs (probe,action-group) (called an enabling or DTEnab) a unique ID called EPID.
|
||||||
we could also use probe IDs and action group IDs but using a single 32-bit ID for both is more flexible/efficient.
|
we could also use probe IDs and action group IDs but using a single 32-bit ID for both is more flexible/efficient.
|
||||||
|
@ -55,7 +48,7 @@ struct DTEnab {
|
||||||
/* probes are never freed */
|
/* probes are never freed */
|
||||||
struct DTProbe {
|
struct DTProbe {
|
||||||
int nenable;
|
int nenable;
|
||||||
DTName;
|
char *name;
|
||||||
DTEnab enablist;
|
DTEnab enablist;
|
||||||
DTProvider *prov;
|
DTProvider *prov;
|
||||||
void *aux; /* for the provider */
|
void *aux; /* for the provider */
|
||||||
|
@ -65,17 +58,16 @@ struct DTProbe {
|
||||||
struct DTProvider {
|
struct DTProvider {
|
||||||
char *name;
|
char *name;
|
||||||
/*
|
/*
|
||||||
provide() is called when the user asks for a probe that doesn't exist.
|
provide() is called when the user first uses a provider.
|
||||||
provide() should call dtpnew() to create probes.
|
provide() should call dtpnew() to create probes.
|
||||||
it can use the DTName as a hint or just create all probes that it knows about.
|
|
||||||
the provider has to ensure not to create the same probe multiple times.
|
|
||||||
*/
|
*/
|
||||||
void (*provide)(DTProvider *, DTName);
|
void (*provide)(DTProvider *);
|
||||||
int (*enable)(DTProbe *); /* enable the probe. return >= 0 for success and < 0 for failure */
|
int (*enable)(DTProbe *); /* enable the probe. return >= 0 for success and < 0 for failure */
|
||||||
void (*disable)(DTProbe *); /* disable the probe */
|
void (*disable)(DTProbe *); /* disable the probe */
|
||||||
|
|
||||||
/* for the library, not the provider */
|
/* for the library, not the provider */
|
||||||
DTProbe *probes;
|
DTProbe *probes;
|
||||||
|
int provided;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -246,8 +238,9 @@ void dtinit(int);
|
||||||
void dtsync(void);
|
void dtsync(void);
|
||||||
|
|
||||||
/* probe functions */
|
/* probe functions */
|
||||||
DTProbe *dtpnew(DTName, DTProvider *, void *aux);
|
DTProbe *dtpnew(char *, DTProvider *, void *aux);
|
||||||
int dtpmatch(DTName, DTProbe ***);
|
int dtpmatch(char *, DTProbe ***);
|
||||||
|
int dtplist(DTProbe ***);
|
||||||
void dtptrigger(DTProbe *, int, DTTrigInfo *);
|
void dtptrigger(DTProbe *, int, DTTrigInfo *);
|
||||||
|
|
||||||
/* expression functions */
|
/* expression functions */
|
||||||
|
@ -269,7 +262,7 @@ void dtclfree(DTClause *);
|
||||||
/* chan functions */
|
/* chan functions */
|
||||||
DTChan *dtcnew(void);
|
DTChan *dtcnew(void);
|
||||||
void dtcfree(DTChan *);
|
void dtcfree(DTChan *);
|
||||||
int dtcaddgr(DTChan *, DTName, DTActGr *);
|
int dtcaddgr(DTChan *, char *, DTActGr *);
|
||||||
int dtcaddcl(DTChan *, DTClause *);
|
int dtcaddcl(DTChan *, DTClause *);
|
||||||
int dtcread(DTChan *, void *, int);
|
int dtcread(DTChan *, void *, int);
|
||||||
int dtcaggread(DTChan *, void *, int);
|
int dtcaggread(DTChan *, void *, int);
|
||||||
|
|
|
@ -25,8 +25,9 @@ program is a series of statements of one of the following forms
|
||||||
\fIprobes\fR \fLif\fR \fIpredicate \fL{\fR \fIactions\fL } \fR
|
\fIprobes\fR \fLif\fR \fIpredicate \fL{\fR \fIactions\fL } \fR
|
||||||
.PP
|
.PP
|
||||||
\fIProbes\fR is a comma-separated list of probes, such as \fLsys:pwrite:entry\fR.
|
\fIProbes\fR is a comma-separated list of probes, such as \fLsys:pwrite:entry\fR.
|
||||||
Each probe consists of three parts separated by \fL:\fR.
|
Each probe name consists of any number of parts separated by \fL:\fR.
|
||||||
If a part is omitted (e.g. \fLqsys::entry\fR), it matches all probes that match the remaining parts.
|
If a part is omitted (e.g. \fLqsys::entry\fR), it matches all probes that match the remaining parts.
|
||||||
|
If the probe name is enclosed in quotation marks, the wildcards \fL*\fR and \fL?\fR are available, e.g. \fL"sys:*stat:entry"\fR.
|
||||||
.PP
|
.PP
|
||||||
\fIPredicate\fR, if specified, is an expression that must evaluate to a non-zero value for the actions to be executed.
|
\fIPredicate\fR, if specified, is an expression that must evaluate to a non-zero value for the actions to be executed.
|
||||||
.PP
|
.PP
|
||||||
|
|
|
@ -46,6 +46,7 @@ prog(DTKChan *p, char *s)
|
||||||
enum {
|
enum {
|
||||||
/* Qdir */
|
/* Qdir */
|
||||||
Qclone = 1,
|
Qclone = 1,
|
||||||
|
Qprobes = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -156,6 +157,7 @@ dtracygen(Chan *c, char *, Dirtab *, int, int s, Dir *dp)
|
||||||
}
|
}
|
||||||
if(c->qid.path == Qdir){
|
if(c->qid.path == Qdir){
|
||||||
if(s-- == 0) goto clone;
|
if(s-- == 0) goto clone;
|
||||||
|
if(s-- == 0) goto probes;
|
||||||
if(s >= ndtktab) return -1;
|
if(s >= ndtktab) return -1;
|
||||||
if(dtklook(s) == nil) return 0;
|
if(dtklook(s) == nil) return 0;
|
||||||
sprint(up->genbuf, "%d", s);
|
sprint(up->genbuf, "%d", s);
|
||||||
|
@ -168,6 +170,12 @@ dtracygen(Chan *c, char *, Dirtab *, int, int s, Dir *dp)
|
||||||
devdir(c, (Qid){Qclone, 0, QTFILE}, up->genbuf, 0, eve, 0444, dp);
|
devdir(c, (Qid){Qclone, 0, QTFILE}, up->genbuf, 0, eve, 0444, dp);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if(c->qid.path == Qprobes){
|
||||||
|
probes:
|
||||||
|
strcpy(up->genbuf, "probes");
|
||||||
|
devdir(c, (Qid){Qprobes, 0, QTFILE}, up->genbuf, 0, eve, 0444, dp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if(s >= nelem(dtracydir))
|
if(s >= nelem(dtracydir))
|
||||||
return -1;
|
return -1;
|
||||||
tab = &dtracydir[s];
|
tab = &dtracydir[s];
|
||||||
|
@ -224,9 +232,13 @@ dtracyopen(Chan *c, int omode)
|
||||||
p = dtknew();
|
p = dtknew();
|
||||||
c->qid.path = QIDPATH(p->idx, Qctl);
|
c->qid.path = QIDPATH(p->idx, Qctl);
|
||||||
}
|
}
|
||||||
p = dtklook(SLOT(c->qid));
|
if(c->qid.path == Qprobes){
|
||||||
if(SLOT(c->qid) >= 0 && p == nil) error(Enonexist);
|
p = nil;
|
||||||
if(FILE(c->qid) != Qdir && !iseve()) error(Eperm);
|
}else{
|
||||||
|
p = dtklook(SLOT(c->qid));
|
||||||
|
if(SLOT(c->qid) >= 0 && p == nil) error(Enonexist);
|
||||||
|
if(FILE(c->qid) != Qdir && !iseve()) error(Eperm);
|
||||||
|
}
|
||||||
ch = devopen(c, omode, nil, 0, dtracygen);
|
ch = devopen(c, omode, nil, 0, dtracygen);
|
||||||
if(p != nil) p->ref++;
|
if(p != nil) p->ref++;
|
||||||
qunlock(&dtracylock);
|
qunlock(&dtracylock);
|
||||||
|
@ -266,12 +278,8 @@ epidread(DTKAux *aux, DTChan *c, char *a, long n, vlong off)
|
||||||
}
|
}
|
||||||
if(aux->str == nil){
|
if(aux->str == nil){
|
||||||
fmtstrinit(&f);
|
fmtstrinit(&f);
|
||||||
for(e = c->enab; e != nil; e = e->channext){
|
for(e = c->enab; e != nil; e = e->channext)
|
||||||
fmtprint(&f, "%d %d %d %s:%s:%s\n", e->epid, e->gr->id, e->gr->reclen,
|
fmtprint(&f, "%d %d %d %s\n", e->epid, e->gr->id, e->gr->reclen, e->prob->name);
|
||||||
e->prob->provider == nil ? "" : e->prob->provider,
|
|
||||||
e->prob->function == nil ? "" : e->prob->function,
|
|
||||||
e->prob->name == nil ? "" : e->prob->name);
|
|
||||||
}
|
|
||||||
aux->str = fmtstrflush(&f);
|
aux->str = fmtstrflush(&f);
|
||||||
}
|
}
|
||||||
return readstr(off, a, n, aux->str);
|
return readstr(off, a, n, aux->str);
|
||||||
|
@ -315,6 +323,24 @@ handleread(DTChan *c, void *a, long n, int(*readf)(DTChan *, void *, int))
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
probesread(DTKAux *aux, char *a, long n, vlong off)
|
||||||
|
{
|
||||||
|
Fmt f;
|
||||||
|
DTProbe **l;
|
||||||
|
int i, nl;
|
||||||
|
|
||||||
|
if(aux->str == nil){
|
||||||
|
fmtstrinit(&f);
|
||||||
|
nl = dtplist(&l);
|
||||||
|
for(i = 0; i < nl; i++)
|
||||||
|
fmtprint(&f, "%s\n", l[i]->name);
|
||||||
|
dtfree(l);
|
||||||
|
aux->str = fmtstrflush(&f);
|
||||||
|
}
|
||||||
|
return readstr(off, a, n, aux->str);
|
||||||
|
}
|
||||||
|
|
||||||
static long
|
static long
|
||||||
dtracyread(Chan *c, void *a, long n, vlong off)
|
dtracyread(Chan *c, void *a, long n, vlong off)
|
||||||
{
|
{
|
||||||
|
@ -332,6 +358,9 @@ dtracyread(Chan *c, void *a, long n, vlong off)
|
||||||
case Qdir:
|
case Qdir:
|
||||||
rc = devdirread(c, a, n, nil, 0, dtracygen);
|
rc = devdirread(c, a, n, nil, 0, dtracygen);
|
||||||
goto out;
|
goto out;
|
||||||
|
case Qprobes:
|
||||||
|
rc = probesread(c->aux, a, n, off);
|
||||||
|
goto out;
|
||||||
default:
|
default:
|
||||||
error(Egreg);
|
error(Egreg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,14 +215,11 @@ static Syscall *wraptab[]={
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sysprovide(DTProvider *prov, DTName)
|
sysprovide(DTProvider *prov)
|
||||||
{
|
{
|
||||||
static int provided;
|
char buf[32], pname[32];
|
||||||
char buf[32];
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(provided) return;
|
|
||||||
provided = 1;
|
|
||||||
dtpsysentry = smalloc(sizeof(Syscall *) * nsyscall);
|
dtpsysentry = smalloc(sizeof(Syscall *) * nsyscall);
|
||||||
dtpsysreturn = smalloc(sizeof(Syscall *) * nsyscall);
|
dtpsysreturn = smalloc(sizeof(Syscall *) * nsyscall);
|
||||||
for(i = 0; i < nsyscall; i++){
|
for(i = 0; i < nsyscall; i++){
|
||||||
|
@ -230,8 +227,10 @@ sysprovide(DTProvider *prov, DTName)
|
||||||
strecpy(buf, buf + sizeof(buf), sysctab[i]);
|
strecpy(buf, buf + sizeof(buf), sysctab[i]);
|
||||||
if(isupper(buf[0])) buf[0] += 'a' - 'A';
|
if(isupper(buf[0])) buf[0] += 'a' - 'A';
|
||||||
if(i == SYSR1) strcpy(buf, "r1");
|
if(i == SYSR1) strcpy(buf, "r1");
|
||||||
dtpsysentry[i] = dtpnew((DTName){"sys", buf, "entry"}, prov, (void *) i);
|
snprint(pname, sizeof(pname), "sys:%s:entry", buf);
|
||||||
dtpsysreturn[i] = dtpnew((DTName){"sys", buf, "return"}, prov, (void *) i);
|
dtpsysentry[i] = dtpnew(pname, prov, (void *) i);
|
||||||
|
snprint(pname, sizeof(pname), "sys:%s:return", buf);
|
||||||
|
dtpsysreturn[i] = dtpnew(pname, prov, (void *) i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,13 +22,9 @@ dtracytimer(void *)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
timerprovide(DTProvider *prov, DTName)
|
timerprovide(DTProvider *prov)
|
||||||
{
|
{
|
||||||
static int provided;
|
timerprobe = dtpnew("timer::1s", prov, nil);
|
||||||
|
|
||||||
if(provided) return;
|
|
||||||
provided = 1;
|
|
||||||
timerprobe = dtpnew((DTName){"timer", "", "1s"}, prov, nil);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -41,6 +41,28 @@ mkval(int type, ...)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
insertstars(char *n)
|
||||||
|
{
|
||||||
|
Fmt f;
|
||||||
|
int partlen;
|
||||||
|
|
||||||
|
fmtstrinit(&f);
|
||||||
|
partlen = 0;
|
||||||
|
for(; *n != 0; n++){
|
||||||
|
if(*n == ':'){
|
||||||
|
if(partlen == 0)
|
||||||
|
fmtrune(&f, '*');
|
||||||
|
partlen = 0;
|
||||||
|
}else
|
||||||
|
partlen++;
|
||||||
|
fmtrune(&f, *n);
|
||||||
|
}
|
||||||
|
if(partlen == 0)
|
||||||
|
fmtrune(&f, '*');
|
||||||
|
return fmtstrflush(&f);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
clausebegin(void)
|
clausebegin(void)
|
||||||
{
|
{
|
||||||
|
@ -52,7 +74,7 @@ void
|
||||||
addprobe(char *s)
|
addprobe(char *s)
|
||||||
{
|
{
|
||||||
clause->probs = erealloc(clause->probs, sizeof(char *) * (clause->nprob + 1));
|
clause->probs = erealloc(clause->probs, sizeof(char *) * (clause->nprob + 1));
|
||||||
clause->probs[clause->nprob++] = strdup(s);
|
clause->probs[clause->nprob++] = insertstars(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *aggtypes[] = {
|
static char *aggtypes[] = {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
%type <n> expr optexpr
|
%type <n> expr optexpr
|
||||||
%type <sym> optsym
|
%type <sym> optsym
|
||||||
%type <t> type
|
%type <t> type
|
||||||
|
%type <str> probe
|
||||||
|
|
||||||
%token <sym> TSYM
|
%token <sym> TSYM
|
||||||
%token <num> TNUM
|
%token <num> TNUM
|
||||||
|
@ -119,8 +120,11 @@ type:
|
||||||
| TSTRING { $$ = type(TYPSTRING); }
|
| TSTRING { $$ = type(TYPSTRING); }
|
||||||
|
|
||||||
probes:
|
probes:
|
||||||
TSYM { addprobe($1->name); }
|
probe { addprobe($1); }
|
||||||
| probes ',' TSYM { addprobe($3->name); }
|
| probes ',' probe { addprobe($3); }
|
||||||
|
|
||||||
|
probe:
|
||||||
|
TSYM { $$ = $1->name; }
|
||||||
|
| TSTR { $$ = $1; }
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
|
@ -81,7 +81,7 @@ dtcfree(DTChan *ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dtcaddgr(DTChan *c, DTName name, DTActGr *gr)
|
dtcaddgr(DTChan *c, char *name, DTActGr *gr)
|
||||||
{
|
{
|
||||||
DTProbe **l, *p;
|
DTProbe **l, *p;
|
||||||
DTEnab *ep;
|
DTEnab *ep;
|
||||||
|
@ -92,6 +92,11 @@ dtcaddgr(DTChan *c, DTName name, DTActGr *gr)
|
||||||
gr->chan = c;
|
gr->chan = c;
|
||||||
|
|
||||||
nl = dtpmatch(name, &l);
|
nl = dtpmatch(name, &l);
|
||||||
|
if(nl == 0){
|
||||||
|
dtfree(l);
|
||||||
|
werrstr("no match for %s", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
n = 0;
|
n = 0;
|
||||||
for(i = 0; i < nl; i++){
|
for(i = 0; i < nl; i++){
|
||||||
p = l[i];
|
p = l[i];
|
||||||
|
@ -118,53 +123,14 @@ dtcaddgr(DTChan *c, DTName name, DTActGr *gr)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
dtnamesplit(char *s, DTName *rp)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
p = strchr(s, ':');
|
|
||||||
if(p == nil) return -1;
|
|
||||||
rp->provider = dtmalloc(p - s + 1);
|
|
||||||
memcpy(rp->provider, s, p - s);
|
|
||||||
s = p + 1;
|
|
||||||
p = strchr(s, ':');
|
|
||||||
if(p == nil){
|
|
||||||
free(rp->provider);
|
|
||||||
rp->provider = nil;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
rp->function = dtmalloc(p - s + 1);
|
|
||||||
memcpy(rp->function, s, p - s);
|
|
||||||
s = p + 1;
|
|
||||||
if(strchr(s, ':') != nil){
|
|
||||||
free(rp->provider);
|
|
||||||
rp->provider = nil;
|
|
||||||
free(rp->function);
|
|
||||||
rp->function = nil;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
rp->name = dtstrdup(s);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
dtcaddcl(DTChan *c, DTClause *cl)
|
dtcaddcl(DTChan *c, DTClause *cl)
|
||||||
{
|
{
|
||||||
DTName n;
|
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
for(i = 0; i < cl->nprob; i++){
|
for(i = 0; i < cl->nprob; i++)
|
||||||
if(dtnamesplit(cl->probs[i], &n) < 0){
|
rc += dtcaddgr(c, cl->probs[i], cl->gr);
|
||||||
werrstr("invalid probe name '%s'", cl->probs[i]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
rc += dtcaddgr(c, n, cl->gr);
|
|
||||||
dtfree(n.provider);
|
|
||||||
dtfree(n.function);
|
|
||||||
dtfree(n.name);
|
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,12 @@ dtstrdup(char *n)
|
||||||
}
|
}
|
||||||
|
|
||||||
DTProbe *
|
DTProbe *
|
||||||
dtpnew(DTName name, DTProvider *prov, void *aux)
|
dtpnew(char *name, DTProvider *prov, void *aux)
|
||||||
{
|
{
|
||||||
DTProbe *p, **pp;
|
DTProbe *p, **pp;
|
||||||
|
|
||||||
p = dtmalloc(sizeof(DTProbe));
|
p = dtmalloc(sizeof(DTProbe));
|
||||||
p->provider = dtstrdup(name.provider);
|
p->name = dtstrdup(name);
|
||||||
p->function = dtstrdup(name.function);
|
|
||||||
p->name = dtstrdup(name.name);
|
|
||||||
p->prov = prov;
|
p->prov = prov;
|
||||||
p->aux = aux;
|
p->aux = aux;
|
||||||
p->enablist.probnext = p->enablist.probprev = &p->enablist;
|
p->enablist.probnext = p->enablist.probprev = &p->enablist;
|
||||||
|
@ -31,16 +29,110 @@ dtpnew(DTName name, DTProvider *prov, void *aux)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/* does the pattern match at most one probe (or provider if provonly)? */
|
||||||
dtstrmatch(char *a, char *b)
|
static int
|
||||||
|
patunique(char *pat, int provonly)
|
||||||
{
|
{
|
||||||
if(a == nil || *a == 0) return 1;
|
for(;; pat++)
|
||||||
if(b == nil) return 0;
|
switch(*pat){
|
||||||
return strcmp(a, b) == 0;
|
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
|
||||||
|
dtnamematch(char *pat, char *str, int provonly)
|
||||||
|
{
|
||||||
|
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
|
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(!dtnamematch(name, prov->name, 1))
|
||||||
|
continue;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(uniqueprov) goto out;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
if(ret != nil)
|
||||||
|
*ret = l;
|
||||||
|
return nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dtplist(DTProbe ***ret)
|
||||||
{
|
{
|
||||||
DTProbe **l;
|
DTProbe **l;
|
||||||
int nl;
|
int nl;
|
||||||
|
@ -50,27 +142,21 @@ dtpmatch(DTName name, DTProbe ***ret)
|
||||||
l = nil;
|
l = nil;
|
||||||
nl = 0;
|
nl = 0;
|
||||||
for(provp = dtproviders; prov = *provp, prov != nil; provp++){
|
for(provp = dtproviders; prov = *provp, prov != nil; provp++){
|
||||||
if(!dtstrmatch(name.provider, prov->name))
|
if(!prov->provided){
|
||||||
continue;
|
prov->provided = 1;
|
||||||
for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext)
|
prov->provide(prov);
|
||||||
if(dtstrmatch(name.function, p->function) && dtstrmatch(name.name, p->name)){
|
}
|
||||||
if(ret != nil){
|
for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext){
|
||||||
l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *));
|
if(ret != nil){
|
||||||
l[nl] = p;
|
l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *));
|
||||||
}
|
l[nl] = p;
|
||||||
nl++;
|
|
||||||
}
|
|
||||||
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++;
|
|
||||||
}
|
}
|
||||||
|
nl++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(ret != nil)
|
if(ret != nil)
|
||||||
*ret = l;
|
*ret = l;
|
||||||
|
else
|
||||||
|
dtfree(l);
|
||||||
return nl;
|
return nl;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue