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>", 0, 0, 0, NULL
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 ((unsigned char) 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 ((unsigned char) *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
)
205 ? strcmp (pattern
->name
,
206 sym
->name
+(discard_underscores
&& sym
->name
[0] == '_')) == 0
212 DEFUN (extend_match
, (m
, sym
, tab
, second_pass
),
213 struct match
*m AND Sym
* sym AND Sym_Table
* tab AND
bool second_pass
)
215 if (m
->prev_match
!= sym
- 1)
217 /* discontinuity: add new match to table: */
220 tab
->base
[tab
->len
] = *sym
;
221 m
->prev_index
= tab
->len
;
223 /* link match into match's chain: */
224 tab
->base
[tab
->len
].next
= m
->first_match
;
225 m
->first_match
= &tab
->base
[tab
->len
];
230 /* extend match to include this symbol: */
233 tab
->base
[m
->prev_index
].end_addr
= sym
->end_addr
;
240 * Go through sym_id list produced by option processing and fill
241 * in the various symbol tables indicating what symbols should
242 * be displayed or suppressed for the various kinds of outputs.
244 * This can potentially produce huge tables and in particulars
245 * tons of arcs, but this happens only if the user makes silly
246 * requests---you get what you ask for!
249 DEFUN_VOID (sym_id_parse
)
251 Sym
*sym
, *left
, *right
;
256 * Convert symbol ids into Syms, so we can deal with them more easily:
258 for (id
= id_list
; id
; id
= id
->next
)
263 /* first determine size of each table: */
265 for (sym
= symtab
.base
; sym
< symtab
.limit
; ++sym
)
267 for (id
= id_list
; id
; id
= id
->next
)
269 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
))
275 extend_match (&id
->right
, sym
, &right_ids
, FALSE
);
280 /* create tables of appropriate size and reset lengths: */
282 for (tab
= syms
; tab
< &syms
[NUM_TABLES
]; ++tab
)
286 tab
->base
= (Sym
*) xmalloc (tab
->len
* sizeof (Sym
));
287 tab
->limit
= tab
->base
+ tab
->len
;
293 right_ids
.base
= (Sym
*) xmalloc (right_ids
.len
* sizeof (Sym
));
294 right_ids
.limit
= right_ids
.base
+ right_ids
.len
;
298 /* make a second pass through symtab, creating syms as necessary: */
300 for (sym
= symtab
.base
; sym
< symtab
.limit
; ++sym
)
302 for (id
= id_list
; id
; id
= id
->next
)
304 if (match (&id
->left
.sym
, sym
))
306 extend_match (&id
->left
, sym
, &syms
[id
->which_table
], TRUE
);
308 if (id
->has_right
&& match (&id
->right
.sym
, sym
))
310 extend_match (&id
->right
, sym
, &right_ids
, TRUE
);
315 /* go through ids creating arcs as needed: */
317 for (id
= id_list
; id
; id
= id
->next
)
321 for (left
= id
->left
.first_match
; left
; left
= left
->next
)
323 for (right
= id
->right
.first_match
; right
; right
= right
->next
)
327 "[sym_id_parse]: arc %s:%s(%lx-%lx) -> %s:%s(%lx-%lx) to %s\n",
328 left
->file
? left
->file
->name
: "*",
329 left
->name
? left
->name
: "*",
330 (unsigned long) left
->addr
,
331 (unsigned long) left
->end_addr
,
332 right
->file
? right
->file
->name
: "*",
333 right
->name
? right
->name
: "*",
334 (unsigned long) right
->addr
,
335 (unsigned long) right
->end_addr
,
336 table_name
[id
->which_table
]));
337 arc_add (left
, right
, (unsigned long) 0);
343 /* finally, we can sort the tables and we're done: */
345 for (tab
= &syms
[0]; tab
< &syms
[NUM_TABLES
]; ++tab
)
347 DBG (IDDEBUG
, printf ("[sym_id_parse] syms[%s]:\n",
348 table_name
[tab
- &syms
[0]]));
349 symtab_finalize (tab
);
355 * Symbol tables storing the FROM symbols of arcs do not necessarily
356 * have distinct address ranges. For example, somebody might request
357 * -k /_mcount to suppress any arcs into _mcount, while at the same
358 * time requesting -k a/b. Fortunately, those symbol tables don't get
359 * very big (the user has to type them!), so a linear search is probably
363 DEFUN (sym_id_arc_is_present
, (symtab
, from
, to
),
364 Sym_Table
* symtab AND Sym
* from AND Sym
* to
)
368 for (sym
= symtab
->base
; sym
< symtab
->limit
; ++sym
)
370 if (from
->addr
>= sym
->addr
&& from
->addr
<= sym
->end_addr
371 && arc_lookup (sym
, to
))