| /* The IGEN simulator generator for GDB, the GNU Debugger. | |
| Copyright 2002-2022 Free Software Foundation, Inc. | |
| Contributed by Andrew Cagney. | |
| This file is part of GDB. | |
| This program is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 3 of the License, or | |
| (at your option) any later version. | |
| This program is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include "misc.h" | |
| #include "lf.h" | |
| #include "filter.h" | |
| struct _filter | |
| { | |
| char *member; | |
| filter *next; | |
| }; | |
| void | |
| filter_parse (filter **filters, const char *filt) | |
| { | |
| while (strlen (filt) > 0) | |
| { | |
| filter *new_filter; | |
| filter **last; | |
| /* break out a member of the filter list */ | |
| const char *flag = filt; | |
| unsigned /*size_t */ len; | |
| filt = strchr (filt, ','); | |
| if (filt == NULL) | |
| { | |
| filt = strchr (flag, '\0'); | |
| len = strlen (flag); | |
| } | |
| else | |
| { | |
| len = filt - flag; | |
| filt = filt + 1; | |
| } | |
| /* find an insertion point - sorted order */ | |
| last = filters; | |
| while (*last != NULL && strncmp (flag, (*last)->member, len) > 0) | |
| last = &(*last)->next; | |
| if (*last != NULL | |
| && strncmp (flag, (*last)->member, len) == 0 | |
| && strlen ((*last)->member) == len) | |
| continue; /* duplicate */ | |
| /* create an entry for that member */ | |
| new_filter = ZALLOC (filter); | |
| new_filter->member = NZALLOC (char, len + 1); | |
| strncpy (new_filter->member, flag, len); | |
| /* insert it */ | |
| new_filter->next = *last; | |
| *last = new_filter; | |
| } | |
| } | |
| void | |
| filter_add (filter **set, filter *add) | |
| { | |
| while (add != NULL) | |
| { | |
| int cmp; | |
| if (*set == NULL) | |
| cmp = 1; /* set->member > add->member */ | |
| else | |
| cmp = strcmp ((*set)->member, add->member); | |
| if (cmp > 0) | |
| { | |
| /* insert it here */ | |
| filter *new = ZALLOC (filter); | |
| new->member = NZALLOC (char, strlen (add->member) + 1); | |
| strcpy (new->member, add->member); | |
| new->next = *set; | |
| *set = new; | |
| add = add->next; | |
| } | |
| else if (cmp == 0) | |
| { | |
| /* already in set */ | |
| add = add->next; | |
| } | |
| else /* cmp < 0 */ | |
| { | |
| /* not reached insertion point */ | |
| set = &(*set)->next; | |
| } | |
| } | |
| } | |
| int | |
| filter_is_subset (filter *superset, filter *subset) | |
| { | |
| while (1) | |
| { | |
| int cmp; | |
| if (subset == NULL) | |
| return 1; | |
| if (superset == NULL) | |
| return 0; /* subset isn't finished */ | |
| cmp = strcmp (subset->member, superset->member); | |
| if (cmp < 0) | |
| return 0; /* not found */ | |
| else if (cmp == 0) | |
| subset = subset->next; /* found */ | |
| else if (cmp > 0) | |
| superset = superset->next; /* later in list? */ | |
| } | |
| } | |
| int | |
| filter_is_common (filter *l, filter *r) | |
| { | |
| while (1) | |
| { | |
| int cmp; | |
| if (l == NULL) | |
| return 0; | |
| if (r == NULL) | |
| return 0; | |
| cmp = strcmp (l->member, r->member); | |
| if (cmp < 0) | |
| l = l->next; | |
| else if (cmp == 0) | |
| return 1; /* common member */ | |
| else if (cmp > 0) | |
| r = r->next; | |
| } | |
| } | |
| int | |
| filter_is_member (filter *filt, const char *flag) | |
| { | |
| int index = 1; | |
| while (filt != NULL) | |
| { | |
| if (strcmp (flag, filt->member) == 0) | |
| return index; | |
| filt = filt->next; | |
| index++; | |
| } | |
| return 0; | |
| } | |
| int | |
| is_filtered_out (filter *filters, const char *flags) | |
| { | |
| while (strlen (flags) > 0) | |
| { | |
| int present; | |
| filter *filt = filters; | |
| /* break the string up */ | |
| char *end = strchr (flags, ','); | |
| char *next; | |
| unsigned /*size_t */ len; | |
| if (end == NULL) | |
| { | |
| end = strchr (flags, '\0'); | |
| next = end; | |
| } | |
| else | |
| { | |
| next = end + 1; | |
| } | |
| len = end - flags; | |
| /* check that it is present */ | |
| present = 0; | |
| filt = filters; | |
| while (filt != NULL) | |
| { | |
| if (strncmp (flags, filt->member, len) == 0 | |
| && strlen (filt->member) == len) | |
| { | |
| present = 1; | |
| break; | |
| } | |
| filt = filt->next; | |
| } | |
| if (!present) | |
| return 1; | |
| flags = next; | |
| } | |
| return 0; | |
| } | |
| char * | |
| filter_next (filter *set, char *member) | |
| { | |
| while (set != NULL) | |
| { | |
| if (strcmp (set->member, member) > 0) | |
| return set->member; | |
| set = set->next; | |
| } | |
| return NULL; | |
| } | |
| void | |
| dump_filter (lf *file, char *prefix, filter *set, char *suffix) | |
| { | |
| char *member; | |
| lf_printf (file, "%s", prefix); | |
| member = filter_next (set, ""); | |
| if (member != NULL) | |
| { | |
| while (1) | |
| { | |
| lf_printf (file, "%s", member); | |
| member = filter_next (set, member); | |
| if (member == NULL) | |
| break; | |
| lf_printf (file, ","); | |
| } | |
| } | |
| lf_printf (file, "%s", suffix); | |
| } | |
| #ifdef MAIN | |
| int | |
| main (int argc, char **argv) | |
| { | |
| filter *subset = NULL; | |
| filter *superset = NULL; | |
| lf *l; | |
| int i; | |
| if (argc < 2) | |
| { | |
| printf ("Usage: filter <subset> <filter> ...\n"); | |
| exit (1); | |
| } | |
| /* load the filter up */ | |
| filter_parse (&subset, argv[1]); | |
| for (i = 2; i < argc; i++) | |
| filter_parse (&superset, argv[i]); | |
| /* dump various info */ | |
| l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-filter"); | |
| /* subset */ | |
| { | |
| dump_filter (l, "{", subset, " }"); | |
| if (filter_is_subset (superset, subset)) | |
| lf_printf (l, " subset of "); | |
| else | |
| lf_printf (l, " !subset of "); | |
| dump_filter (l, "{", superset, " }"); | |
| lf_printf (l, "\n"); | |
| } | |
| /* intersection */ | |
| { | |
| dump_filter (l, "{", subset, " }"); | |
| if (filter_is_common (subset, superset)) | |
| lf_printf (l, " intersects "); | |
| else | |
| lf_printf (l, " !intersects "); | |
| dump_filter (l, "{", superset, " }"); | |
| lf_printf (l, "\n"); | |
| } | |
| /* membership */ | |
| { | |
| filter *memb = subset; | |
| while (memb != NULL) | |
| { | |
| lf_printf (l, "%s", memb->member); | |
| if (filter_is_member (superset, memb->member)) | |
| lf_printf (l, " in "); | |
| else | |
| lf_printf (l, " !in "); | |
| dump_filter (l, "{", superset, " }"); | |
| lf_printf (l, "\n"); | |
| memb = memb->next; | |
| } | |
| } | |
| /* addition */ | |
| { | |
| filter *add = NULL; | |
| filter_add (&add, superset); | |
| filter_add (&add, subset); | |
| dump_filter (l, "{", add, " }"); | |
| lf_printf (l, " = "); | |
| dump_filter (l, "{", subset, " }"); | |
| lf_printf (l, " + "); | |
| dump_filter (l, "{", superset, " }"); | |
| lf_printf (l, "\n"); | |
| } | |
| return 0; | |
| } | |
| #endif |