sval: update add_filter() to take svals
[smatch.git] / smatch_function_hooks.c
blob201e3d02a04392aa832e975e4eb25d6c082b6b0b
1 /*
2 * sparse/smatch_function_hooks.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
11 * There are several types of function hooks:
12 * add_function_hook() - For any time a function is called.
13 * add_function_assign_hook() - foo = the_function().
14 * add_implied_return_hook() - Calculates the implied return value.
15 * add_macro_assign_hook() - foo = the_macro().
16 * return_implies_state() - For when a return value of 1 implies locked
17 * and 0 implies unlocked. etc. etc.
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include "smatch.h"
24 #include "smatch_slist.h"
25 #include "smatch_extra.h"
26 #include "smatch_function_hashtable.h"
28 struct fcall_back {
29 int type;
30 struct data_range *range;
31 union {
32 func_hook *call_back;
33 implication_hook *ranged;
34 implied_return_hook *implied_return;
35 } u;
36 void *info;
39 ALLOCATOR(fcall_back, "call backs");
40 DECLARE_PTR_LIST(call_back_list, struct fcall_back);
42 DEFINE_FUNCTION_HASHTABLE_STATIC(callback, struct fcall_back, struct call_back_list);
43 static struct hashtable *func_hash;
45 #define REGULAR_CALL 0
46 #define RANGED_CALL 1
47 #define ASSIGN_CALL 2
48 #define IMPLIED_RETURN 3
49 #define MACRO_ASSIGN 4
50 #define MACRO_ASSIGN_EXTRA 5
52 struct return_implies_callback {
53 int type;
54 return_implies_hook *callback;
56 ALLOCATOR(return_implies_callback, "return_implies callbacks");
57 DECLARE_PTR_LIST(db_implies_list, struct return_implies_callback);
58 static struct db_implies_list *db_implies_list;
59 static struct db_implies_list *db_return_states_list;
61 static struct fcall_back *alloc_fcall_back(int type, void *call_back,
62 void *info)
64 struct fcall_back *cb;
66 cb = __alloc_fcall_back(0);
67 cb->type = type;
68 cb->u.call_back = call_back;
69 cb->info = info;
70 return cb;
73 void add_function_hook(const char *look_for, func_hook *call_back, void *info)
75 struct fcall_back *cb;
77 cb = alloc_fcall_back(REGULAR_CALL, call_back, info);
78 add_callback(func_hash, look_for, cb);
81 void add_function_assign_hook(const char *look_for, func_hook *call_back,
82 void *info)
84 struct fcall_back *cb;
86 cb = alloc_fcall_back(ASSIGN_CALL, call_back, info);
87 add_callback(func_hash, look_for, cb);
90 void add_implied_return_hook(const char *look_for,
91 implied_return_hook *call_back,
92 void *info)
94 struct fcall_back *cb;
96 cb = alloc_fcall_back(IMPLIED_RETURN, call_back, info);
97 add_callback(func_hash, look_for, cb);
100 void add_macro_assign_hook(const char *look_for, func_hook *call_back,
101 void *info)
103 struct fcall_back *cb;
105 cb = alloc_fcall_back(MACRO_ASSIGN, call_back, info);
106 add_callback(func_hash, look_for, cb);
109 void add_macro_assign_hook_extra(const char *look_for, func_hook *call_back,
110 void *info)
112 struct fcall_back *cb;
114 cb = alloc_fcall_back(MACRO_ASSIGN_EXTRA, call_back, info);
115 add_callback(func_hash, look_for, cb);
118 void return_implies_state(const char *look_for, long long start, long long end,
119 implication_hook *call_back, void *info)
121 struct fcall_back *cb;
123 cb = alloc_fcall_back(RANGED_CALL, call_back, info);
124 cb->range = alloc_range_perm(start, end);
125 add_callback(func_hash, look_for, cb);
128 void add_db_return_implies_callback(int type, return_implies_hook *callback)
130 struct return_implies_callback *cb = __alloc_return_implies_callback(0);
132 cb->type = type;
133 cb->callback = callback;
134 add_ptr_list(&db_implies_list, cb);
137 void add_db_return_states_callback(int type, return_implies_hook *callback)
139 struct return_implies_callback *cb = __alloc_return_implies_callback(0);
141 cb->type = type;
142 cb->callback = callback;
143 add_ptr_list(&db_return_states_list, cb);
146 static int call_call_backs(struct call_back_list *list, int type,
147 const char *fn, struct expression *expr)
149 struct fcall_back *tmp;
150 int handled = 0;
152 FOR_EACH_PTR(list, tmp) {
153 if (tmp->type == type) {
154 (tmp->u.call_back)(fn, expr, tmp->info);
155 handled = 1;
157 } END_FOR_EACH_PTR(tmp);
159 return handled;
162 static void call_ranged_call_backs(struct call_back_list *list,
163 const char *fn, struct expression *call_expr,
164 struct expression *assign_expr)
166 struct fcall_back *tmp;
168 FOR_EACH_PTR(list, tmp) {
169 (tmp->u.ranged)(fn, call_expr, assign_expr, tmp->info);
170 } END_FOR_EACH_PTR(tmp);
173 static struct call_back_list *get_same_ranged_call_backs(struct call_back_list *list,
174 struct data_range_sval *drange)
176 struct call_back_list *ret = NULL;
177 struct fcall_back *tmp;
179 FOR_EACH_PTR(list, tmp) {
180 struct data_range_sval *range_tmp;
182 if (tmp->type != RANGED_CALL)
183 continue;
184 range_tmp = drange_to_drange_sval(tmp->range);
185 if (ranges_equiv_sval(range_tmp, drange))
186 add_ptr_list(&ret, tmp);
187 } END_FOR_EACH_PTR(tmp);
188 return ret;
191 static int in_list_exact_sval(struct range_list_sval *list, struct data_range_sval *drange)
193 struct data_range_sval *tmp;
195 FOR_EACH_PTR(list, tmp) {
196 if (ranges_equiv_sval(tmp, drange))
197 return 1;
198 } END_FOR_EACH_PTR(tmp);
199 return 0;
202 static int assign_ranged_funcs(const char *fn, struct expression *expr,
203 struct call_back_list *call_backs)
205 struct fcall_back *tmp;
206 struct sm_state *sm;
207 char *var_name;
208 struct symbol *sym;
209 struct smatch_state *estate;
210 struct state_list *tmp_slist;
211 struct state_list *final_states = NULL;
212 struct range_list_sval *handled_ranges = NULL;
213 struct call_back_list *same_range_call_backs = NULL;
214 int handled = 0;
216 if (!call_backs)
217 return 0;
219 var_name = get_variable_from_expr(expr->left, &sym);
220 if (!var_name || !sym)
221 goto free;
223 FOR_EACH_PTR(call_backs, tmp) {
224 struct data_range_sval *tmp_dr_sval;
226 if (tmp->type != RANGED_CALL)
227 continue;
228 tmp_dr_sval = drange_to_drange_sval(tmp->range);
230 if (in_list_exact_sval(handled_ranges, tmp_dr_sval))
231 continue;
232 __push_fake_cur_slist();
233 tack_on_sval(&handled_ranges, tmp_dr_sval);
235 same_range_call_backs = get_same_ranged_call_backs(call_backs, tmp_dr_sval);
236 call_ranged_call_backs(same_range_call_backs, fn, expr->right, expr);
237 __free_ptr_list((struct ptr_list **)&same_range_call_backs);
239 estate = alloc_estate_range(tmp->range->min, tmp->range->max);
240 set_extra_mod(var_name, sym, estate);
242 tmp_slist = __pop_fake_cur_slist();
243 merge_slist(&final_states, tmp_slist);
244 free_slist(&tmp_slist);
245 handled = 1;
246 } END_FOR_EACH_PTR(tmp);
248 FOR_EACH_PTR(final_states, sm) {
249 __set_sm(sm);
250 } END_FOR_EACH_PTR(sm);
252 free_slist(&final_states);
253 free:
254 free_string(var_name);
255 return handled;
258 int call_implies_callbacks(int comparison, struct expression *expr, long long value, int left)
260 struct call_back_list *call_backs;
261 struct fcall_back *tmp;
262 const char *fn;
263 struct data_range_sval *value_range;
264 struct state_list *true_states = NULL;
265 struct state_list *false_states = NULL;
266 struct state_list *tmp_slist;
267 struct sm_state *sm;
269 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
270 return 0;
271 fn = expr->fn->symbol->ident->name;
272 call_backs = search_callback(func_hash, (char *)expr->fn->symbol->ident->name);
273 if (!call_backs)
274 return 0;
275 value_range = alloc_range_sval(ll_to_sval(value), ll_to_sval(value));
277 /* set true states */
278 __push_fake_cur_slist();
279 FOR_EACH_PTR(call_backs, tmp) {
280 if (tmp->type != RANGED_CALL)
281 continue;
282 if (!true_comparison_range_lr_sval(comparison, drange_to_drange_sval(tmp->range), value_range, left))
283 continue;
284 (tmp->u.ranged)(fn, expr, NULL, tmp->info);
285 } END_FOR_EACH_PTR(tmp);
286 tmp_slist = __pop_fake_cur_slist();
287 merge_slist(&true_states, tmp_slist);
288 free_slist(&tmp_slist);
290 /* set false states */
291 __push_fake_cur_slist();
292 FOR_EACH_PTR(call_backs, tmp) {
293 if (tmp->type != RANGED_CALL)
294 continue;
295 if (!false_comparison_range_lr_sval(comparison, drange_to_drange_sval(tmp->range), value_range, left))
296 continue;
297 (tmp->u.ranged)(fn, expr, NULL, tmp->info);
298 } END_FOR_EACH_PTR(tmp);
299 tmp_slist = __pop_fake_cur_slist();
300 merge_slist(&false_states, tmp_slist);
301 free_slist(&tmp_slist);
303 FOR_EACH_PTR(true_states, sm) {
304 __set_true_false_sm(sm, NULL);
305 } END_FOR_EACH_PTR(sm);
306 FOR_EACH_PTR(false_states, sm) {
307 __set_true_false_sm(NULL, sm);
308 } END_FOR_EACH_PTR(sm);
310 free_slist(&true_states);
311 free_slist(&false_states);
312 return 1;
315 struct db_callback_info {
316 int true_side;
317 int comparison;
318 struct expression *expr;
319 struct range_list_sval *rl;
320 int left;
321 struct state_list *slist;
322 struct db_implies_list *callbacks;
324 static struct db_callback_info db_info;
325 static int db_compare_callback(void *unused, int argc, char **argv, char **azColName)
327 struct range_list_sval *ret_range;
328 int type, param;
329 char *key, *value;
330 struct return_implies_callback *tmp;
332 if (argc != 5)
333 return 0;
335 get_value_ranges_sval(argv[0], &ret_range);
336 type = atoi(argv[1]);
337 param = atoi(argv[2]);
338 key = argv[3];
339 value = argv[4];
341 if (db_info.true_side) {
342 if (!possibly_true_range_lists_rl_sval(db_info.comparison,
343 ret_range, db_info.rl,
344 db_info.left))
345 return 0;
346 } else {
347 if (!possibly_false_range_lists_rl_sval(db_info.comparison,
348 ret_range, db_info.rl,
349 db_info.left))
350 return 0;
353 FOR_EACH_PTR(db_info.callbacks, tmp) {
354 if (tmp->type == type)
355 tmp->callback(db_info.expr, param, key, value);
356 } END_FOR_EACH_PTR(tmp);
357 return 0;
360 void compare_db_implies_callbacks(int comparison, struct expression *expr, long long value, int left)
362 struct symbol *sym;
363 static char sql_filter[1024];
364 struct state_list *true_states;
365 struct state_list *false_states;
366 struct sm_state *sm;
368 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
369 return;
371 sym = expr->fn->symbol;
372 if (!sym)
373 return;
375 if (sym->ctype.modifiers & MOD_STATIC) {
376 snprintf(sql_filter, 1024,
377 "file = '%s' and function = '%s' and static = '1';",
378 get_filename(), sym->ident->name);
379 } else {
380 snprintf(sql_filter, 1024,
381 "function = '%s' and static = '0';", sym->ident->name);
384 db_info.comparison = comparison;
385 db_info.expr = expr;
386 db_info.rl = range_list_to_sval(alloc_range_list(value, value));
387 db_info.left = left;
388 db_info.callbacks = db_implies_list;
390 db_info.true_side = 1;
391 __push_fake_cur_slist();
392 run_sql(db_compare_callback,
393 "select return, type, parameter, key, value from return_implies where %s",
394 sql_filter);
395 true_states = __pop_fake_cur_slist();
397 db_info.true_side = 0;
398 __push_fake_cur_slist();
399 run_sql(db_compare_callback,
400 "select return, type, parameter, key, value from return_implies where %s",
401 sql_filter);
402 false_states = __pop_fake_cur_slist();
404 FOR_EACH_PTR(true_states, sm) {
405 __set_true_false_sm(sm, NULL);
406 } END_FOR_EACH_PTR(sm);
407 FOR_EACH_PTR(false_states, sm) {
408 __set_true_false_sm(NULL, sm);
409 } END_FOR_EACH_PTR(sm);
411 free_slist(&true_states);
412 free_slist(&false_states);
415 void compare_db_return_states_callbacks(int comparison, struct expression *expr, long long value, int left)
417 struct symbol *sym;
418 static char sql_filter[1024];
419 struct state_list *true_states;
420 struct state_list *false_states;
421 struct sm_state *sm;
423 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
424 return;
426 sym = expr->fn->symbol;
427 if (!sym)
428 return;
430 if (sym->ctype.modifiers & MOD_STATIC) {
431 snprintf(sql_filter, 1024,
432 "file = '%s' and function = '%s' and static = '1';",
433 get_filename(), sym->ident->name);
434 } else {
435 snprintf(sql_filter, 1024,
436 "function = '%s' and static = '0';", sym->ident->name);
439 db_info.comparison = comparison;
440 db_info.expr = expr;
441 db_info.rl = range_list_to_sval(alloc_range_list(value, value));
442 db_info.left = left;
443 db_info.callbacks = db_return_states_list;
445 db_info.true_side = 1;
446 __push_fake_cur_slist();
447 run_sql(db_compare_callback,
448 "select return, type, parameter, key, value from return_states where %s",
449 sql_filter);
450 true_states = __pop_fake_cur_slist();
452 db_info.true_side = 0;
453 __push_fake_cur_slist();
454 run_sql(db_compare_callback,
455 "select return, type, parameter, key, value from return_states where %s",
456 sql_filter);
457 false_states = __pop_fake_cur_slist();
459 FOR_EACH_PTR(true_states, sm) {
460 __set_true_false_sm(sm, NULL);
461 } END_FOR_EACH_PTR(sm);
462 FOR_EACH_PTR(false_states, sm) {
463 __set_true_false_sm(NULL, sm);
464 } END_FOR_EACH_PTR(sm);
466 free_slist(&true_states);
467 free_slist(&false_states);
472 void function_comparison(int comparison, struct expression *expr,
473 long long value, int left)
475 if (call_implies_callbacks(comparison, expr, value, left))
476 return;
477 compare_db_implies_callbacks(comparison, expr, value, left);
478 compare_db_return_states_callbacks(comparison, expr, value, left);
481 static int db_assign_callback(void *unused, int argc, char **argv, char **azColName)
483 struct range_list_sval *ret_range;
484 int type, param;
485 char *key, *value;
486 struct return_implies_callback *tmp;
487 struct state_list *slist;
489 if (argc != 5)
490 return 0;
492 get_value_ranges_sval(argv[0], &ret_range);
493 type = atoi(argv[1]);
494 param = atoi(argv[2]);
495 key = argv[3];
496 value = argv[4];
498 __push_fake_cur_slist();
499 FOR_EACH_PTR(db_implies_list, tmp) {
500 if (tmp->type == type)
501 tmp->callback(db_info.expr->right, param, key, value);
502 } END_FOR_EACH_PTR(tmp);
503 set_extra_expr_mod(db_info.expr->left, alloc_estate_range_list(rl_sval_to_rl(ret_range)));
504 slist = __pop_fake_cur_slist();
506 merge_slist(&db_info.slist, slist);
508 return 0;
511 static int db_return_implies_assign(struct expression *expr)
513 struct symbol *sym;
514 static char sql_filter[1024];
515 static struct sm_state *sm;
516 int handled = 0;
518 if (expr->right->fn->type != EXPR_SYMBOL || !expr->right->fn->symbol)
519 return 0;
521 sym = expr->right->fn->symbol;
522 if (!sym)
523 return 0;
525 if (sym->ctype.modifiers & MOD_STATIC) {
526 snprintf(sql_filter, 1024,
527 "file = '%s' and function = '%s' and static = '1';",
528 get_filename(), sym->ident->name);
529 } else {
530 snprintf(sql_filter, 1024,
531 "function = '%s' and static = '0';", sym->ident->name);
534 db_info.expr = expr;
535 db_info.slist = NULL;
536 run_sql(db_assign_callback,
537 "select return, type, parameter, key, value from return_implies where %s",
538 sql_filter);
540 FOR_EACH_PTR(db_info.slist, sm) {
541 __set_sm(sm);
542 handled = 1;
543 } END_FOR_EACH_PTR(sm);
545 return handled;
548 static int prev_return_id;
549 static int db_assign_return_states_callback(void *unused, int argc, char **argv, char **azColName)
551 struct range_list_sval *ret_range;
552 int type, param;
553 char *key, *value;
554 struct return_implies_callback *tmp;
555 struct state_list *slist;
556 int return_id;
558 if (argc != 6)
559 return 0;
561 return_id = atoi(argv[0]);
562 get_value_ranges_sval(argv[1], &ret_range);
563 if (!ret_range)
564 ret_range = range_list_to_sval(whole_range_list());
565 type = atoi(argv[2]);
566 param = atoi(argv[3]);
567 key = argv[4];
568 value = argv[5];
570 if (prev_return_id != -1 && return_id != prev_return_id) {
571 slist = __pop_fake_cur_slist();
572 merge_slist(&db_info.slist, slist);
573 __push_fake_cur_slist();
575 prev_return_id = return_id;
577 FOR_EACH_PTR(db_return_states_list, tmp) {
578 if (tmp->type == type)
579 tmp->callback(db_info.expr, param, key, value);
580 } END_FOR_EACH_PTR(tmp);
581 set_extra_expr_mod(db_info.expr->left, alloc_estate_range_list(rl_sval_to_rl(ret_range)));
583 return 0;
586 static int db_return_states_assign(struct expression *expr)
588 struct expression *right;
589 struct symbol *sym;
590 struct sm_state *sm;
591 struct state_list *slist;
592 static char sql_filter[1024];
593 int handled = 0;
595 right = strip_expr(expr->right);
596 if (right->fn->type != EXPR_SYMBOL || !right->fn->symbol)
597 return 0;
599 sym = right->fn->symbol;
600 if (!sym)
601 return 0;
603 if (sym->ctype.modifiers & MOD_STATIC) {
604 snprintf(sql_filter, 1024,
605 "file = '%s' and function = '%s' and static = '1';",
606 get_filename(), sym->ident->name);
607 } else {
608 snprintf(sql_filter, 1024,
609 "function = '%s' and static = '0';", sym->ident->name);
612 prev_return_id = -1;
613 db_info.expr = expr;
614 db_info.slist = NULL;
615 __push_fake_cur_slist();
616 run_sql(db_assign_return_states_callback,
617 "select return_id, return, type, parameter, key, value from return_states where %s",
618 sql_filter);
619 slist = __pop_fake_cur_slist();
620 merge_slist(&db_info.slist, slist);
622 FOR_EACH_PTR(db_info.slist, sm) {
623 __set_sm(sm);
624 handled = 1;
625 } END_FOR_EACH_PTR(sm);
627 return handled;
630 static int handle_implied_return(struct expression *expr)
632 struct range_list_sval *rl;
633 struct range_list *tmp_no_sval;
635 if (!get_implied_return_sval(expr->right, &rl))
636 return 0;
637 tmp_no_sval = rl_sval_to_rl(rl);
638 set_extra_expr_mod(expr->left, alloc_estate_range_list(tmp_no_sval));
639 return 1;
642 static void match_assign_call(struct expression *expr)
644 struct call_back_list *call_backs;
645 const char *fn;
646 struct expression *right;
647 int handled = 0;
649 right = strip_expr(expr->right);
650 if (right->fn->type != EXPR_SYMBOL || !right->fn->symbol) {
651 set_extra_expr_mod(expr->left, extra_undefined());
652 return;
654 fn = right->fn->symbol->ident->name;
657 * some of these conflict (they try to set smatch extra twice), so we
658 * call them in order from least important to most important.
661 call_backs = search_callback(func_hash, (char *)fn);
662 call_call_backs(call_backs, ASSIGN_CALL, fn, expr);
664 handled |= db_return_states_assign(expr);
665 handled |= db_return_implies_assign(expr);
666 handled |= assign_ranged_funcs(fn, expr, call_backs);
667 handled |= handle_implied_return(expr);
669 if (!handled)
670 set_extra_expr_mod(expr->left, extra_undefined());
673 static int db_return_states_callback(void *unused, int argc, char **argv, char **azColName)
675 struct range_list_sval *ret_range;
676 int type, param;
677 char *key, *value;
678 struct return_implies_callback *tmp;
679 struct state_list *slist;
680 int return_id;
682 if (argc != 6)
683 return 0;
685 return_id = atoi(argv[0]);
686 get_value_ranges_sval(argv[1], &ret_range);
687 type = atoi(argv[2]);
688 param = atoi(argv[3]);
689 key = argv[4];
690 value = argv[5];
692 if (prev_return_id != -1 && return_id != prev_return_id) {
693 slist = __pop_fake_cur_slist();
694 merge_slist(&db_info.slist, slist);
695 __push_fake_cur_slist();
697 prev_return_id = return_id;
699 FOR_EACH_PTR(db_return_states_list, tmp) {
700 if (tmp->type == type)
701 tmp->callback(db_info.expr, param, key, value);
702 } END_FOR_EACH_PTR(tmp);
704 return 0;
707 static void db_return_states(struct expression *expr)
709 struct symbol *sym;
710 struct sm_state *sm;
711 struct state_list *slist;
712 static char sql_filter[1024];
714 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
715 return;
717 sym = expr->fn->symbol;
718 if (!sym)
719 return;
721 if (sym->ctype.modifiers & MOD_STATIC) {
722 snprintf(sql_filter, 1024,
723 "file = '%s' and function = '%s' and static = '1';",
724 get_filename(), sym->ident->name);
725 } else {
726 snprintf(sql_filter, 1024,
727 "function = '%s' and static = '0';", sym->ident->name);
730 prev_return_id = -1;
731 db_info.expr = expr;
732 db_info.slist = NULL;
733 __push_fake_cur_slist();
734 run_sql(db_return_states_callback,
735 "select return_id, return, type, parameter, key, value from return_states where %s",
736 sql_filter);
737 slist = __pop_fake_cur_slist();
738 merge_slist(&db_info.slist, slist);
740 FOR_EACH_PTR(db_info.slist, sm) {
741 __set_sm(sm);
742 } END_FOR_EACH_PTR(sm);
745 static int is_assigned_call(struct expression *expr)
747 struct expression *tmp;
749 FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) {
750 if (tmp->type == EXPR_ASSIGNMENT && strip_expr(tmp->right) == expr)
751 return 1;
752 if (tmp->pos.line < expr->pos.line)
753 return 0;
754 } END_FOR_EACH_PTR_REVERSE(tmp);
755 return 0;
758 static void db_return_states_call(struct expression *expr)
760 if (is_assigned_call(expr))
761 return;
762 db_return_states(expr);
765 static void match_function_call(struct expression *expr)
767 struct call_back_list *call_backs;
769 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
770 return;
771 call_backs = search_callback(func_hash, (char *)expr->fn->symbol->ident->name);
772 if (call_backs)
773 call_call_backs(call_backs, REGULAR_CALL,
774 expr->fn->symbol->ident->name, expr);
775 db_return_states_call(expr);
778 static void match_macro_assign(struct expression *expr)
780 struct call_back_list *call_backs;
781 const char *macro;
782 struct expression *right;
784 right = strip_expr(expr->right);
785 macro = get_macro_name(right->pos);
786 call_backs = search_callback(func_hash, (char *)macro);
787 if (!call_backs)
788 return;
789 call_call_backs(call_backs, MACRO_ASSIGN, macro, expr);
790 call_call_backs(call_backs, MACRO_ASSIGN_EXTRA, macro, expr);
793 int get_implied_return_sval(struct expression *expr, struct range_list_sval **rl)
795 struct call_back_list *call_backs;
796 struct fcall_back *tmp;
797 int handled = 0;
798 char *fn;
800 *rl = NULL;
802 expr = strip_expr(expr);
803 fn = get_variable_from_expr(expr->fn, NULL);
804 if (!fn)
805 goto out;
807 call_backs = search_callback(func_hash, fn);
809 FOR_EACH_PTR(call_backs, tmp) {
810 if (tmp->type == IMPLIED_RETURN) {
811 (tmp->u.implied_return)(expr, tmp->info, rl);
812 handled = 1;
814 } END_FOR_EACH_PTR(tmp);
816 out:
817 free_string(fn);
818 return handled;
821 void create_function_hook_hash(void)
823 func_hash = create_function_hashtable(5000);
826 void register_function_hooks(int id)
828 add_hook(&match_function_call, FUNCTION_CALL_HOOK);
829 add_hook(&match_assign_call, CALL_ASSIGNMENT_HOOK);
830 add_hook(&match_macro_assign, MACRO_ASSIGNMENT_HOOK);