1/* The IGEN simulator generator for GDB, the GNU Debugger.
2
3   Copyright 2002-2023 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
30struct _filter
31{
32  char *member;
33  filter *next;
34};
35
36
37void
38filter_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
77void
78filter_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
111int
112filter_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
132int
133filter_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
153int
154filter_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
168int
169is_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
210const char *
211filter_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
223void
224dump_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
248int
249main (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