1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2 
3    Copyright 2002-2024 Free Software Foundation, Inc.
4 
5    Contributed by Andrew Cagney.
6 
7    This file is part of GDB.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 
22 
23 #include <stdio.h>
24 #include <string.h>
25 
26 #include "misc.h"
27 #include "lf.h"
28 #include "filter.h"
29 
30 struct _filter
31 {
32   char *member;
33   filter *next;
34 };
35 
36 
37 void
filter_parse(filter ** filters,const char * filt)38 filter_parse (filter **filters, const char *filt)
39 {
40   while (strlen (filt) > 0)
41     {
42       filter *new_filter;
43       filter **last;
44       /* break out a member of the filter list */
45       const char *flag = filt;
46       unsigned /*size_t */ len;
47       filt = strchr (filt, ',');
48       if (filt == NULL)
49           {
50             filt = strchr (flag, '\0');
51             len = strlen (flag);
52           }
53       else
54           {
55             len = filt - flag;
56             filt = filt + 1;
57           }
58       /* find an insertion point - sorted order */
59       last = filters;
60       while (*last != NULL && strncmp (flag, (*last)->member, len) > 0)
61           last = &(*last)->next;
62       if (*last != NULL
63             && strncmp (flag, (*last)->member, len) == 0
64             && strlen ((*last)->member) == len)
65           continue;           /* duplicate */
66       /* create an entry for that member */
67       new_filter = ZALLOC (filter);
68       new_filter->member = NZALLOC (char, len + 1);
69       strncpy (new_filter->member, flag, len);
70       /* insert it */
71       new_filter->next = *last;
72       *last = new_filter;
73     }
74 }
75 
76 
77 void
filter_add(filter ** set,const filter * add)78 filter_add (filter **set, const filter *add)
79 {
80   while (add != NULL)
81     {
82       int cmp;
83       if (*set == NULL)
84           cmp = 1;            /* set->member > add->member */
85       else
86           cmp = strcmp ((*set)->member, add->member);
87       if (cmp > 0)
88           {
89             /* insert it here */
90             filter *new = ZALLOC (filter);
91             new->member = NZALLOC (char, strlen (add->member) + 1);
92             strcpy (new->member, add->member);
93             new->next = *set;
94             *set = new;
95             add = add->next;
96           }
97       else if (cmp == 0)
98           {
99             /* already in set */
100             add = add->next;
101           }
102       else                              /* cmp < 0 */
103           {
104             /* not reached insertion point */
105             set = &(*set)->next;
106           }
107     }
108 }
109 
110 
111 int
filter_is_subset(const filter * superset,const filter * subset)112 filter_is_subset (const filter *superset, const filter *subset)
113 {
114   while (1)
115     {
116       int cmp;
117       if (subset == NULL)
118           return 1;
119       if (superset == NULL)
120           return 0;           /* subset isn't finished */
121       cmp = strcmp (subset->member, superset->member);
122       if (cmp < 0)
123           return 0;           /* not found */
124       else if (cmp == 0)
125           subset = subset->next;        /* found */
126       else if (cmp > 0)
127           superset = superset->next;    /* later in list? */
128     }
129 }
130 
131 
132 int
filter_is_common(const filter * l,const filter * r)133 filter_is_common (const filter *l, const filter *r)
134 {
135   while (1)
136     {
137       int cmp;
138       if (l == NULL)
139           return 0;
140       if (r == NULL)
141           return 0;
142       cmp = strcmp (l->member, r->member);
143       if (cmp < 0)
144           l = l->next;
145       else if (cmp == 0)
146           return 1;           /* common member */
147       else if (cmp > 0)
148           r = r->next;
149     }
150 }
151 
152 
153 int
filter_is_member(const filter * filt,const char * flag)154 filter_is_member (const filter *filt, const char *flag)
155 {
156   int index = 1;
157   while (filt != NULL)
158     {
159       if (strcmp (flag, filt->member) == 0)
160           return index;
161       filt = filt->next;
162       index++;
163     }
164   return 0;
165 }
166 
167 
168 int
is_filtered_out(const filter * filters,const char * flags)169 is_filtered_out (const filter *filters, const char *flags)
170 {
171   while (strlen (flags) > 0)
172     {
173       int present;
174       const filter *filt = filters;
175       /* break the string up */
176       const char *end = strchr (flags, ',');
177       const char *next;
178       unsigned /*size_t */ len;
179       if (end == NULL)
180           {
181             end = strchr (flags, '\0');
182             next = end;
183           }
184       else
185           {
186             next = end + 1;
187           }
188       len = end - flags;
189       /* check that it is present */
190       present = 0;
191       filt = filters;
192       while (filt != NULL)
193           {
194             if (strncmp (flags, filt->member, len) == 0
195                 && strlen (filt->member) == len)
196               {
197                 present = 1;
198                 break;
199               }
200             filt = filt->next;
201           }
202       if (!present)
203           return 1;
204       flags = next;
205     }
206   return 0;
207 }
208 
209 
210 const char *
filter_next(const filter * set,const char * member)211 filter_next (const filter *set, const char *member)
212 {
213   while (set != NULL)
214     {
215       if (strcmp (set->member, member) > 0)
216           return set->member;
217       set = set->next;
218     }
219   return NULL;
220 }
221 
222 
223 void
dump_filter(lf * file,const char * prefix,const filter * set,const char * suffix)224 dump_filter (lf *file,
225                const char *prefix,
226                const filter *set,
227                const char *suffix)
228 {
229   const char *member;
230   lf_printf (file, "%s", prefix);
231   member = filter_next (set, "");
232   if (member != NULL)
233     {
234       while (1)
235           {
236             lf_printf (file, "%s", member);
237             member = filter_next (set, member);
238             if (member == NULL)
239               break;
240             lf_printf (file, ",");
241           }
242     }
243   lf_printf (file, "%s", suffix);
244 }
245 
246 
247 #ifdef MAIN
248 int
main(int argc,char ** argv)249 main (int argc, char **argv)
250 {
251   filter *subset = NULL;
252   filter *superset = NULL;
253   lf *l;
254   int i;
255   if (argc < 2)
256     {
257       printf ("Usage: filter <subset> <filter> ...\n");
258       exit (1);
259     }
260 
261   /* load the filter up */
262   filter_parse (&subset, argv[1]);
263   for (i = 2; i < argc; i++)
264     filter_parse (&superset, argv[i]);
265 
266   /* dump various info */
267   l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-filter");
268 
269   /* subset */
270   {
271     dump_filter (l, "{", subset, " }");
272     if (filter_is_subset (superset, subset))
273       lf_printf (l, " subset of ");
274     else
275       lf_printf (l, " !subset of ");
276     dump_filter (l, "{", superset, " }");
277     lf_printf (l, "\n");
278   }
279   /* intersection */
280   {
281     dump_filter (l, "{", subset, " }");
282     if (filter_is_common (subset, superset))
283       lf_printf (l, " intersects ");
284     else
285       lf_printf (l, " !intersects ");
286     dump_filter (l, "{", superset, " }");
287     lf_printf (l, "\n");
288   }
289   /* membership */
290   {
291     filter *memb = subset;
292     while (memb != NULL)
293       {
294           lf_printf (l, "%s", memb->member);
295           if (filter_is_member (superset, memb->member))
296             lf_printf (l, " in ");
297           else
298             lf_printf (l, " !in ");
299           dump_filter (l, "{", superset, " }");
300           lf_printf (l, "\n");
301           memb = memb->next;
302       }
303   }
304   /* addition */
305   {
306     filter *add = NULL;
307     filter_add (&add, superset);
308     filter_add (&add, subset);
309     dump_filter (l, "{", add, " }");
310     lf_printf (l, " = ");
311     dump_filter (l, "{", subset, " }");
312     lf_printf (l, " + ");
313     dump_filter (l, "{", superset, " }");
314     lf_printf (l, "\n");
315   }
316 
317   return 0;
318 }
319 #endif
320