8 char *spec
; /* parsing modifies this */
13 int prev_index
; /* index of prev match */
14 Sym
*prev_match
; /* previous match */
15 Sym
*first_match
; /* chain of all matches */
22 Sym_Table syms
[NUM_TABLES
];
25 const char *table_name
[] =
27 "INCL_GRAPH", "EXCL_GRAPH",
28 "INCL_ARCS", "EXCL_ARCS",
29 "INCL_FLAT", "EXCL_FLAT",
30 "INCL_TIME", "EXCL_TIME",
31 "INCL_ANNO", "EXCL_ANNO",
32 "INCL_EXEC", "EXCL_EXEC"
37 * This is the table in which we keep all the syms that match
38 * the right half of an arc id. It is NOT sorted according
39 * to the addresses, because it is accessed only through
40 * the left half's CHILDREN pointers (so it's crucial not
41 * to reorder this table once pointers into it exist).
43 static Sym_Table right_ids
;
45 static Source_File non_existent_file
=
47 0, "<non-existent-file>"
52 DEFUN (sym_id_add
, (spec
, which_table
),
53 const char *spec AND Table_Id which_table
)
56 int len
= strlen (spec
);
58 id
= (struct sym_id
*) xmalloc (sizeof (*id
) + len
+ 1);
59 memset (id
, 0, sizeof (*id
));
61 id
->spec
= (char *) id
+ sizeof (*id
);
62 strcpy (id
->spec
, spec
);
63 id
->which_table
= which_table
;
71 * A spec has the syntax FILENAME:(FUNCNAME|LINENUM). As a convenience
72 * to the user, a spec without a colon is interpreted as:
74 * (i) a FILENAME if it contains a dot
75 * (ii) a FUNCNAME if it starts with a non-digit character
76 * (iii) a LINENUM if it starts with a digit
78 * A FUNCNAME containing a dot can be specified by :FUNCNAME, a
79 * FILENAME not containing a dot can be specified by FILENAME:.
82 DEFUN (parse_spec
, (spec
, sym
), char *spec AND Sym
* sym
)
87 colon
= strrchr (spec
, ':');
93 sym
->file
= source_file_lookup_name (spec
);
96 sym
->file
= &non_existent_file
;
102 if (isdigit (spec
[0]))
104 sym
->line_num
= atoi (spec
);
112 else if (strlen (spec
))
114 /* no colon: spec is a filename if it contains a dot: */
115 if (strchr (spec
, '.'))
117 sym
->file
= source_file_lookup_name (spec
);
120 sym
->file
= &non_existent_file
;
123 else if (isdigit (*spec
))
125 sym
->line_num
= atoi (spec
);
127 else if (strlen (spec
))
136 * A symbol id has the syntax SPEC[/SPEC], where SPEC is is defined
140 DEFUN (parse_id
, (id
), struct sym_id
*id
)
144 DBG (IDDEBUG
, printf ("[parse_id] %s -> ", id
->spec
));
146 slash
= strchr (id
->spec
, '/');
149 parse_spec (slash
+ 1, &id
->right
.sym
);
151 id
->has_right
= TRUE
;
153 parse_spec (id
->spec
, &id
->left
.sym
);
156 if (debug_level
& IDDEBUG
)
158 printf ("%s:", id
->left
.sym
.file
? id
->left
.sym
.file
->name
: "*");
159 if (id
->left
.sym
.name
)
161 printf ("%s", id
->left
.sym
.name
);
163 else if (id
->left
.sym
.line_num
)
165 printf ("%d", id
->left
.sym
.line_num
);
174 id
->right
.sym
.file
? id
->right
.sym
.file
->name
: "*");
175 if (id
->right
.sym
.name
)
177 printf ("%s", id
->right
.sym
.name
);
179 else if (id
->right
.sym
.line_num
)
181 printf ("%d", id
->right
.sym
.line_num
);
195 * Return TRUE iff PATTERN matches SYM.
198 DEFUN (match
, (pattern
, sym
), Sym
* pattern AND Sym
* sym
)
200 return (pattern
->file
? pattern
->file
== sym
->file
: TRUE
)
201 && (pattern
->line_num
? pattern
->line_num
== sym
->line_num
: TRUE
)
202 && (pattern
->name
? strcmp (pattern
->name
, sym
->name
) == 0 : TRUE
);
207 DEFUN (extend_match
, (m
, sym
, tab
, second_pass
),
208 struct match
*m AND Sym
* sym AND Sym_Table
* tab AND
bool second_pass
)
210 if (m
->prev_match
!= sym
- 1)
212 /* discontinuity: add new match to table: */
215 tab
->base
[tab
->len
] = *sym
;
216 m
->prev_index
= tab
->len
;
218 /* link match into match's chain: */
219 tab
->base
[tab
->len
].next
= m
->first_match
;
220 m
->first_match
= &tab
->base
[tab
->len
];
225 /* extend match to include this symbol: */
228 tab
->base
[m
->prev_index
].end_addr
= sym
->end_addr
;
235 * Go through sym_id list produced by option processing and fill
236 * in the various symbol tables indicating what symbols should
237 * be displayed or suppressed for the various kinds of outputs.
239 * This can potentially produce huge tables and in particulars
240 * tons of arcs, but this happens only if the user makes silly
241 * requests---you get what you ask for!
244 DEFUN_VOID (sym_id_parse
)
246 Sym
*sym
, *left
, *right
;
251 * Convert symbol ids into Syms, so we can deal with them more easily:
253 for (id
= id_list
; id
; id
= id
->next
)
258 /* first determine size of each table: */
260 for (sym
= symtab
.base
; sym
< symtab
.limit
; ++sym
)
262 for (id
= id_list
; id
; id
= id
->next
)
264 if (match (&id
->left
.sym
, sym
))
266 extend_match (&id
->left
, sym
, &syms
[id
->which_table
], FALSE
);
268 if (id
->has_right
&& match (&id
->right
.sym
, sym
))
270 extend_match (&id
->right
, sym
, &right_ids
, FALSE
);
275 /* create tables of appropriate size and reset lengths: */
277 for (tab
= syms
; tab
< &syms
[NUM_TABLES
]; ++tab
)
281 tab
->base
= (Sym
*) xmalloc (tab
->len
* sizeof (Sym
));
282 tab
->limit
= tab
->base
+ tab
->len
;
288 right_ids
.base
= (Sym
*) xmalloc (right_ids
.len
* sizeof (Sym
));
289 right_ids
.limit
= right_ids
.base
+ right_ids
.len
;
293 /* make a second pass through symtab, creating syms as necessary: */
295 for (sym
= symtab
.base
; sym
< symtab
.limit
; ++sym
)
297 for (id
= id_list
; id
; id
= id
->next
)
299 if (match (&id
->left
.sym
, sym
))
301 extend_match (&id
->left
, sym
, &syms
[id
->which_table
], TRUE
);
303 if (id
->has_right
&& match (&id
->right
.sym
, sym
))
305 extend_match (&id
->right
, sym
, &right_ids
, TRUE
);
310 /* go through ids creating arcs as needed: */
312 for (id
= id_list
; id
; id
= id
->next
)
316 for (left
= id
->left
.first_match
; left
; left
= left
->next
)
318 for (right
= id
->right
.first_match
; right
; right
= right
->next
)
322 "[sym_id_parse]: arc %s:%s(%lx-%lx) -> %s:%s(%lx-%lx) to %s\n",
323 left
->file
? left
->file
->name
: "*",
324 left
->name
? left
->name
: "*", left
->addr
,
326 right
->file
? right
->file
->name
: "*",
327 right
->name
? right
->name
: "*", right
->addr
,
329 table_name
[id
->which_table
]));
330 arc_add (left
, right
, 0);
336 /* 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
);
348 * Symbol tables storing the FROM symbols of arcs do not necessarily
349 * have distinct address ranges. For example, somebody might request
350 * -k /_mcount to suppress any arcs into _mcount, while at the same
351 * time requesting -k a/b. Fortunately, those symbol tables don't get
352 * very big (the user has to type them!), so a linear search is probably
356 DEFUN (sym_id_arc_is_present
, (symtab
, from
, to
),
357 Sym_Table
* symtab AND Sym
* from AND Sym
* to
)
361 for (sym
= symtab
->base
; sym
< symtab
->limit
; ++sym
)
363 if (from
->addr
>= sym
->addr
&& from
->addr
<= sym
->end_addr
364 && arc_lookup (sym
, to
))