14 struct ref
*ref_init(char *name
, int flags
)
16 struct ref
*result
= xmalloc(sizeof(struct ref
));
18 result
->flags
= flags
;
22 struct block
*block_init(struct node
*node
)
24 struct block
*block
= xmalloc(sizeof(struct block
));
25 memset(block
, 0, sizeof(*block
));
30 static void free_hashed(void *name
, void *data
)
35 void block_free(struct block
*block
)
37 struct block_list
*cur
= block
->_children
;
39 struct block_list
*next
= cur
->next
;
40 block_free(cur
->block
);
45 hash_walk(block
->_names
, free_hashed
, NULL
);
46 hash_release(block
->_names
);
51 static int find_blocks(struct node
*node
, void *data
)
53 struct block
*block
= data
;
54 if (node
== block
->node
)
56 if (node
->type
== AST_BLOCK
|| node
->type
== AST_FUNCTION
) {
57 struct block_list
*newchild
= xmalloc(sizeof(struct block_list
));
58 newchild
->block
= block_init(node
);
59 newchild
->block
->parent
= block
;
60 newchild
->next
= block
->_children
;
61 block
->_children
= newchild
;
67 static void init_children(struct block
*block
)
69 struct block_list
*cur
= NULL
;
70 struct block_list
*newhead
= NULL
;
71 node_walk(block
->node
, find_blocks
, block
);
72 /* reversing children order */
73 cur
= block
->_children
;
75 struct block_list
*next
= cur
->next
;
80 block
->_children
= newhead
;
84 struct block_list
*block_children(struct block
*block
)
88 return block
->_children
;
91 static void block_walk(struct block
*block
,
92 int (*see
)(struct block
*, void *),
95 if (see(block
, data
)) {
96 struct block_list
*cur
;
97 cur
= block_children(block
);
99 block_walk(cur
->block
, see
, data
);
105 struct block_search
{
107 struct block
*result
;
110 static int search_offset(struct block
*block
, void *data
)
112 struct block_search
*search
= data
;
113 long offset
= search
->offset
;
114 if (block
->node
->start
<= offset
&& offset
< block
->node
->end
) {
115 search
->result
= block
;
121 struct block
*block_find(struct block
*block
, long offset
)
123 struct block_search result
;
124 result
.offset
= offset
;
125 result
.result
= NULL
;
126 block_walk(block
, search_offset
, &result
);
127 return result
.result
;
130 static void handle_enum(struct block
*block
, struct node
*node
)
133 /* ENUM -> ENUMLIST */
134 struct node
*list
= node
->children
[node
->count
- 1];
135 if (list
->type
!= AST_ENUMLIST
)
137 if (node
->children
[0]->type
== AST_IDENTIFIER
)
138 hash_put(block_names(block
),
139 name_init(node
->children
[0], NAME_ENUM
));
140 for (i
= 0; i
< list
->count
; i
++) {
141 /* ENUMLIST -> ENUMVAL -> IDENTIFIER */
142 struct node
*child
= list
->children
[i
]->children
[0];
143 hash_put(block_names(block
),
144 name_init(child
, 0));
148 static void handle_struct(struct block
*block
, struct node
*node
)
152 if (node
->children
[1]->type
== AST_IDENTIFIER
) {
153 int flags
= node
->children
[0]->type
== AST_STRUCTKW
?
154 NAME_STRUCT
: NAME_UNION
;
155 hash_put(block_names(block
),
156 name_init(node
->children
[1], flags
));
163 unsigned isstatic
: 1;
164 unsigned isextern
: 1;
167 static int analyze_declspec(struct node
*node
, void *data
)
169 struct declinfo
*declinfo
= data
;
170 switch (node
->type
) {
172 handle_enum(declinfo
->block
, node
);
175 handle_struct(declinfo
->block
, node
);
178 declinfo
->isstatic
= 1;
181 declinfo
->isextern
= 1;
188 static int declinfo_flags(struct declinfo
*declinfo
)
191 if (declinfo
->isstatic
)
192 flags
|= NAME_STATIC
;
193 if (declinfo
->isextern
)
194 flags
|= NAME_EXTERN
;
195 return flags
| declinfo
->flags
;
198 static void handle_function(struct block
*block
, struct node
*node
)
201 struct declinfo declinfo
;
202 memset(&declinfo
, 0, sizeof(declinfo
));
203 node_walk(node
->children
[0], analyze_declspec
, &declinfo
);
204 name
= declarator_name(node
->children
[1]);
206 int flags
= declinfo_flags(&declinfo
) | NAME_FUNCTION
;
207 hash_put(block_names(block
), name_init(name
, flags
));
211 static void add_declarator_name(struct declinfo
*declinfo
, struct node
*decl
)
214 struct block
*block
= declinfo
->block
;
215 struct node
*dirdecl
= decl
->children
[decl
->count
- 1];
216 /* nothing to do for function declarations */
217 switch (*(enum decltype *) dirdecl
->data
) {
219 case DECL_PARENS_TYPE
:
225 name
= declarator_name(decl
);
227 hash_put(block_names(block
),
228 name_init(name
, declinfo_flags(declinfo
)));
231 static int search_declarators(struct node
*node
, void *data
)
233 struct declinfo
*declinfo
= data
;
234 if (node
->type
== AST_INIT
) {
235 add_declarator_name(declinfo
, node
->children
[0]);
238 /* should ignore "extern int var" but not "extern int var = 1" */
239 if (!declinfo
->isextern
&& node
->type
== AST_DECL
) {
240 add_declarator_name(declinfo
, node
);
246 static void handle_declaration(struct block
*block
,
250 struct declinfo declinfo
;
251 memset(&declinfo
, 0, sizeof(declinfo
));
252 declinfo
.block
= block
;
253 declinfo
.flags
= flags
;
254 node_walk(node
->children
[0], analyze_declspec
, &declinfo
);
256 node_walk(node
->children
[1], search_declarators
, &declinfo
);
259 static void handle_parameters(struct block
*block
, struct node
*node
)
262 for (i
= 0; i
< node
->count
; i
++) {
263 struct node
*param
= node
->children
[i
];
264 if (param
->count
> 1) {
265 struct node
*name
= declarator_name(
266 param
->children
[param
->count
- 1]);
268 hash_put(block_names(block
),
274 static void handle_label(struct block
*block
, struct node
*node
)
276 struct node
*id
= node
->children
[0];
277 hash_put(block_names(block
), name_init(id
, NAME_LABEL
));
280 static int find_names(struct node
*node
, void *data
)
282 struct block
*block
= data
;
283 switch (node
->type
) {
285 handle_function(block
, node
);
288 handle_declaration(block
, node
, 0);
291 handle_label(block
, node
);
299 return block
->node
== node
;
302 static long name_hash(void *name
)
304 return str_hash(((struct name
*) name
)->name
);
307 static long ref_hash(void *name
)
309 return str_hash(((struct name
*) name
)->name
);
312 static int name_cmp(void *data
, void *key
)
314 struct name
*name
= data
;
315 struct ref
*ref
= key
;
316 if (!strcmp(name
->name
, ref
->name
))
317 return !modifiers_match(name
, ref
->flags
);
321 static void init_names(struct block
*block
)
323 block
->_names
= hash_init(name_hash
, ref_hash
, name_cmp
, 4);
324 if (block
->node
->type
== AST_FUNCTION
) {
325 /* FUNCTION -> DECL -> DECL2 -> PARAMLIST */
326 struct node
*node
= block
->node
;
327 struct node
*decl
= node
->children
[node
->count
- 2];
328 struct node
*decl2
= decl
->children
[decl
->count
- 1];
329 if (decl2
->count
> 1) {
330 struct node
*params
= decl2
->children
[decl2
->count
- 1];
331 handle_parameters(block
, params
);
333 if (node
->count
>= 4) {
335 struct node
*decllist
= node
->children
[node
->count
- 2];
336 for (i
= 0; i
< decllist
->count
; i
++)
337 handle_declaration(block
,
338 decllist
->children
[i
],
342 node_walk(block
->node
, find_names
, block
);
346 struct hash
*block_names(struct block
*block
)
350 return block
->_names
;
353 struct ref
*name_on(struct node
*node
)
355 if (node
->type
!= AST_IDENTIFIER
&& node
->type
!= AST_TYPENAME
)
357 return ref_init(node
->data
, guess_name_flags(node
));
360 struct block
*block_defining(struct block
*block
, struct node
*node
)
362 struct ref
*ref
= name_on(node
);
363 while (block
&& !hash_get(block_names(block
), ref
))
364 block
= block
->parent
;
369 struct name
*block_lookup(struct block
*block
, struct node
*node
)
371 struct ref
*ref
= name_on(node
);
372 struct name
*result
= NULL
;
373 if (!ref
|| ref
->flags
& (NAME_FIELD
| NAME_PARAMDECL
))
376 struct name
*cur
= hash_get(block_names(block
), ref
);
381 block
= block
->parent
;
390 } tags
[] = {{"struct ", NAME_STRUCT
},
391 {"enum ", NAME_ENUM
},
392 {"union ", NAME_UNION
},
393 {"label ", NAME_LABEL
}};
395 static struct ref
*token_name(char *token
)
399 for (i
= 0; i
< LENGTH(tags
); i
++) {
400 if (startswith(token
, tags
[i
].name
)) {
401 token
+= strlen(tags
[i
].name
);
402 flags
|= tags
[i
].flag
;
406 return ref_init(token
, flags
);
409 static struct block
*block_byname(struct block
*block
, char *name
)
411 struct block_list
*blist
= block_children(block
);
413 struct node
*node
= blist
->block
->node
;
414 struct node
*declname
= declarator_name(node
->children
[1]);
415 if (node
->type
== AST_FUNCTION
&&
416 !strcmp(name
, declname
->data
))
423 struct name
*block_find_hier(struct block
*block
, char *location
)
426 char *newlocation
= readtoken(token
, location
, ":");
427 struct block_list
*blist
= NULL
;
429 struct block
*newblock
= block_byname(block
, token
);
431 return block_find_hier(newblock
, newlocation
);
433 struct ref
*key
= token_name(token
);
434 struct name
*name
= hash_get(block_names(block
), key
);
439 blist
= block_children(block
);
441 struct name
*name
= block_find_hier(blist
->block
, location
);