]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdtracy/prov.c
vmx: clean up mksegment, memset only if segment existed (devsegment clears new ones)
[plan9front.git] / sys / src / libdtracy / prov.c
1 #include <u.h>
2 #include <libc.h>
3 #include <dtracy.h>
4
5 char *
6 dtstrdup(char *n)
7 {
8         char *m;
9         
10         m = dtmalloc(strlen(n) + 1);
11         strcpy(m, n);
12         setmalloctag(m, getcallerpc(&n));
13         return m;
14 }
15
16 DTProbe *
17 dtpnew(char *name, DTProvider *prov, void *aux)
18 {
19         DTProbe *p, **pp;
20
21         p = dtmalloc(sizeof(DTProbe));
22         p->name = dtstrdup(name);
23         p->prov = prov;
24         p->aux = aux;
25         p->enablist.probnext = p->enablist.probprev = &p->enablist;
26         for(pp = &prov->probes; *pp != nil; pp = &(*pp)->provnext)
27                 ;
28         *pp = p;
29         return p;
30 }
31
32 /* does the pattern match at most one probe (or provider if provonly)? */
33 static int
34 patunique(char *pat, int provonly)
35 {
36         for(;; pat++)
37                 switch(*pat){
38                 case ':':
39                         if(provonly){
40                 case 0:
41                                 return 1;
42                         }
43                         break;
44                 case '?':
45                 case '*':
46                         return 0;
47                 }
48 }
49
50 static char *
51 partmatch(char *pat, char *str, int provonly)
52 {
53         for(;; pat++, str++){
54                 if(*pat == '*')
55                         return pat;
56                 if(*pat != *str && (*pat != '?' || *str == ':') && (!provonly || *pat != ':' || *str != 0))
57                         return nil;
58                 if(*pat == 0 || *pat == ':' && provonly)
59                         return (void*)-1;
60         }
61 }
62
63 /*      
64         do a wildcard match with * and ?, but don't match : against a wildcard
65         if provonly, stop at the first :
66         
67         replacing empty parts with * is done in user space
68 */
69 int
70 dtnamematch(char *pat, char *str, int provonly)
71 {
72         char *patp, *strp, *p;
73         
74         patp = partmatch(pat, str, provonly);
75         if(patp == nil) return 0;
76         if(patp == (void*)-1) return 1;
77         /* reached a * */
78         strp = str + (patp - pat);
79         patp++;
80         for(;;){
81                 /* try the rest of the pattern against each position */
82                 p = partmatch(patp, strp, provonly);
83                 if(p == nil){
84                         if(*strp == 0 || *strp == ':') return 0;
85                         strp++;
86                         continue;
87                 }
88                 if(p == (void*)-1)
89                         return 1;
90                 /* reached another * */
91                 strp += p - patp;
92                 patp = p + 1;
93         }
94 }
95
96 int
97 dtpmatch(char *name, DTProbe ***ret)
98 {
99         DTProbe **l;
100         int nl;
101         DTProvider **provp, *prov;
102         DTProbe **pp, *p;
103         int unique, uniqueprov;
104         
105         l = nil;
106         nl = 0;
107         unique = patunique(name, 0);
108         uniqueprov = patunique(name, 1);
109         for(provp = dtproviders; prov = *provp, prov != nil; provp++){
110                 if(!dtnamematch(name, prov->name, 1))
111                         continue;
112                 if(!prov->provided){
113                         prov->provided = 1;
114                         prov->provide(prov);
115                 }
116                 for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext){
117                         if(dtnamematch(name, p->name, 0)){
118                                 if(ret != nil){
119                                         l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *));
120                                         l[nl] = p;
121                                 }
122                                 nl++;
123                                 if(unique) goto out;
124                         }
125                 }
126                 if(uniqueprov) goto out;
127         }
128 out:
129         if(ret != nil)
130                 *ret = l;
131         return nl;
132 }
133
134 int
135 dtplist(DTProbe ***ret)
136 {
137         DTProbe **l;
138         int nl;
139         DTProvider **provp, *prov;
140         DTProbe **pp, *p;
141         
142         l = nil;
143         nl = 0;
144         for(provp = dtproviders; prov = *provp, prov != nil; provp++){
145                 if(!prov->provided){
146                         prov->provided = 1;
147                         prov->provide(prov);
148                 }
149                 for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext){
150                         if(ret != nil){
151                                 l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *));
152                                 l[nl] = p;
153                         }
154                         nl++;
155                 }
156         }
157         if(ret != nil)
158                 *ret = l;
159         else
160                 dtfree(l);
161         return nl;
162 }