10 char *spec
; /* parsing modifies this */
15 int prev_index
; /* index of prev match */
16 Sym
*prev_match
; /* previous match */
17 Sym
*first_match
; /* chain of all matches */
24 Sym_Table syms
[NUM_TABLES
];
27 const char *table_name
[] =
29 "INCL_GRAPH", "EXCL_GRAPH",
30 "INCL_ARCS", "EXCL_ARCS",
31 "INCL_FLAT", "EXCL_FLAT",
32 "INCL_TIME", "EXCL_TIME",
33 "INCL_ANNO", "EXCL_ANNO",
34 "INCL_EXEC", "EXCL_EXEC"
39 * This is the table in which we keep all the syms that match
40 * the right half of an arc id. It is NOT sorted according
41 * to the addresses, because it is accessed only through
42 * the left half's CHILDREN pointers (so it's crucial not
43 * to reorder this table once pointers into it exist).
45 static Sym_Table right_ids
;
47 static Source_File non_existent_file
=
49 0, "<non-existent-file>"
54 DEFUN (sym_id_add
, (spec
, which_table
),
55 const char *spec AND Table_Id which_table
)
58 int len
= strlen (spec
);
60 id
= (struct sym_id
*) xmalloc (sizeof (*id
) + len
+ 1);
61 memset (id
, 0, sizeof (*id
));
63 id
->spec
= (char *) id
+ sizeof (*id
);
64 strcpy (id
->spec
, spec
);
65 id
->which_table
= which_table
;
73 * A spec has the syntax FILENAME:(FUNCNAME|LINENUM). As a convenience
74 * to the user, a spec without a colon is interpreted as:
76 * (i) a FILENAME if it contains a dot
77 * (ii) a FUNCNAME if it starts with a non-digit character
78 * (iii) a LINENUM if it starts with a digit
80 * A FUNCNAME containing a dot can be specified by :FUNCNAME, a
81 * FILENAME not containing a dot can be specified by FILENAME:.
84 DEFUN (parse_spec
, (spec
, sym
), char *spec AND Sym
* sym
)
89 colon
= strrchr (spec
, ':');
95 sym
->file
= source_file_lookup_name (spec
);
98 sym
->file
= &non_existent_file
;
104 if (isdigit (spec
[0]))
106 sym
->line_num
= atoi (spec
);
114 else if (strlen (spec
))
116 /* no colon: spec is a filename if it contains a dot: */
117 if (strchr (spec
, '.'))
119 sym
->file
= source_file_lookup_name (spec
);
122 sym
->file
= &non_existent_file
;
125 else if (isdigit (*spec
))
127 sym
->line_num
= atoi (spec
);
129 else if (strlen (spec
))
138 * A symbol id has the syntax SPEC[/SPEC], where SPEC is is defined
142 DEFUN (parse_id
, (id
), struct sym_id
*id
)
146 DBG (IDDEBUG
, printf ("[parse_id] %s -> ", id
->spec
));
148 slash
= strchr (id
->spec
, '/');
151 parse_spec (slash
+ 1, &id
->right
.sym
);
153 id
->has_right
= TRUE
;
155 parse_spec (id
->spec
, &id
->left
.sym
);
158 if (debug_level
& IDDEBUG
)
160 printf ("%s:", id
->left
.sym
.file
? id
->left
.sym
.file
->name
: "*");
161 if (id
->left
.sym
.name
)
163 printf ("%s", id
->left
.sym
.name
);
165 else if (id
->left
.sym
.line_num
)
167 printf ("%d", id
->left
.sym
.line_num
);
176 id
->right
.sym
.file
? id
->right
.sym
.file
->name
: "*");
177 if (id
->right
.sym
.name
)
179 printf ("%s", id
->right
.sym
.name
);
181 else if (id
->right
.sym
.line_num
)
183 printf ("%d", id
->right
.sym
.line_num
);
197 * Return TRUE iff PATTERN matches SYM.
200 DEFUN (match
, (pattern
, sym
), Sym
* pattern AND Sym
* sym
)
202 return (pattern
->file
? pattern
->file
== sym
->file
: TRUE
)
203 && (pattern
->line_num
? pattern
->line_num
== sym
->line_num
: TRUE
)
204 && (pattern
->name
? strcmp (pattern
->name
, sym
->name
) == 0 : TRUE
);
209 DEFUN (extend_match
, (m
, sym
, tab
, second_pass
),
210 struct match
*m AND Sym
* sym AND Sym_Table
* tab AND
bool second_pass
)
212 if (m
->prev_match
!= sym
- 1)
214 /* discontinuity: add new match to table: */
217 tab
->base
[tab
->len
] = *sym
;
218 m
->prev_index
= tab
->len
;
220 /* link match into match's chain: */
221 tab
->base
[tab
->len
].next
= m
->first_match
;
222 m
->first_match
= &tab
->base
[tab
->len
];
227 /* extend match to include this symbol: */
230 tab
->base
[m
->prev_index
].end_addr
= sym
->end_addr
;
237 * Go through sym_id list produced by option processing and fill
238 * in the various symbol tables indicating what symbols should
239 * be displayed or suppressed for the various kinds of outputs.
241 * This can potentially produce huge tables and in particulars
242 * tons of arcs, but this happens only if the user makes silly
243 * requests---you get what you ask for!
246 DEFUN_VOID (sym_id_parse
)
248 Sym
*sym
, *left
, *right
;
253 * Convert symbol ids into Syms, so we can deal with them more easily:
255 for (id
= id_list
; id
; id
= id
->next
)
260 /* first determine size of each table: */
262 for (sym
= symtab
.base
; sym
< symtab
.limit
; ++sym
)
264 for (id
= id_list
; id
; id
= id
->next
)
266 if (match (&id
->left
.sym
, sym
))
268 extend_match (&id
->left
, sym
, &syms
[id
->which_table
], FALSE
);
270 if (id
->has_right
&& match (&id
->right
.sym
, sym
))
272 extend_match (&id
->right
, sym
, &right_ids
, FALSE
);
277 /* create tables of appropriate size and reset lengths: */
279 for (tab
= syms
; tab
< &syms
[NUM_TABLES
]; ++tab
)
283 tab
->base
= (Sym
*) xmalloc (tab
->len
* sizeof (Sym
));
284 tab
->limit
= tab
->base
+ tab
->len
;
290 right_ids
.base
= (Sym
*) xmalloc (right_ids
.len
* sizeof (Sym
));
291 right_ids
.limit
= right_ids
.base
+ right_ids
.len
;
295 /* 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
))
303 extend_match (&id
->left
, sym
, &syms
[id
->which_table
], TRUE
);
305 if (id
->has_right
&& match (&id
->right
.sym
, sym
))
307 extend_match (&id
->right
, sym
, &right_ids
, TRUE
);
312 /* go through ids creating arcs as needed: */
314 for (id
= id_list
; id
; id
= id
->next
)
318 for (left
= id
->left
.first_match
; left
; left
= left
->next
)
320 for (right
= id
->right
.first_match
; right
; right
= right
->next
)
324 "[sym_id_parse]: arc %s:%s(%lx-%lx) -> %s:%s(%lx-%lx) to %s\n",
325 left
->file
? left
->file
->name
: "*",
326 left
->name
? left
->name
: "*", left
->addr
,
328 right
->file
? right
->file
->name
: "*",
329 right
->name
? right
->name
: "*", right
->addr
,
331 table_name
[id
->which_table
]));
332 arc_add (left
, right
, 0);
338 /* finally, we can sort the tables and we're done: */
340 for (tab
= &syms
[0]; tab
< &syms
[NUM_TABLES
]; ++tab
)
342 DBG (IDDEBUG
, printf ("[sym_id_parse] syms[%s]:\n",
343 table_name
[tab
- &syms
[0]]));
344 symtab_finalize (tab
);
350 * Symbol tables storing the FROM symbols of arcs do not necessarily
351 * have distinct address ranges. For example, somebody might request
352 * -k /_mcount to suppress any arcs into _mcount, while at the same
353 * time requesting -k a/b. Fortunately, those symbol tables don't get
354 * very big (the user has to type them!), so a linear search is probably
358 DEFUN (sym_id_arc_is_present
, (symtab
, from
, to
),
359 Sym_Table
* symtab AND Sym
* from AND Sym
* to
)
363 for (sym
= symtab
->base
; sym
< symtab
->limit
; ++sym
)
365 if (from
->addr
>= sym
->addr
&& from
->addr
<= sym
->end_addr
366 && arc_lookup (sym
, to
))