* Usability improvement
[binutils-gdb.git] / gprof / sym_ids.c
blob8bde3b9d5d6aa231a35246cac72f9378b89c5cdd
1 /* sym_ids.c
3 Copyright (C) 2000 Free Software Foundation, Inc.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
22 #include <ctype.h>
24 #include "libiberty.h"
25 #include "cg_arcs.h"
26 #include "sym_ids.h"
28 struct sym_id
30 struct sym_id *next;
31 char *spec; /* Parsing modifies this. */
32 Table_Id which_table;
33 bool has_right;
35 struct match
37 int prev_index; /* Index of prev match. */
38 Sym *prev_match; /* Previous match. */
39 Sym *first_match; /* Chain of all matches. */
40 Sym sym;
42 left, right;
44 *id_list;
46 Sym_Table syms[NUM_TABLES];
48 #ifdef DEBUG
49 const char *table_name[] =
51 "INCL_GRAPH", "EXCL_GRAPH",
52 "INCL_ARCS", "EXCL_ARCS",
53 "INCL_FLAT", "EXCL_FLAT",
54 "INCL_TIME", "EXCL_TIME",
55 "INCL_ANNO", "EXCL_ANNO",
56 "INCL_EXEC", "EXCL_EXEC"
58 #endif /* DEBUG */
60 /* This is the table in which we keep all the syms that match
61 the right half of an arc id. It is NOT sorted according
62 to the addresses, because it is accessed only through
63 the left half's CHILDREN pointers (so it's crucial not
64 to reorder this table once pointers into it exist). */
65 static Sym_Table right_ids;
67 static Source_File non_existent_file =
69 0, "<non-existent-file>", 0, 0, 0, NULL
73 void
74 DEFUN (sym_id_add, (spec, which_table),
75 const char *spec AND Table_Id which_table)
77 struct sym_id *id;
78 int len = strlen (spec);
80 id = (struct sym_id *) xmalloc (sizeof (*id) + len + 1);
81 memset (id, 0, sizeof (*id));
83 id->spec = (char *) id + sizeof (*id);
84 strcpy (id->spec, spec);
85 id->which_table = which_table;
87 id->next = id_list;
88 id_list = id;
92 /* A spec has the syntax FILENAME:(FUNCNAME|LINENUM). As a convenience
93 to the user, a spec without a colon is interpreted as:
95 (i) a FILENAME if it contains a dot
96 (ii) a FUNCNAME if it starts with a non-digit character
97 (iii) a LINENUM if it starts with a digit
99 A FUNCNAME containing a dot can be specified by :FUNCNAME, a
100 FILENAME not containing a dot can be specified by FILENAME. */
102 static void
103 DEFUN (parse_spec, (spec, sym), char *spec AND Sym * sym)
105 char *colon;
107 sym_init (sym);
108 colon = strrchr (spec, ':');
110 if (colon)
112 *colon = '\0';
114 if (colon > spec)
116 sym->file = source_file_lookup_name (spec);
118 if (!sym->file)
119 sym->file = &non_existent_file;
122 spec = colon + 1;
124 if (strlen (spec))
126 if (isdigit ((unsigned char) spec[0]))
127 sym->line_num = atoi (spec);
128 else
129 sym->name = spec;
132 else if (strlen (spec))
134 /* No colon: spec is a filename if it contains a dot. */
135 if (strchr (spec, '.'))
137 sym->file = source_file_lookup_name (spec);
139 if (!sym->file)
140 sym->file = &non_existent_file;
142 else if (isdigit ((unsigned char) *spec))
144 sym->line_num = atoi (spec);
146 else if (strlen (spec))
148 sym->name = spec;
154 /* A symbol id has the syntax SPEC[/SPEC], where SPEC is is defined
155 by parse_spec(). */
157 static void
158 DEFUN (parse_id, (id), struct sym_id *id)
160 char *slash;
162 DBG (IDDEBUG, printf ("[parse_id] %s -> ", id->spec));
164 slash = strchr (id->spec, '/');
165 if (slash)
167 parse_spec (slash + 1, &id->right.sym);
168 *slash = '\0';
169 id->has_right = TRUE;
171 parse_spec (id->spec, &id->left.sym);
173 #ifdef DEBUG
174 if (debug_level & IDDEBUG)
176 printf ("%s:", id->left.sym.file ? id->left.sym.file->name : "*");
178 if (id->left.sym.name)
179 printf ("%s", id->left.sym.name);
180 else if (id->left.sym.line_num)
181 printf ("%d", id->left.sym.line_num);
182 else
183 printf ("*");
185 if (id->has_right)
187 printf ("/%s:",
188 id->right.sym.file ? id->right.sym.file->name : "*");
190 if (id->right.sym.name)
191 printf ("%s", id->right.sym.name);
192 else if (id->right.sym.line_num)
193 printf ("%d", id->right.sym.line_num);
194 else
195 printf ("*");
198 printf ("\n");
200 #endif
204 /* Return TRUE iff PATTERN matches SYM. */
206 static bool
207 DEFUN (match, (pattern, sym), Sym * pattern AND Sym * sym)
209 return (pattern->file ? pattern->file == sym->file : TRUE)
210 && (pattern->line_num ? pattern->line_num == sym->line_num : TRUE)
211 && (pattern->name
212 ? strcmp (pattern->name,
213 sym->name+(discard_underscores && sym->name[0] == '_')) == 0
214 : TRUE);
218 static void
219 DEFUN (extend_match, (m, sym, tab, second_pass),
220 struct match *m AND Sym * sym AND Sym_Table * tab AND bool second_pass)
222 if (m->prev_match != sym - 1)
224 /* Discontinuity: add new match to table. */
225 if (second_pass)
227 tab->base[tab->len] = *sym;
228 m->prev_index = tab->len;
230 /* Link match into match's chain. */
231 tab->base[tab->len].next = m->first_match;
232 m->first_match = &tab->base[tab->len];
235 ++tab->len;
238 /* Extend match to include this symbol. */
239 if (second_pass)
240 tab->base[m->prev_index].end_addr = sym->end_addr;
242 m->prev_match = sym;
246 /* Go through sym_id list produced by option processing and fill
247 in the various symbol tables indicating what symbols should
248 be displayed or suppressed for the various kinds of outputs.
250 This can potentially produce huge tables and in particulars
251 tons of arcs, but this happens only if the user makes silly
252 requests---you get what you ask for! */
254 void
255 DEFUN_VOID (sym_id_parse)
257 Sym *sym, *left, *right;
258 struct sym_id *id;
259 Sym_Table *tab;
261 /* Convert symbol ids into Syms, so we can deal with them more easily. */
262 for (id = id_list; id; id = id->next)
263 parse_id (id);
265 /* First determine size of each table. */
266 for (sym = symtab.base; sym < symtab.limit; ++sym)
268 for (id = id_list; id; id = id->next)
270 if (match (&id->left.sym, sym))
271 extend_match (&id->left, sym, &syms[id->which_table], FALSE);
273 if (id->has_right && match (&id->right.sym, sym))
274 extend_match (&id->right, sym, &right_ids, FALSE);
278 /* Create tables of appropriate size and reset lengths. */
279 for (tab = syms; tab < &syms[NUM_TABLES]; ++tab)
281 if (tab->len)
283 tab->base = (Sym *) xmalloc (tab->len * sizeof (Sym));
284 tab->limit = tab->base + tab->len;
285 tab->len = 0;
289 if (right_ids.len)
291 right_ids.base = (Sym *) xmalloc (right_ids.len * sizeof (Sym));
292 right_ids.limit = right_ids.base + right_ids.len;
293 right_ids.len = 0;
296 /* Make a second pass through symtab, creating syms as necessary. */
297 for (sym = symtab.base; sym < symtab.limit; ++sym)
299 for (id = id_list; id; id = id->next)
301 if (match (&id->left.sym, sym))
302 extend_match (&id->left, sym, &syms[id->which_table], TRUE);
304 if (id->has_right && match (&id->right.sym, sym))
305 extend_match (&id->right, sym, &right_ids, TRUE);
309 /* Go through ids creating arcs as needed. */
310 for (id = id_list; id; id = id->next)
312 if (id->has_right)
314 for (left = id->left.first_match; left; left = left->next)
316 for (right = id->right.first_match; right; right = right->next)
318 DBG (IDDEBUG,
319 printf (
320 "[sym_id_parse]: arc %s:%s(%lx-%lx) -> %s:%s(%lx-%lx) to %s\n",
321 left->file ? left->file->name : "*",
322 left->name ? left->name : "*",
323 (unsigned long) left->addr,
324 (unsigned long) left->end_addr,
325 right->file ? right->file->name : "*",
326 right->name ? right->name : "*",
327 (unsigned long) right->addr,
328 (unsigned long) right->end_addr,
329 table_name[id->which_table]));
331 arc_add (left, right, (unsigned long) 0);
337 /* Finally, we can sort the tables and we're done. */
338 for (tab = &syms[0]; tab < &syms[NUM_TABLES]; ++tab)
340 DBG (IDDEBUG, printf ("[sym_id_parse] syms[%s]:\n",
341 table_name[tab - &syms[0]]));
342 symtab_finalize (tab);
347 /* Symbol tables storing the FROM symbols of arcs do not necessarily
348 have distinct address ranges. For example, somebody might request
349 -k /_mcount to suppress any arcs into _mcount, while at the same
350 time requesting -k a/b. Fortunately, those symbol tables don't get
351 very big (the user has to type them!), so a linear search is probably
352 tolerable. */
353 bool
354 DEFUN (sym_id_arc_is_present, (symtab, from, to),
355 Sym_Table * symtab AND Sym * from AND Sym * to)
357 Sym *sym;
359 for (sym = symtab->base; sym < symtab->limit; ++sym)
361 if (from->addr >= sym->addr && from->addr <= sym->end_addr
362 && arc_lookup (sym, to))
363 return TRUE;
366 return FALSE;