7 char *spec; /* parsing modifies this */
11 int prev_index; /* index of prev match */
12 Sym *prev_match; /* previous match */
13 Sym *first_match; /* chain of all matches */
18 Sym_Table syms[NUM_TABLES];
21 const char *table_name[] = {
22 "INCL_GRAPH", "EXCL_GRAPH",
23 "INCL_ARCS", "EXCL_ARCS",
24 "INCL_FLAT", "EXCL_FLAT",
25 "INCL_TIME", "EXCL_TIME",
26 "INCL_ANNO", "EXCL_ANNO",
27 "INCL_EXEC", "EXCL_EXEC"
32 * This is the table in which we keep all the syms that match
33 * the right half of an arc id. It is NOT sorted according
34 * to the addresses, because it is accessed only through
35 * the left half's CHILDREN pointers (so it's crucial not
36 * to reorder this table once pointers into it exist).
38 static Sym_Table right_ids;
40 static Source_File non_existent_file = {
41 0, "<non-existent-file>"
46 DEFUN(sym_id_add, (spec, which_table),
47 const char *spec AND Table_Id which_table)
50 int len = strlen(spec);
52 id = (struct sym_id*) xmalloc(sizeof(*id) + len + 1);
53 memset(id, 0, sizeof(*id));
55 id->spec = (char*)id + sizeof(*id);
56 strcpy(id->spec, spec);
57 id->which_table = which_table;
65 * A spec has the syntax FILENAME:(FUNCNAME|LINENUM). As a convenience
66 * to the user, a spec without a colon is interpreted as:
68 * (i) a FILENAME if it contains a dot
69 * (ii) a FUNCNAME if it starts with a non-digit character
70 * (iii) a LINENUM if it starts with a digit
72 * A FUNCNAME containing a dot can be specified by :FUNCNAME, a
73 * FILENAME not containing a dot can be specified by FILENAME:.
76 DEFUN(parse_spec, (spec, sym), char *spec AND Sym *sym)
81 colon = strrchr(spec, ':');
85 sym->file = source_file_lookup_name(spec);
87 sym->file = &non_existent_file;
92 if (isdigit(spec[0])) {
93 sym->line_num = atoi(spec);
98 } else if (strlen(spec)) {
99 /* no colon: spec is a filename if it contains a dot: */
100 if (strchr(spec, '.')) {
101 sym->file = source_file_lookup_name(spec);
103 sym->file = &non_existent_file;
105 } else if (isdigit(*spec)) {
106 sym->line_num = atoi(spec);
107 } else if (strlen(spec)) {
115 * A symbol id has the syntax SPEC[/SPEC], where SPEC is is defined
119 DEFUN(parse_id, (id), struct sym_id *id)
123 DBG(IDDEBUG, printf("[parse_id] %s -> ", id->spec));
125 slash = strchr(id->spec, '/');
127 parse_spec(slash + 1, &id->right.sym);
129 id->has_right = TRUE;
131 parse_spec(id->spec, &id->left.sym);
134 printf("%s:", id->left.sym.file ? id->left.sym.file->name : "*");
135 if (id->left.sym.name) {
136 printf("%s", id->left.sym.name);
137 } else if (id->left.sym.line_num) {
138 printf("%d", id->left.sym.line_num);
144 id->right.sym.file ? id->right.sym.file->name : "*");
145 if (id->right.sym.name) {
146 printf("%s", id->right.sym.name);
147 } else if (id->right.sym.line_num) {
148 printf("%d", id->right.sym.line_num);
158 * Return TRUE iff PATTERN matches SYM.
161 DEFUN(match, (pattern, sym), Sym *pattern AND Sym *sym)
163 return (pattern->file ? pattern->file == sym->file : TRUE)
164 && (pattern->line_num ? pattern->line_num == sym->line_num : TRUE)
165 && (pattern->name ? strcmp(pattern->name, sym->name) == 0 : TRUE);
170 DEFUN(extend_match, (m, sym, tab, second_pass),
171 struct match *m AND Sym *sym AND Sym_Table *tab AND bool second_pass)
173 if (m->prev_match != sym - 1) {
174 /* discontinuity: add new match to table: */
176 tab->base[tab->len] = *sym;
177 m->prev_index = tab->len;
179 /* link match into match's chain: */
180 tab->base[tab->len].next = m->first_match;
181 m->first_match = &tab->base[tab->len];
186 /* extend match to include this symbol: */
188 tab->base[m->prev_index].end_addr = sym->end_addr;
195 * Go through sym_id list produced by option processing and fill
196 * in the various symbol tables indicating what symbols should
197 * be displayed or suppressed for the various kinds of outputs.
199 * This can potentially produce huge tables and in particulars
200 * tons of arcs, but this happens only if the user makes silly
201 * requests---you get what you ask for!
204 DEFUN_VOID(sym_id_parse)
206 Sym *sym, *left, *right;
211 * Convert symbol ids into Syms, so we can deal with them more easily:
213 for (id = id_list; id; id = id->next) {
217 /* first determine size of each table: */
219 for (sym = symtab.base; sym < symtab.limit; ++sym) {
220 for (id = id_list; id; id = id->next) {
221 if (match(&id->left.sym, sym)) {
222 extend_match(&id->left, sym, &syms[id->which_table], FALSE);
224 if (id->has_right && match(&id->right.sym, sym)) {
225 extend_match(&id->right, sym, &right_ids, FALSE);
230 /* create tables of appropriate size and reset lengths: */
232 for (tab = syms; tab < &syms[NUM_TABLES]; ++tab) {
234 tab->base = (Sym*) xmalloc(tab->len * sizeof(Sym));
235 tab->limit = tab->base + tab->len;
240 right_ids.base = (Sym*) xmalloc(right_ids.len * sizeof(Sym));
241 right_ids.limit = right_ids.base + right_ids.len;
245 /* make a second pass through symtab, creating syms as necessary: */
247 for (sym = symtab.base; sym < symtab.limit; ++sym) {
248 for (id = id_list; id; id = id->next) {
249 if (match(&id->left.sym, sym)) {
250 extend_match(&id->left, sym, &syms[id->which_table], TRUE);
252 if (id->has_right && match(&id->right.sym, sym)) {
253 extend_match(&id->right, sym, &right_ids, TRUE);
258 /* go through ids creating arcs as needed: */
260 for (id = id_list; id; id = id->next) {
262 for (left = id->left.first_match; left; left = left->next) {
263 for (right = id->right.first_match; right; right = right->next)
267 "[sym_id_parse]: arc %s:%s(%lx-%lx) -> %s:%s(%lx-%lx) to %s\n",
268 left->file ? left->file->name : "*",
269 left->name ? left->name : "*", left->addr,
271 right->file ? right->file->name : "*",
272 right->name ? right->name : "*", right->addr,
274 table_name[id->which_table]));
275 arc_add(left, right, 0);
281 /* finally, we can sort the tables and we're done: */
283 for (tab = &syms[0]; tab < &syms[NUM_TABLES]; ++tab) {
284 DBG(IDDEBUG, printf("[sym_id_parse] syms[%s]:\n",
285 table_name[tab - &syms[0]]));
286 symtab_finalize(tab);
292 * Symbol tables storing the FROM symbols of arcs do not necessarily
293 * have distinct address ranges. For example, somebody might request
294 * -k /_mcount to suppress any arcs into _mcount, while at the same
295 * time requesting -k a/b. Fortunately, those symbol tables don't get
296 * very big (the user has to type them!), so a linear search is probably
300 DEFUN(sym_id_arc_is_present, (symtab, from, to),
301 Sym_Table *symtab AND Sym *from AND Sym *to)
305 for (sym = symtab->base; sym < symtab->limit; ++sym) {
306 if (from->addr >= sym->addr && from->addr <= sym->end_addr
307 && arc_lookup(sym, to))
313 } /* sym_id_arc_is_present */
315 /*** end of sym_ids.h ***/