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 ***/