check_precedence: fix a segfault
[smatch.git] / smatch_function_hooks.c
blob281f2efa2f6fddf7f0de0259709ad40ba9466f1b
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 *drange)
176 struct call_back_list *ret = NULL;
177 struct fcall_back *tmp;
179 FOR_EACH_PTR(list, tmp) {
180 if (tmp->type != RANGED_CALL)
181 continue;
182 if (tmp->range->min == drange->min && tmp->range->max == drange->max)
183 add_ptr_list(&ret, tmp);
184 } END_FOR_EACH_PTR(tmp);
185 return ret;
188 static int assign_ranged_funcs(const char *fn, struct expression *expr,
189 struct call_back_list *call_backs)
191 struct fcall_back *tmp;
192 struct sm_state *sm;
193 char *var_name;
194 struct symbol *sym;
195 struct smatch_state *estate;
196 struct state_list *tmp_slist;
197 struct state_list *final_states = NULL;
198 struct range_list *handled_ranges = NULL;
199 struct call_back_list *same_range_call_backs = NULL;
200 int handled = 0;
202 if (!call_backs)
203 return 0;
205 var_name = get_variable_from_expr(expr->left, &sym);
206 if (!var_name || !sym)
207 goto free;
209 FOR_EACH_PTR(call_backs, tmp) {
210 if (tmp->type != RANGED_CALL)
211 continue;
212 if (in_list_exact(handled_ranges, tmp->range))
213 continue;
214 __push_fake_cur_slist();
215 tack_on(&handled_ranges, tmp->range);
217 same_range_call_backs = get_same_ranged_call_backs(call_backs, tmp->range);
218 call_ranged_call_backs(same_range_call_backs, fn, expr->right, expr);
219 __free_ptr_list((struct ptr_list **)&same_range_call_backs);
221 estate = alloc_estate_range(tmp->range->min, tmp->range->max);
222 set_extra_mod(var_name, sym, estate);
224 tmp_slist = __pop_fake_cur_slist();
225 merge_slist(&final_states, tmp_slist);
226 free_slist(&tmp_slist);
227 handled = 1;
228 } END_FOR_EACH_PTR(tmp);
230 FOR_EACH_PTR(final_states, sm) {
231 __set_sm(sm);
232 } END_FOR_EACH_PTR(sm);
234 free_slist(&final_states);
235 free:
236 free_string(var_name);
237 return handled;
240 int call_implies_callbacks(int comparison, struct expression *expr, long long value, int left)
242 struct call_back_list *call_backs;
243 struct fcall_back *tmp;
244 const char *fn;
245 struct data_range *value_range;
246 struct state_list *true_states = NULL;
247 struct state_list *false_states = NULL;
248 struct state_list *tmp_slist;
249 struct sm_state *sm;
251 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
252 return 0;
253 fn = expr->fn->symbol->ident->name;
254 call_backs = search_callback(func_hash, (char *)expr->fn->symbol->ident->name);
255 if (!call_backs)
256 return 0;
257 value_range = alloc_range(value, value);
259 /* set true states */
260 __push_fake_cur_slist();
261 FOR_EACH_PTR(call_backs, tmp) {
262 if (tmp->type != RANGED_CALL)
263 continue;
264 if (!true_comparison_range_lr(comparison, tmp->range, value_range, left))
265 continue;
266 (tmp->u.ranged)(fn, expr, NULL, tmp->info);
267 } END_FOR_EACH_PTR(tmp);
268 tmp_slist = __pop_fake_cur_slist();
269 merge_slist(&true_states, tmp_slist);
270 free_slist(&tmp_slist);
272 /* set false states */
273 __push_fake_cur_slist();
274 FOR_EACH_PTR(call_backs, tmp) {
275 if (tmp->type != RANGED_CALL)
276 continue;
277 if (!false_comparison_range_lr(comparison, tmp->range, value_range, left))
278 continue;
279 (tmp->u.ranged)(fn, expr, NULL, tmp->info);
280 } END_FOR_EACH_PTR(tmp);
281 tmp_slist = __pop_fake_cur_slist();
282 merge_slist(&false_states, tmp_slist);
283 free_slist(&tmp_slist);
285 FOR_EACH_PTR(true_states, sm) {
286 __set_true_false_sm(sm, NULL);
287 } END_FOR_EACH_PTR(sm);
288 FOR_EACH_PTR(false_states, sm) {
289 __set_true_false_sm(NULL, sm);
290 } END_FOR_EACH_PTR(sm);
292 free_slist(&true_states);
293 free_slist(&false_states);
294 return 1;
297 struct db_callback_info {
298 int true_side;
299 int comparison;
300 struct expression *expr;
301 struct range_list *rl;
302 int left;
303 struct state_list *slist;
304 struct db_implies_list *callbacks;
306 static struct db_callback_info db_info;
307 static int db_compare_callback(void *unused, int argc, char **argv, char **azColName)
309 struct range_list *ret_range;
310 int type, param;
311 char *key, *value;
312 struct return_implies_callback *tmp;
314 if (argc != 5)
315 return 0;
317 get_value_ranges(argv[0], &ret_range);
318 type = atoi(argv[1]);
319 param = atoi(argv[2]);
320 key = argv[3];
321 value = argv[4];
323 if (db_info.true_side) {
324 if (!possibly_true_range_lists_rl(db_info.comparison,
325 ret_range, db_info.rl,
326 db_info.left))
327 return 0;
328 } else {
329 if (!possibly_false_range_lists_rl(db_info.comparison,
330 ret_range, db_info.rl,
331 db_info.left))
332 return 0;
335 FOR_EACH_PTR(db_info.callbacks, tmp) {
336 if (tmp->type == type)
337 tmp->callback(db_info.expr, param, key, value);
338 } END_FOR_EACH_PTR(tmp);
339 return 0;
342 void compare_db_implies_callbacks(int comparison, struct expression *expr, long long value, int left)
344 struct symbol *sym;
345 static char sql_filter[1024];
346 struct state_list *true_states;
347 struct state_list *false_states;
348 struct sm_state *sm;
350 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
351 return;
353 sym = expr->fn->symbol;
354 if (!sym)
355 return;
357 if (sym->ctype.modifiers & MOD_STATIC) {
358 snprintf(sql_filter, 1024,
359 "file = '%s' and function = '%s' and static = '1';",
360 get_filename(), sym->ident->name);
361 } else {
362 snprintf(sql_filter, 1024,
363 "function = '%s' and static = '0';", sym->ident->name);
366 db_info.comparison = comparison;
367 db_info.expr = expr;
368 db_info.rl = alloc_range_list(value, value);
369 db_info.left = left;
370 db_info.callbacks = db_implies_list;
372 db_info.true_side = 1;
373 __push_fake_cur_slist();
374 run_sql(db_compare_callback,
375 "select return, type, parameter, key, value from return_implies where %s",
376 sql_filter);
377 true_states = __pop_fake_cur_slist();
379 db_info.true_side = 0;
380 __push_fake_cur_slist();
381 run_sql(db_compare_callback,
382 "select return, type, parameter, key, value from return_implies where %s",
383 sql_filter);
384 false_states = __pop_fake_cur_slist();
386 FOR_EACH_PTR(true_states, sm) {
387 __set_true_false_sm(sm, NULL);
388 } END_FOR_EACH_PTR(sm);
389 FOR_EACH_PTR(false_states, sm) {
390 __set_true_false_sm(NULL, sm);
391 } END_FOR_EACH_PTR(sm);
393 free_slist(&true_states);
394 free_slist(&false_states);
397 void compare_db_return_states_callbacks(int comparison, struct expression *expr, long long value, int left)
399 struct symbol *sym;
400 static char sql_filter[1024];
401 struct state_list *true_states;
402 struct state_list *false_states;
403 struct sm_state *sm;
405 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
406 return;
408 sym = expr->fn->symbol;
409 if (!sym)
410 return;
412 if (sym->ctype.modifiers & MOD_STATIC) {
413 snprintf(sql_filter, 1024,
414 "file = '%s' and function = '%s' and static = '1';",
415 get_filename(), sym->ident->name);
416 } else {
417 snprintf(sql_filter, 1024,
418 "function = '%s' and static = '0';", sym->ident->name);
421 db_info.comparison = comparison;
422 db_info.expr = expr;
423 db_info.rl = alloc_range_list(value, value);
424 db_info.left = left;
425 db_info.callbacks = db_return_states_list;
427 db_info.true_side = 1;
428 __push_fake_cur_slist();
429 run_sql(db_compare_callback,
430 "select return, type, parameter, key, value from return_states where %s",
431 sql_filter);
432 true_states = __pop_fake_cur_slist();
434 db_info.true_side = 0;
435 __push_fake_cur_slist();
436 run_sql(db_compare_callback,
437 "select return, type, parameter, key, value from return_states where %s",
438 sql_filter);
439 false_states = __pop_fake_cur_slist();
441 FOR_EACH_PTR(true_states, sm) {
442 __set_true_false_sm(sm, NULL);
443 } END_FOR_EACH_PTR(sm);
444 FOR_EACH_PTR(false_states, sm) {
445 __set_true_false_sm(NULL, sm);
446 } END_FOR_EACH_PTR(sm);
448 free_slist(&true_states);
449 free_slist(&false_states);
454 void function_comparison(int comparison, struct expression *expr,
455 long long value, int left)
457 if (call_implies_callbacks(comparison, expr, value, left))
458 return;
459 compare_db_implies_callbacks(comparison, expr, value, left);
460 compare_db_return_states_callbacks(comparison, expr, value, left);
463 static int db_assign_callback(void *unused, int argc, char **argv, char **azColName)
465 struct range_list *ret_range;
466 int type, param;
467 char *key, *value;
468 struct return_implies_callback *tmp;
469 struct state_list *slist;
471 if (argc != 5)
472 return 0;
474 get_value_ranges(argv[0], &ret_range);
475 type = atoi(argv[1]);
476 param = atoi(argv[2]);
477 key = argv[3];
478 value = argv[4];
480 __push_fake_cur_slist();
481 FOR_EACH_PTR(db_implies_list, tmp) {
482 if (tmp->type == type)
483 tmp->callback(db_info.expr->right, param, key, value);
484 } END_FOR_EACH_PTR(tmp);
485 set_extra_expr_mod(db_info.expr->left, alloc_estate_range_list(ret_range));
486 slist = __pop_fake_cur_slist();
488 merge_slist(&db_info.slist, slist);
490 return 0;
493 static int db_return_implies_assign(struct expression *expr)
495 struct symbol *sym;
496 static char sql_filter[1024];
497 static struct sm_state *sm;
498 int handled = 0;
500 if (expr->right->fn->type != EXPR_SYMBOL || !expr->right->fn->symbol)
501 return 0;
503 sym = expr->right->fn->symbol;
504 if (!sym)
505 return 0;
507 if (sym->ctype.modifiers & MOD_STATIC) {
508 snprintf(sql_filter, 1024,
509 "file = '%s' and function = '%s' and static = '1';",
510 get_filename(), sym->ident->name);
511 } else {
512 snprintf(sql_filter, 1024,
513 "function = '%s' and static = '0';", sym->ident->name);
516 db_info.expr = expr;
517 db_info.slist = NULL;
518 run_sql(db_assign_callback,
519 "select return, type, parameter, key, value from return_implies where %s",
520 sql_filter);
522 FOR_EACH_PTR(db_info.slist, sm) {
523 __set_sm(sm);
524 handled = 1;
525 } END_FOR_EACH_PTR(sm);
527 return handled;
530 static int prev_return_id;
531 static int db_assign_return_states_callback(void *unused, int argc, char **argv, char **azColName)
533 struct range_list *ret_range;
534 int type, param;
535 char *key, *value;
536 struct return_implies_callback *tmp;
537 struct state_list *slist;
538 int return_id;
540 if (argc != 6)
541 return 0;
543 return_id = atoi(argv[0]);
544 get_value_ranges(argv[1], &ret_range);
545 if (!ret_range)
546 ret_range = whole_range_list();
547 type = atoi(argv[2]);
548 param = atoi(argv[3]);
549 key = argv[4];
550 value = argv[5];
552 if (prev_return_id != -1 && return_id != prev_return_id) {
553 slist = __pop_fake_cur_slist();
554 merge_slist(&db_info.slist, slist);
555 __push_fake_cur_slist();
557 prev_return_id = return_id;
559 FOR_EACH_PTR(db_return_states_list, tmp) {
560 if (tmp->type == type)
561 tmp->callback(db_info.expr, param, key, value);
562 } END_FOR_EACH_PTR(tmp);
563 set_extra_expr_mod(db_info.expr->left, alloc_estate_range_list(ret_range));
565 return 0;
568 static int db_return_states_assign(struct expression *expr)
570 struct expression *right;
571 struct symbol *sym;
572 struct sm_state *sm;
573 struct state_list *slist;
574 static char sql_filter[1024];
575 int handled = 0;
577 right = strip_expr(expr->right);
578 if (right->fn->type != EXPR_SYMBOL || !right->fn->symbol)
579 return 0;
581 sym = right->fn->symbol;
582 if (!sym)
583 return 0;
585 if (sym->ctype.modifiers & MOD_STATIC) {
586 snprintf(sql_filter, 1024,
587 "file = '%s' and function = '%s' and static = '1';",
588 get_filename(), sym->ident->name);
589 } else {
590 snprintf(sql_filter, 1024,
591 "function = '%s' and static = '0';", sym->ident->name);
594 prev_return_id = -1;
595 db_info.expr = expr;
596 db_info.slist = NULL;
597 __push_fake_cur_slist();
598 run_sql(db_assign_return_states_callback,
599 "select return_id, return, type, parameter, key, value from return_states where %s",
600 sql_filter);
601 slist = __pop_fake_cur_slist();
602 merge_slist(&db_info.slist, slist);
604 FOR_EACH_PTR(db_info.slist, sm) {
605 __set_sm(sm);
606 handled = 1;
607 } END_FOR_EACH_PTR(sm);
609 return handled;
612 static int handle_implied_return(struct expression *expr)
614 struct range_list *rl;
616 if (!get_implied_return(expr->right, &rl))
617 return 0;
618 set_extra_expr_mod(expr->left, alloc_estate_range_list(rl));
619 return 1;
622 static void match_assign_call(struct expression *expr)
624 struct call_back_list *call_backs;
625 const char *fn;
626 struct expression *right;
627 int handled = 0;
629 right = strip_expr(expr->right);
630 if (right->fn->type != EXPR_SYMBOL || !right->fn->symbol) {
631 set_extra_expr_mod(expr->left, extra_undefined());
632 return;
634 fn = right->fn->symbol->ident->name;
637 * some of these conflict (they try to set smatch extra twice), so we
638 * call them in order from least important to most important.
641 call_backs = search_callback(func_hash, (char *)fn);
642 call_call_backs(call_backs, ASSIGN_CALL, fn, expr);
644 handled |= db_return_states_assign(expr);
645 handled |= db_return_implies_assign(expr);
646 handled |= assign_ranged_funcs(fn, expr, call_backs);
647 handled |= handle_implied_return(expr);
649 if (!handled)
650 set_extra_expr_mod(expr->left, extra_undefined());
653 static int db_return_states_callback(void *unused, int argc, char **argv, char **azColName)
655 struct range_list *ret_range;
656 int type, param;
657 char *key, *value;
658 struct return_implies_callback *tmp;
659 struct state_list *slist;
660 int return_id;
662 if (argc != 6)
663 return 0;
665 return_id = atoi(argv[0]);
666 get_value_ranges(argv[1], &ret_range);
667 type = atoi(argv[2]);
668 param = atoi(argv[3]);
669 key = argv[4];
670 value = argv[5];
672 if (prev_return_id != -1 && return_id != prev_return_id) {
673 slist = __pop_fake_cur_slist();
674 merge_slist(&db_info.slist, slist);
675 __push_fake_cur_slist();
677 prev_return_id = return_id;
679 FOR_EACH_PTR(db_return_states_list, tmp) {
680 if (tmp->type == type)
681 tmp->callback(db_info.expr, param, key, value);
682 } END_FOR_EACH_PTR(tmp);
684 return 0;
687 static void db_return_states(struct expression *expr)
689 struct symbol *sym;
690 struct sm_state *sm;
691 struct state_list *slist;
692 static char sql_filter[1024];
694 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
695 return;
697 sym = expr->fn->symbol;
698 if (!sym)
699 return;
701 if (sym->ctype.modifiers & MOD_STATIC) {
702 snprintf(sql_filter, 1024,
703 "file = '%s' and function = '%s' and static = '1';",
704 get_filename(), sym->ident->name);
705 } else {
706 snprintf(sql_filter, 1024,
707 "function = '%s' and static = '0';", sym->ident->name);
710 prev_return_id = -1;
711 db_info.expr = expr;
712 db_info.slist = NULL;
713 __push_fake_cur_slist();
714 run_sql(db_return_states_callback,
715 "select return_id, return, type, parameter, key, value from return_states where %s",
716 sql_filter);
717 slist = __pop_fake_cur_slist();
718 merge_slist(&db_info.slist, slist);
720 FOR_EACH_PTR(db_info.slist, sm) {
721 __set_sm(sm);
722 } END_FOR_EACH_PTR(sm);
725 static int is_assigned_call(struct expression *expr)
727 struct expression *tmp;
729 FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) {
730 if (tmp->type == EXPR_ASSIGNMENT && strip_expr(tmp->right) == expr)
731 return 1;
732 if (tmp->pos.line < expr->pos.line)
733 return 0;
734 } END_FOR_EACH_PTR_REVERSE(tmp);
735 return 0;
738 static void db_return_states_call(struct expression *expr)
740 if (is_assigned_call(expr))
741 return;
742 db_return_states(expr);
745 static void match_function_call(struct expression *expr)
747 struct call_back_list *call_backs;
749 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
750 return;
751 call_backs = search_callback(func_hash, (char *)expr->fn->symbol->ident->name);
752 if (call_backs)
753 call_call_backs(call_backs, REGULAR_CALL,
754 expr->fn->symbol->ident->name, expr);
755 db_return_states_call(expr);
758 static void match_macro_assign(struct expression *expr)
760 struct call_back_list *call_backs;
761 const char *macro;
762 struct expression *right;
764 right = strip_expr(expr->right);
765 macro = get_macro_name(right->pos);
766 call_backs = search_callback(func_hash, (char *)macro);
767 if (!call_backs)
768 return;
769 call_call_backs(call_backs, MACRO_ASSIGN, macro, expr);
770 call_call_backs(call_backs, MACRO_ASSIGN_EXTRA, macro, expr);
773 int get_implied_return(struct expression *expr, struct range_list **rl)
775 struct call_back_list *call_backs;
776 struct fcall_back *tmp;
777 int handled = 0;
778 char *fn;
780 *rl = NULL;
782 expr = strip_expr(expr);
783 fn = get_variable_from_expr(expr->fn, NULL);
784 if (!fn)
785 goto out;
787 call_backs = search_callback(func_hash, fn);
789 FOR_EACH_PTR(call_backs, tmp) {
790 if (tmp->type == IMPLIED_RETURN) {
791 (tmp->u.implied_return)(expr, tmp->info, rl);
792 handled = 1;
794 } END_FOR_EACH_PTR(tmp);
796 out:
797 free_string(fn);
798 return handled;
801 void create_function_hook_hash(void)
803 func_hash = create_function_hashtable(5000);
806 void register_function_hooks(int id)
808 add_hook(&match_function_call, FUNCTION_CALL_HOOK);
809 add_hook(&match_assign_call, CALL_ASSIGNMENT_HOOK);
810 add_hook(&match_macro_assign, MACRO_ASSIGNMENT_HOOK);