1/* The IGEN simulator generator for GDB, the GNU Debugger.
2
3   Copyright 2002, 2007, 2008, 2009, 2010, 2011 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
25#include "config.h"
26
27#ifdef HAVE_STRING_H
28#include <string.h>
29#else
30#ifdef HAVE_STRINGS_H
31#include <strings.h>
32#endif
33#endif
34
35#include "misc.h"
36#include "lf.h"
37#include "filter.h"
38
39struct _filter
40{
41  char *member;
42  filter *next;
43};
44
45
46void
47filter_parse (filter **filters, const char *filt)
48{
49  while (strlen (filt) > 0)
50    {
51      filter *new_filter;
52      filter **last;
53      /* break out a member of the filter list */
54      const char *flag = filt;
55      unsigned /*size_t */ len;
56      filt = strchr (filt, ',');
57      if (filt == NULL)
58	{
59	  filt = strchr (flag, '\0');
60	  len = strlen (flag);
61	}
62      else
63	{
64	  len = filt - flag;
65	  filt = filt + 1;
66	}
67      /* find an insertion point - sorted order */
68      last = filters;
69      while (*last != NULL && strncmp (flag, (*last)->member, len) > 0)
70	last = &(*last)->next;
71      if (*last != NULL
72	  && strncmp (flag, (*last)->member, len) == 0
73	  && strlen ((*last)->member) == len)
74	continue;		/* duplicate */
75      /* create an entry for that member */
76      new_filter = ZALLOC (filter);
77      new_filter->member = NZALLOC (char, len + 1);
78      strncpy (new_filter->member, flag, len);
79      /* insert it */
80      new_filter->next = *last;
81      *last = new_filter;
82    }
83}
84
85
86void
87filter_add (filter **set, filter *add)
88{
89  while (add != NULL)
90    {
91      int cmp;
92      if (*set == NULL)
93	cmp = 1;		/* set->member > add->member */
94      else
95	cmp = strcmp ((*set)->member, add->member);
96      if (cmp > 0)
97	{
98	  /* insert it here */
99	  filter *new = ZALLOC (filter);
100	  new->member = NZALLOC (char, strlen (add->member) + 1);
101	  strcpy (new->member, add->member);
102	  new->next = *set;
103	  *set = new;
104	  add = add->next;
105	}
106      else if (cmp == 0)
107	{
108	  /* already in set */
109	  add = add->next;
110	}
111      else			/* cmp < 0 */
112	{
113	  /* not reached insertion point */
114	  set = &(*set)->next;
115	}
116    }
117}
118
119
120int
121filter_is_subset (filter *superset, filter *subset)
122{
123  while (1)
124    {
125      int cmp;
126      if (subset == NULL)
127	return 1;
128      if (superset == NULL)
129	return 0;		/* subset isn't finished */
130      cmp = strcmp (subset->member, superset->member);
131      if (cmp < 0)
132	return 0;		/* not found */
133      else if (cmp == 0)
134	subset = subset->next;	/* found */
135      else if (cmp > 0)
136	superset = superset->next;	/* later in list? */
137    }
138}
139
140
141int
142filter_is_common (filter *l, filter *r)
143{
144  while (1)
145    {
146      int cmp;
147      if (l == NULL)
148	return 0;
149      if (r == NULL)
150	return 0;
151      cmp = strcmp (l->member, r->member);
152      if (cmp < 0)
153	l = l->next;
154      else if (cmp == 0)
155	return 1;		/* common member */
156      else if (cmp > 0)
157	r = r->next;
158    }
159}
160
161
162int
163filter_is_member (filter *filt, const char *flag)
164{
165  int index = 1;
166  while (filt != NULL)
167    {
168      if (strcmp (flag, filt->member) == 0)
169	return index;
170      filt = filt->next;
171      index++;
172    }
173  return 0;
174}
175
176
177int
178is_filtered_out (filter *filters, const char *flags)
179{
180  while (strlen (flags) > 0)
181    {
182      int present;
183      filter *filt = filters;
184      /* break the string up */
185      char *end = strchr (flags, ',');
186      char *next;
187      unsigned /*size_t */ len;
188      if (end == NULL)
189	{
190	  end = strchr (flags, '\0');
191	  next = end;
192	}
193      else
194	{
195	  next = end + 1;
196	}
197      len = end - flags;
198      /* check that it is present */
199      present = 0;
200      filt = filters;
201      while (filt != NULL)
202	{
203	  if (strncmp (flags, filt->member, len) == 0
204	      && strlen (filt->member) == len)
205	    {
206	      present = 1;
207	      break;
208	    }
209	  filt = filt->next;
210	}
211      if (!present)
212	return 1;
213      flags = next;
214    }
215  return 0;
216}
217
218
219#if 0
220int
221it_is (const char *flag, const char *flags)
222{
223  int flag_len = strlen (flag);
224  while (*flags != '\0')
225    {
226      if (!strncmp (flags, flag, flag_len)
227	  && (flags[flag_len] == ',' || flags[flag_len] == '\0'))
228	return 1;
229      while (*flags != ',')
230	{
231	  if (*flags == '\0')
232	    return 0;
233	  flags++;
234	}
235      flags++;
236    }
237  return 0;
238}
239#endif
240
241
242char *
243filter_next (filter *set, char *member)
244{
245  while (set != NULL)
246    {
247      if (strcmp (set->member, member) > 0)
248	return set->member;
249      set = set->next;
250    }
251  return NULL;
252}
253
254
255void
256dump_filter (lf *file, char *prefix, filter *set, char *suffix)
257{
258  char *member;
259  lf_printf (file, "%s", prefix);
260  member = filter_next (set, "");
261  if (member != NULL)
262    {
263      while (1)
264	{
265	  lf_printf (file, "%s", member);
266	  member = filter_next (set, member);
267	  if (member == NULL)
268	    break;
269	  lf_printf (file, ",");
270	}
271    }
272  lf_printf (file, "%s", suffix);
273}
274
275
276#ifdef MAIN
277int
278main (int argc, char **argv)
279{
280  filter *subset = NULL;
281  filter *superset = NULL;
282  lf *l;
283  int i;
284  if (argc < 2)
285    {
286      printf ("Usage: filter <subset> <filter> ...\n");
287      exit (1);
288    }
289
290  /* load the filter up */
291  filter_parse (&subset, argv[1]);
292  for (i = 2; i < argc; i++)
293    filter_parse (&superset, argv[i]);
294
295  /* dump various info */
296  l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-filter");
297#if 0
298  if (is_filtered_out (argv[1], superset))
299    lf_printf (l, "excluded\n");
300  else
301    lf_printf (l, "included\n");
302#endif
303  /* subset */
304  {
305    dump_filter (l, "{", subset, " }");
306    if (filter_is_subset (superset, subset))
307      lf_printf (l, " subset of ");
308    else
309      lf_printf (l, " !subset of ");
310    dump_filter (l, "{", superset, " }");
311    lf_printf (l, "\n");
312  }
313  /* intersection */
314  {
315    dump_filter (l, "{", subset, " }");
316    if (filter_is_common (subset, superset))
317      lf_printf (l, " intersects ");
318    else
319      lf_printf (l, " !intersects ");
320    dump_filter (l, "{", superset, " }");
321    lf_printf (l, "\n");
322  }
323  /* membership */
324  {
325    filter *memb = subset;
326    while (memb != NULL)
327      {
328	lf_printf (l, "%s", memb->member);
329	if (filter_is_member (superset, memb->member))
330	  lf_printf (l, " in ");
331	else
332	  lf_printf (l, " !in ");
333	dump_filter (l, "{", superset, " }");
334	lf_printf (l, "\n");
335	memb = memb->next;
336      }
337  }
338  /* addition */
339  {
340    filter *add = NULL;
341    filter_add (&add, superset);
342    filter_add (&add, subset);
343    dump_filter (l, "{", add, " }");
344    lf_printf (l, " = ");
345    dump_filter (l, "{", subset, " }");
346    lf_printf (l, " + ");
347    dump_filter (l, "{", superset, " }");
348    lf_printf (l, "\n");
349  }
350
351  return 0;
352}
353#endif
354