kernel_irq_context: add (struct irqaction)->handler as an ignored function
[smatch.git] / smatch_flow.c
blobee026ebb5250d79d96f1b154599bf94110e13cf2
1 /*
2 * Copyright (C) 2006,2008 Dan Carpenter.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
18 #define _GNU_SOURCE 1
19 #include <unistd.h>
20 #include <stdio.h>
21 #include "token.h"
22 #include "scope.h"
23 #include "smatch.h"
24 #include "smatch_expression_stacks.h"
25 #include "smatch_extra.h"
26 #include "smatch_slist.h"
28 int __in_fake_assign;
29 int __in_fake_struct_assign;
30 int __in_buf_clear;
31 int __in_fake_var_assign;
32 int __fake_state_cnt;
33 int __debug_skip;
34 int in_fake_env;
35 int final_pass;
36 int __inline_call;
37 struct expression *__inline_fn;
39 int __smatch_lineno = 0;
41 static char *base_file;
42 static const char *filename;
43 static char *pathname;
44 static char *full_filename;
45 static char *full_base_file;
46 static char *cur_func;
47 int base_file_stream;
48 static unsigned int loop_count;
49 static int last_goto_statement_handled;
50 int __expr_stmt_count;
51 int __in_function_def;
52 int __in_unmatched_hook;
53 static struct expression_list *switch_expr_stack = NULL;
54 static struct expression_list *post_op_stack = NULL;
56 static struct ptr_list *fn_data_list;
57 static struct ptr_list *backup;
59 struct expression_list *big_expression_stack;
60 struct statement_list *big_statement_stack;
61 struct statement *__prev_stmt;
62 struct statement *__cur_stmt;
63 struct statement *__next_stmt;
64 static struct expression_list *parsed_calls;
65 static int indent_cnt;
66 int __in_pre_condition = 0;
67 int __bail_on_rest_of_function = 0;
68 static struct timeval fn_start_time;
69 static struct timeval outer_fn_start_time;
70 char *get_function(void) { return cur_func; }
71 int get_lineno(void) { return __smatch_lineno; }
72 int inside_loop(void) { return !!loop_count; }
73 int definitely_inside_loop(void) { return !!(loop_count & ~0x08000000); }
74 struct expression *get_switch_expr(void) { return top_expression(switch_expr_stack); }
75 int in_expression_statement(void) { return !!__expr_stmt_count; }
77 static void split_symlist(struct symbol_list *sym_list);
78 static void split_declaration(struct symbol_list *sym_list);
79 static void split_expr_list(struct expression_list *expr_list, struct expression *parent);
80 static void split_args(struct expression *expr);
81 static struct expression *fake_a_variable_assign(struct symbol *type, struct expression *call, struct expression *expr, int nr);
82 static void add_inline_function(struct symbol *sym);
83 static void parse_inline(struct expression *expr);
85 int option_assume_loops = 0;
86 int option_two_passes = 0;
87 struct symbol *cur_func_sym = NULL;
88 struct stree *global_states;
90 const unsigned long valid_ptr_min = 4096;
91 unsigned long valid_ptr_max = ULONG_MAX & ~(MTAG_OFFSET_MASK);
92 const sval_t valid_ptr_min_sval = {
93 .type = &ptr_ctype,
94 {.value = 4096},
96 sval_t ptr_err_min = { .type = &ptr_ctype };
97 sval_t ptr_err_max = { .type = &ptr_ctype };
98 sval_t ulong_ULONG_MAX = { .type = &ulong_ctype };
100 sval_t valid_ptr_max_sval = {
101 .type = &ptr_ctype,
102 {.value = ULONG_MAX & ~(MTAG_OFFSET_MASK)},
104 struct range_list *valid_ptr_rl;
106 void alloc_ptr_constants(void)
108 valid_ptr_max = sval_type_max(&ulong_ctype).value & ~(MTAG_OFFSET_MASK);
109 valid_ptr_max_sval.value = valid_ptr_max;
111 valid_ptr_rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
112 valid_ptr_rl = cast_rl(&ptr_ctype, valid_ptr_rl);
113 valid_ptr_rl = clone_rl_permanent(valid_ptr_rl);
115 ptr_err_min = sval_cast(&ptr_ctype, err_min);
116 ptr_err_max = sval_cast(&ptr_ctype, err_max);
117 ulong_ULONG_MAX = sval_type_max(&ulong_ctype);
120 int outside_of_function(void)
122 return cur_func_sym == NULL;
125 const char *get_filename(void)
127 if (option_info && option_full_path)
128 return full_base_file;
129 if (option_info)
130 return base_file;
131 if (option_full_path)
132 return full_filename;
133 return filename;
136 const char *get_base_file(void)
138 if (option_full_path)
139 return full_base_file;
140 return base_file;
143 unsigned long long get_file_id(void)
145 return str_to_llu_hash(get_filename());
148 unsigned long long get_base_file_id(void)
150 return str_to_llu_hash(get_base_file());
153 static void set_position(struct position pos)
155 int len;
156 static int prev_stream = -1;
158 if (in_fake_env)
159 return;
161 if (pos.stream == 0 && pos.line == 0)
162 return;
164 __smatch_lineno = pos.line;
166 if (pos.stream == prev_stream)
167 return;
169 prev_stream = pos.stream;
170 filename = stream_name(pos.stream);
172 free(full_filename);
173 pathname = getcwd(NULL, 0);
174 if (pathname) {
175 len = strlen(pathname) + 1 + strlen(filename) + 1;
176 full_filename = malloc(len);
177 snprintf(full_filename, len, "%s/%s", pathname, filename);
178 } else {
179 full_filename = alloc_string(filename);
181 free(pathname);
184 int is_assigned_call(struct expression *expr)
186 struct expression *parent = expr_get_parent_expr(expr);
188 if (parent &&
189 parent->type == EXPR_ASSIGNMENT &&
190 parent->op == '=' &&
191 strip_expr(parent->right) == expr)
192 return 1;
194 return 0;
197 int is_fake_assigned_call(struct expression *expr)
199 struct expression *parent = expr_get_fake_parent_expr(expr);
201 if (parent &&
202 parent->type == EXPR_ASSIGNMENT &&
203 parent->op == '=' &&
204 strip_expr(parent->right) == expr)
205 return 1;
207 return 0;
210 static bool is_inline_func(struct expression *expr)
212 if (expr->type != EXPR_SYMBOL || !expr->symbol)
213 return false;
214 if (!expr->symbol->definition)
215 return false;
216 if (expr->symbol->definition->ctype.modifiers & MOD_INLINE)
217 return true;
219 return 0;
222 static int is_noreturn_func(struct expression *expr)
224 if (expr->type != EXPR_SYMBOL || !expr->symbol)
225 return 0;
228 * It's almost impossible for Smatch to handle __builtin_constant_p()
229 * the same way that GCC does so Smatch ends up making some functions
230 * as no return functions incorrectly.
233 if (option_project == PROJ_KERNEL && expr->symbol->ident &&
234 strstr(expr->symbol->ident->name, "__compiletime_assert"))
235 return 0;
237 if (expr->symbol->ctype.modifiers & MOD_NORETURN)
238 return 1;
239 return 0;
242 static int save_func_time(void *_rl, int argc, char **argv, char **azColName)
244 unsigned long *rl = _rl;
246 *rl = strtoul(argv[0], NULL, 10);
247 return 0;
250 static int get_func_time(struct symbol *sym)
252 unsigned long time = 0;
254 run_sql(&save_func_time, &time,
255 "select key from return_implies where %s and type = %d;",
256 get_static_filter(sym), FUNC_TIME);
258 return time;
261 static int inline_budget = 20;
263 int inlinable(struct expression *expr)
265 struct symbol *sym;
266 struct statement *last_stmt = NULL;
268 if (__inline_fn) /* don't nest */
269 return 0;
271 if (expr->type != EXPR_SYMBOL || !expr->symbol)
272 return 0;
273 if (is_no_inline_function(expr->symbol->ident->name))
274 return 0;
275 sym = get_base_type(expr->symbol);
276 if (sym->stmt && sym->stmt->type == STMT_COMPOUND) {
277 if (ptr_list_size((struct ptr_list *)sym->stmt->stmts) > 10)
278 return 0;
279 if (sym->stmt->type != STMT_COMPOUND)
280 return 0;
281 last_stmt = last_ptr_list((struct ptr_list *)sym->stmt->stmts);
283 if (sym->inline_stmt && sym->inline_stmt->type == STMT_COMPOUND) {
284 if (ptr_list_size((struct ptr_list *)sym->inline_stmt->stmts) > 10)
285 return 0;
286 if (sym->inline_stmt->type != STMT_COMPOUND)
287 return 0;
288 last_stmt = last_ptr_list((struct ptr_list *)sym->inline_stmt->stmts);
291 if (!last_stmt)
292 return 0;
294 /* the magic numbers in this function are pulled out of my bum. */
295 if (last_stmt->pos.line > sym->pos.line + inline_budget)
296 return 0;
298 if (get_func_time(expr->symbol) >= 2)
299 return 0;
301 return 1;
304 void __process_post_op_stack(void)
306 struct expression *expr;
308 FOR_EACH_PTR(post_op_stack, expr) {
309 __pass_to_client(expr, OP_HOOK);
310 } END_FOR_EACH_PTR(expr);
312 __free_ptr_list((struct ptr_list **)&post_op_stack);
315 static int handle_comma_assigns(struct expression *expr)
317 struct expression *right;
318 struct expression *assign;
320 right = strip_expr(expr->right);
321 if (right->type != EXPR_COMMA)
322 return 0;
324 __split_expr(right->left);
325 __process_post_op_stack();
327 assign = assign_expression(expr->left, '=', right->right);
328 __split_expr(assign);
330 return 1;
333 /* This is to handle *p++ = foo; assignments */
334 static int handle_postop_assigns(struct expression *expr)
336 struct expression *left, *fake_left;
337 struct expression *assign;
339 left = strip_expr(expr->left);
340 if (left->type != EXPR_PREOP || left->op != '*')
341 return 0;
342 left = strip_expr(left->unop);
343 if (left->type != EXPR_POSTOP)
344 return 0;
346 fake_left = deref_expression(strip_expr(left->unop));
347 assign = assign_expression(fake_left, '=', expr->right);
349 __split_expr(assign);
350 __split_expr(expr->left);
352 return 1;
355 static bool parent_is_dereference(struct expression *expr)
357 struct expression *parent;
359 parent = expr;
360 while ((parent = expr_get_parent_expr(parent))) {
361 if (parent->type == EXPR_DEREF)
362 return true;
363 if (parent->type == EXPR_PREOP &&
364 parent->op == '*')
365 return true;
368 return false;
371 static int prev_expression_is_getting_address(struct expression *expr)
373 struct expression *parent;
375 do {
376 parent = expr_get_parent_expr(expr);
378 if (!parent)
379 return 0;
380 if (parent->type == EXPR_PREOP && parent->op == '&') {
381 if (parent_is_dereference(parent))
382 return false;
383 return true;
385 if (parent->type == EXPR_PREOP && parent->op == '(')
386 goto next;
387 if (parent->type == EXPR_DEREF && parent->op == '.')
388 goto next;
389 /* Handle &foo->array[offset] */
390 if (parent->type == EXPR_BINOP && parent->op == '+') {
391 parent = expr_get_parent_expr(parent);
392 if (!parent)
393 return 0;
394 if (parent->type == EXPR_PREOP && parent->op == '*')
395 goto next;
398 return 0;
399 next:
400 expr = parent;
401 } while (1);
404 int __in_builtin_overflow_func;
405 static void handle_builtin_overflow_func(struct expression *expr)
407 struct expression *a, *b, *res, *assign;
408 int op;
410 if (sym_name_is("__builtin_add_overflow", expr->fn))
411 op = '+';
412 else if (sym_name_is("__builtin_sub_overflow", expr->fn))
413 op = '-';
414 else if (sym_name_is("__builtin_mul_overflow", expr->fn))
415 op = '*';
416 else
417 return;
419 a = get_argument_from_call_expr(expr->args, 0);
420 b = get_argument_from_call_expr(expr->args, 1);
421 res = get_argument_from_call_expr(expr->args, 2);
423 assign = assign_expression(deref_expression(res), '=', binop_expression(a, op, b));
425 __in_builtin_overflow_func++;
426 __split_expr(assign);
427 __in_builtin_overflow_func--;
430 static int handle__builtin_choose_expr(struct expression *expr)
432 struct expression *const_expr, *expr1, *expr2;
433 sval_t sval;
435 if (!sym_name_is("__builtin_choose_expr", expr->fn))
436 return 0;
438 const_expr = get_argument_from_call_expr(expr->args, 0);
439 expr1 = get_argument_from_call_expr(expr->args, 1);
440 expr2 = get_argument_from_call_expr(expr->args, 2);
442 if (!get_value(const_expr, &sval) || !expr1 || !expr2)
443 return 0;
444 if (sval.value)
445 __split_expr(expr1);
446 else
447 __split_expr(expr2);
448 return 1;
451 static int handle__builtin_choose_expr_assigns(struct expression *expr)
453 struct expression *const_expr, *right, *expr1, *expr2, *fake;
454 sval_t sval;
457 * We can't use strip_no_cast() because it strips out
458 * __builtin_choose_expr() which turns this function into a no-op.
461 right = strip_parens(expr->right);
462 if (right->type != EXPR_CALL)
463 return 0;
464 if (!sym_name_is("__builtin_choose_expr", right->fn))
465 return 0;
467 const_expr = get_argument_from_call_expr(right->args, 0);
468 expr1 = get_argument_from_call_expr(right->args, 1);
469 expr2 = get_argument_from_call_expr(right->args, 2);
471 if (!get_value(const_expr, &sval) || !expr1 || !expr2)
472 return 0;
474 fake = assign_expression(expr->left, '=', sval.value ? expr1 : expr2);
475 __split_expr(fake);
476 return 1;
479 int is_condition_call(struct expression *expr)
481 struct expression *tmp;
483 FOR_EACH_PTR_REVERSE(big_condition_stack, tmp) {
484 if (expr == tmp || expr_get_parent_expr(expr) == tmp)
485 return 1;
486 if (tmp->pos.line < expr->pos.line)
487 return 0;
488 } END_FOR_EACH_PTR_REVERSE(tmp);
490 return 0;
493 static struct expression *expr_get_parent_no_parens(struct expression *expr)
495 do {
496 expr = expr_get_parent_expr(expr);
497 } while (expr &&
498 expr->type == EXPR_PREOP &&
499 expr->op == '(');
501 return expr;
504 static bool gen_fake_function_assign(struct expression *expr)
506 static struct expression *parsed;
507 struct expression *assign, *parent;
508 struct symbol *type;
509 char buf[64];
511 /* The rule is that every non-void function call has to be part of an
512 * assignment. TODO: Should we create a fake non-casted assignment
513 * for casted assignments? Also faked assigns for += assignments?
515 type = get_type(expr);
516 if (!type || type == &void_ctype)
517 return false;
519 parent = expr_get_parent_no_parens(expr);
520 if (parent && parent->type == EXPR_ASSIGNMENT)
521 return false;
523 parent = expr_get_fake_parent_expr(expr);
524 if (parent) {
525 struct expression *left = parent->left;
527 if (parent == parsed)
528 return false;
529 if (!left || left->type != EXPR_SYMBOL)
530 return false;
531 if (strncmp(left->symbol_name->name, "__fake_assign_", 14) != 0)
532 return false;
533 parsed = parent;
534 __split_expr(parent);
535 return true;
538 // TODO: faked_assign skipping conditions is a hack
539 if (is_condition_call(expr))
540 return false;
542 snprintf(buf, sizeof(buf), "__fake_assign_%p", expr);
543 assign = create_fake_assign(buf, get_type(expr), expr);
545 parsed = assign;
546 __split_expr(assign);
547 return true;
550 static void split_call(struct expression *expr)
552 if (gen_fake_function_assign(expr))
553 return;
555 expr_set_parent_expr(expr->fn, expr);
557 if (sym_name_is("__builtin_constant_p", expr->fn))
558 return;
559 if (handle__builtin_choose_expr(expr))
560 return;
561 __split_expr(expr->fn);
562 split_args(expr);
563 if (is_inline_func(expr->fn))
564 add_inline_function(expr->fn->symbol->definition);
565 if (inlinable(expr->fn))
566 __inline_call = 1;
567 __process_post_op_stack();
568 __pass_to_client(expr, FUNCTION_CALL_HOOK_BEFORE);
569 __pass_to_client(expr, FUNCTION_CALL_HOOK);
570 __inline_call = 0;
571 if (inlinable(expr->fn))
572 parse_inline(expr);
573 __pass_to_client(expr, CALL_HOOK_AFTER_INLINE);
574 if (is_noreturn_func(expr->fn))
575 nullify_path();
576 if (!expr_get_parent_expr(expr) && indent_cnt == 1)
577 __discard_fake_states(expr);
578 handle_builtin_overflow_func(expr);
579 __add_ptr_list((struct ptr_list **)&parsed_calls, expr);
582 static unsigned long skip_split;
583 void parse_assignment(struct expression *expr, bool shallow)
585 struct expression *right;
587 expr_set_parent_expr(expr->left, expr);
588 expr_set_parent_expr(expr->right, expr);
590 right = strip_expr(expr->right);
591 if (!right)
592 return;
594 if (shallow)
595 skip_split++;
597 __pass_to_client(expr, RAW_ASSIGNMENT_HOOK);
599 /* foo = !bar() */
600 if (__handle_condition_assigns(expr))
601 goto after_assign;
602 /* foo = (x < 5 ? foo : 5); */
603 if (__handle_select_assigns(expr))
604 goto after_assign;
605 /* foo = ({frob(); frob(); frob(); 1;}) */
606 if (__handle_expr_statement_assigns(expr))
607 goto done; // FIXME: goto after
608 /* foo = (3, 4); */
609 if (handle_comma_assigns(expr))
610 goto after_assign;
611 if (handle__builtin_choose_expr_assigns(expr))
612 goto after_assign;
613 if (handle_postop_assigns(expr))
614 goto done; /* no need to goto after_assign */
616 __split_expr(expr->right);
617 if (outside_of_function())
618 __pass_to_client(expr, GLOBAL_ASSIGNMENT_HOOK);
619 else
620 __pass_to_client(expr, ASSIGNMENT_HOOK);
623 // FIXME: the ordering of this is tricky
624 __fake_struct_member_assignments(expr);
626 /* Re-examine ->right for inlines. See the commit message */
627 right = strip_expr(expr->right);
628 if (expr->op == '=' && right->type == EXPR_CALL)
629 __pass_to_client(expr, CALL_ASSIGNMENT_HOOK);
631 after_assign:
632 if (get_macro_name(right->pos) &&
633 get_macro_name(expr->left->pos) != get_macro_name(right->pos))
634 __pass_to_client(expr, MACRO_ASSIGNMENT_HOOK);
636 __pass_to_client(expr, ASSIGNMENT_HOOK_AFTER);
637 __split_expr(expr->left);
639 done:
640 if (shallow)
641 skip_split--;
644 static bool skip_split_off(struct expression *expr)
646 if (expr->type == EXPR_CALL &&
647 sym_name_is("__smatch_stop_skip", expr->fn))
648 return true;
649 return false;
652 void __split_expr(struct expression *expr)
654 if (!expr)
655 return;
657 if (skip_split_off(expr))
658 __debug_skip = 0;
659 if (__debug_skip)
660 return;
662 if (skip_split)
663 return;
665 // if (local_debug)
666 // sm_msg("Debug expr_type %d %s expr = '%s'", expr->type, show_special(expr->op), expr_to_str(expr));
668 if (__in_fake_assign && expr->type != EXPR_ASSIGNMENT)
669 return;
670 if (__in_fake_assign >= 4) /* don't allow too much nesting */
671 return;
673 push_expression(&big_expression_stack, expr);
674 set_position(expr->pos);
675 __pass_to_client(expr, EXPR_HOOK);
677 switch (expr->type) {
678 case EXPR_PREOP:
679 expr_set_parent_expr(expr->unop, expr);
681 __split_expr(expr->unop);
682 if (expr->op == '*' &&
683 !prev_expression_is_getting_address(expr))
684 __pass_to_client(expr, DEREF_HOOK);
685 __pass_to_client(expr, OP_HOOK);
686 break;
687 case EXPR_POSTOP:
688 expr_set_parent_expr(expr->unop, expr);
690 __split_expr(expr->unop);
691 push_expression(&post_op_stack, expr);
692 break;
693 case EXPR_STATEMENT:
694 __expr_stmt_count++;
695 if (expr->statement && !expr->statement) {
696 stmt_set_parent_stmt(expr->statement,
697 last_ptr_list((struct ptr_list *)big_statement_stack));
699 __split_stmt(expr->statement);
700 __expr_stmt_count--;
701 break;
702 case EXPR_LOGICAL:
703 case EXPR_COMPARE:
704 expr_set_parent_expr(expr->left, expr);
705 expr_set_parent_expr(expr->right, expr);
707 __pass_to_client(expr, LOGIC_HOOK);
708 __handle_logic(expr);
709 break;
710 case EXPR_BINOP:
711 expr_set_parent_expr(expr->left, expr);
712 expr_set_parent_expr(expr->right, expr);
714 __pass_to_client(expr, BINOP_HOOK);
715 __split_expr(expr->left);
716 __split_expr(expr->right);
717 break;
718 case EXPR_COMMA:
719 expr_set_parent_expr(expr->left, expr);
720 expr_set_parent_expr(expr->right, expr);
722 __split_expr(expr->left);
723 __process_post_op_stack();
724 __split_expr(expr->right);
725 break;
726 case EXPR_ASSIGNMENT:
727 parse_assignment(expr, false);
728 break;
729 case EXPR_DEREF:
730 expr_set_parent_expr(expr->deref, expr);
732 __split_expr(expr->deref);
733 __pass_to_client(expr, DEREF_HOOK);
734 break;
735 case EXPR_SLICE:
736 expr_set_parent_expr(expr->base, expr);
738 __split_expr(expr->base);
739 break;
740 case EXPR_CAST:
741 case EXPR_FORCE_CAST:
742 expr_set_parent_expr(expr->cast_expression, expr);
744 __pass_to_client(expr, CAST_HOOK);
745 __split_expr(expr->cast_expression);
746 break;
747 case EXPR_SIZEOF:
748 if (expr->cast_expression)
749 __pass_to_client(strip_parens(expr->cast_expression),
750 SIZEOF_HOOK);
751 break;
752 case EXPR_OFFSETOF:
753 case EXPR_ALIGNOF:
754 break;
755 case EXPR_CONDITIONAL:
756 case EXPR_SELECT:
757 expr_set_parent_expr(expr->conditional, expr);
758 expr_set_parent_expr(expr->cond_true, expr);
759 expr_set_parent_expr(expr->cond_false, expr);
761 if (known_condition_true(expr->conditional)) {
762 __split_expr(expr->cond_true);
763 break;
765 if (known_condition_false(expr->conditional)) {
766 __split_expr(expr->cond_false);
767 break;
769 __pass_to_client(expr, SELECT_HOOK);
770 __split_whole_condition(expr->conditional);
771 __split_expr(expr->cond_true);
772 __push_true_states();
773 __use_false_states();
774 __split_expr(expr->cond_false);
775 __merge_true_states();
776 break;
777 case EXPR_CALL:
778 split_call(expr);
779 break;
780 case EXPR_INITIALIZER:
781 split_expr_list(expr->expr_list, expr);
782 break;
783 case EXPR_IDENTIFIER:
784 expr_set_parent_expr(expr->ident_expression, expr);
785 __split_expr(expr->ident_expression);
786 break;
787 case EXPR_INDEX:
788 expr_set_parent_expr(expr->idx_expression, expr);
789 __split_expr(expr->idx_expression);
790 break;
791 case EXPR_POS:
792 expr_set_parent_expr(expr->init_expr, expr);
793 __split_expr(expr->init_expr);
794 break;
795 case EXPR_SYMBOL:
796 __pass_to_client(expr, SYM_HOOK);
797 break;
798 case EXPR_STRING:
799 __pass_to_client(expr, STRING_HOOK);
800 break;
801 case EXPR_GENERIC: {
802 struct expression *tmp;
804 tmp = strip_Generic(expr);
805 if (tmp != expr)
806 __split_expr(tmp);
807 break;
809 default:
810 break;
812 __pass_to_client(expr, EXPR_HOOK_AFTER);
813 pop_expression(&big_expression_stack);
816 static int is_forever_loop(struct statement *stmt)
818 struct expression *expr;
819 sval_t sval;
821 expr = strip_expr(stmt->iterator_pre_condition);
822 if (!expr)
823 expr = stmt->iterator_post_condition;
824 if (!expr) {
825 /* this is a for(;;) loop... */
826 return 1;
829 if (get_value(expr, &sval) && sval.value != 0)
830 return 1;
832 return 0;
835 static int loop_num;
836 static char *get_loop_name(int num)
838 char buf[256];
840 snprintf(buf, 255, "-loop%d", num);
841 buf[255] = '\0';
842 return alloc_sname(buf);
845 static struct bool_stmt_fn_list *once_through_hooks;
846 void add_once_through_hook(bool_stmt_func *fn)
848 add_ptr_list(&once_through_hooks, fn);
851 static bool call_once_through_hooks(struct statement *stmt)
853 bool_stmt_func *fn;
855 if (option_assume_loops)
856 return true;
858 FOR_EACH_PTR(once_through_hooks, fn) {
859 if ((fn)(stmt))
860 return true;
861 } END_FOR_EACH_PTR(fn);
863 return false;
867 * Pre Loops are while and for loops.
869 static void handle_pre_loop(struct statement *stmt)
871 int once_through; /* we go through the loop at least once */
872 struct sm_state *extra_sm = NULL;
873 int unchanged = 0;
874 char *loop_name;
875 struct stree *stree = NULL;
876 struct sm_state *sm = NULL;
878 __push_scope_hooks();
880 loop_name = get_loop_name(loop_num);
881 loop_num++;
883 split_declaration(stmt->iterator_syms);
884 if (stmt->iterator_pre_statement) {
885 __split_stmt(stmt->iterator_pre_statement);
886 __prev_stmt = stmt->iterator_pre_statement;
889 loop_count++;
890 __push_continues();
891 __push_breaks();
893 __merge_gotos(loop_name, NULL);
895 extra_sm = __extra_handle_canonical_loops(stmt, &stree);
896 __in_pre_condition++;
897 __set_confidence_implied();
898 __split_whole_condition_tf(stmt->iterator_pre_condition, &once_through);
899 __unset_confidence();
900 if (once_through != true)
901 once_through = call_once_through_hooks(stmt);
902 __pass_to_client(stmt, PRELOOP_HOOK);
903 __in_pre_condition--;
904 FOR_EACH_SM(stree, sm) {
905 set_state(sm->owner, sm->name, sm->sym, sm->state);
906 } END_FOR_EACH_SM(sm);
907 free_stree(&stree);
908 if (extra_sm)
909 extra_sm = get_sm_state(extra_sm->owner, extra_sm->name, extra_sm->sym);
911 __split_stmt(stmt->iterator_statement);
912 if (is_forever_loop(stmt)) {
913 __merge_continues();
914 __save_gotos(loop_name, NULL);
916 __push_fake_cur_stree();
917 __split_stmt(stmt->iterator_post_statement);
918 stree = __pop_fake_cur_stree();
920 __discard_false_states();
921 __pass_to_client(stmt, AFTER_LOOP_NO_BREAKS);
922 __use_breaks();
924 if (!__path_is_null())
925 __merge_stree_into_cur(stree);
926 free_stree(&stree);
927 } else {
928 __merge_continues();
929 unchanged = __iterator_unchanged(extra_sm);
930 __split_stmt(stmt->iterator_post_statement);
931 __prev_stmt = stmt->iterator_post_statement;
932 __cur_stmt = stmt;
934 __save_gotos(loop_name, NULL);
935 __in_pre_condition++;
936 __split_whole_condition(stmt->iterator_pre_condition);
937 __in_pre_condition--;
938 nullify_path();
939 __merge_false_states();
940 if (once_through == true)
941 __discard_false_states();
942 else
943 __merge_false_states();
945 if (extra_sm && unchanged)
946 __extra_pre_loop_hook_after(extra_sm,
947 stmt->iterator_post_statement,
948 stmt->iterator_pre_condition);
949 __pass_to_client(stmt, AFTER_LOOP_NO_BREAKS);
950 __merge_breaks();
952 loop_count--;
954 __call_scope_hooks();
958 * Post loops are do {} while();
960 static void handle_post_loop(struct statement *stmt)
962 char *loop_name;
964 loop_name = get_loop_name(loop_num);
965 loop_num++;
966 loop_count++;
968 __pass_to_client(stmt, POSTLOOP_HOOK);
970 __push_continues();
971 __push_breaks();
972 __merge_gotos(loop_name, NULL);
973 __split_stmt(stmt->iterator_statement);
974 __merge_continues();
975 if (!expr_is_zero(stmt->iterator_post_condition))
976 __save_gotos(loop_name, NULL);
978 if (is_forever_loop(stmt)) {
979 __pass_to_client(stmt, AFTER_LOOP_NO_BREAKS);
980 __use_breaks();
981 } else {
982 __split_whole_condition(stmt->iterator_post_condition);
983 __use_false_states();
984 __pass_to_client(stmt, AFTER_LOOP_NO_BREAKS);
985 __merge_breaks();
987 loop_count--;
990 static int empty_statement(struct statement *stmt)
992 if (!stmt)
993 return 0;
994 if (stmt->type == STMT_EXPRESSION && !stmt->expression)
995 return 1;
996 return 0;
999 static int last_stmt_on_same_line(void)
1001 struct statement *stmt;
1002 int i = 0;
1004 FOR_EACH_PTR_REVERSE(big_statement_stack, stmt) {
1005 if (!i++)
1006 continue;
1007 if (stmt->pos.line == get_lineno())
1008 return 1;
1009 return 0;
1010 } END_FOR_EACH_PTR_REVERSE(stmt);
1011 return 0;
1014 static void split_asm_ops(struct asm_operand_list *ops)
1016 struct asm_operand *op;
1018 FOR_EACH_PTR(ops, op) {
1019 __split_expr(op->expr);
1020 } END_FOR_EACH_PTR(op);
1023 static int is_case_val(struct statement *stmt, sval_t sval)
1025 sval_t case_sval;
1027 if (stmt->type != STMT_CASE)
1028 return 0;
1029 if (!stmt->case_expression) {
1030 __set_default();
1031 return 1;
1033 if (!get_value(stmt->case_expression, &case_sval))
1034 return 0;
1035 if (case_sval.value == sval.value)
1036 return 1;
1037 return 0;
1040 static struct range_list *get_case_rl(struct expression *switch_expr,
1041 struct expression *case_expr,
1042 struct expression *case_to)
1044 sval_t start, end;
1045 struct range_list *rl = NULL;
1046 struct symbol *switch_type;
1048 switch_type = get_type(switch_expr);
1049 if (get_value(case_to, &end) && get_value(case_expr, &start)) {
1050 start = sval_cast(switch_type, start);
1051 end = sval_cast(switch_type, end);
1052 add_range(&rl, start, end);
1053 } else if (get_value(case_expr, &start)) {
1054 start = sval_cast(switch_type, start);
1055 add_range(&rl, start, start);
1058 return rl;
1061 static void split_known_switch(struct statement *stmt, sval_t sval)
1063 struct statement *tmp;
1064 struct range_list *rl;
1066 __split_expr(stmt->switch_expression);
1067 sval = sval_cast(get_type(stmt->switch_expression), sval);
1069 push_expression(&switch_expr_stack, stmt->switch_expression);
1070 __save_switch_states(top_expression(switch_expr_stack));
1071 nullify_path();
1072 __push_default();
1073 __push_breaks();
1075 stmt = stmt->switch_statement;
1077 __push_scope_hooks();
1078 FOR_EACH_PTR(stmt->stmts, tmp) {
1079 __smatch_lineno = tmp->pos.line;
1080 // FIXME: what if default comes before the known case statement?
1081 if (is_case_val(tmp, sval)) {
1082 rl = alloc_rl(sval, sval);
1083 __merge_switches(top_expression(switch_expr_stack), rl);
1084 __pass_case_to_client(top_expression(switch_expr_stack), rl);
1085 stmt_set_parent_stmt(tmp->case_statement, tmp);
1086 __split_stmt(tmp->case_statement);
1087 goto next;
1089 if (__path_is_null())
1090 continue;
1091 __split_stmt(tmp);
1092 next:
1093 if (__path_is_null()) {
1094 __set_default();
1095 goto out;
1097 } END_FOR_EACH_PTR(tmp);
1098 out:
1099 __call_scope_hooks();
1100 if (!__pop_default())
1101 __merge_switches(top_expression(switch_expr_stack), NULL);
1102 __discard_switches();
1103 __merge_breaks();
1104 pop_expression(&switch_expr_stack);
1107 static void split_case(struct statement *stmt)
1109 struct range_list *rl = NULL;
1111 expr_set_parent_stmt(stmt->case_expression, stmt);
1112 expr_set_parent_stmt(stmt->case_to, stmt);
1114 rl = get_case_rl(top_expression(switch_expr_stack),
1115 stmt->case_expression, stmt->case_to);
1116 while (stmt->case_statement->type == STMT_CASE) {
1117 struct range_list *tmp;
1119 tmp = get_case_rl(top_expression(switch_expr_stack),
1120 stmt->case_statement->case_expression,
1121 stmt->case_statement->case_to);
1122 if (!tmp)
1123 goto next;
1124 rl = rl_union(rl, tmp);
1125 if (!stmt->case_expression)
1126 __set_default();
1127 next:
1128 stmt = stmt->case_statement;
1131 __merge_switches(top_expression(switch_expr_stack), rl);
1133 if (!stmt->case_expression)
1134 __set_default();
1136 stmt_set_parent_stmt(stmt->case_statement, stmt);
1137 __split_stmt(stmt->case_statement);
1140 int time_parsing_function(void)
1142 return ms_since(&fn_start_time) / 1000;
1145 bool taking_too_long(void)
1147 if ((ms_since(&outer_fn_start_time) / 1000) > 60 * 5) /* five minutes */
1148 return 1;
1149 return 0;
1152 struct statement *get_last_stmt(void)
1154 struct symbol *fn;
1155 struct statement *stmt;
1157 fn = get_base_type(cur_func_sym);
1158 if (!fn)
1159 return NULL;
1160 stmt = fn->stmt;
1161 if (!stmt)
1162 stmt = fn->inline_stmt;
1163 if (!stmt || stmt->type != STMT_COMPOUND)
1164 return NULL;
1165 stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
1166 if (stmt && stmt->type == STMT_LABEL)
1167 stmt = stmt->label_statement;
1168 return stmt;
1171 int is_last_stmt(struct statement *cur_stmt)
1173 struct statement *last;
1175 last = get_last_stmt();
1176 if (last && last == cur_stmt)
1177 return 1;
1178 return 0;
1181 static bool is_function_scope(struct statement *stmt)
1183 struct symbol *base_type;
1185 if (!cur_func_sym)
1186 return false;
1188 base_type = get_base_type(cur_func_sym);
1189 if (base_type->stmt == stmt ||
1190 base_type->inline_stmt == stmt)
1191 return true;
1193 return false;
1196 static void handle_backward_goto(struct statement *goto_stmt)
1198 const char *goto_name, *label_name;
1199 struct statement *func_stmt;
1200 struct symbol *base_type = get_base_type(cur_func_sym);
1201 struct statement *tmp;
1202 int found = 0;
1204 if (!option_info)
1205 return;
1206 if (last_goto_statement_handled)
1207 return;
1208 last_goto_statement_handled = 1;
1210 if (!goto_stmt->goto_label ||
1211 goto_stmt->goto_label->type != SYM_LABEL ||
1212 !goto_stmt->goto_label->ident)
1213 return;
1214 goto_name = goto_stmt->goto_label->ident->name;
1216 func_stmt = base_type->stmt;
1217 if (!func_stmt)
1218 func_stmt = base_type->inline_stmt;
1219 if (!func_stmt)
1220 return;
1221 if (func_stmt->type != STMT_COMPOUND)
1222 return;
1224 FOR_EACH_PTR(func_stmt->stmts, tmp) {
1225 if (!found) {
1226 if (tmp->type != STMT_LABEL)
1227 continue;
1228 if (!tmp->label_identifier ||
1229 tmp->label_identifier->type != SYM_LABEL ||
1230 !tmp->label_identifier->ident)
1231 continue;
1232 label_name = tmp->label_identifier->ident->name;
1233 if (strcmp(goto_name, label_name) != 0)
1234 continue;
1235 found = 1;
1237 __split_stmt(tmp);
1238 } END_FOR_EACH_PTR(tmp);
1241 static void fake_a_return(void)
1243 struct expression *ret = NULL;
1245 nullify_path();
1246 __unnullify_path();
1248 if (cur_func_return_type() != &void_ctype)
1249 ret = unknown_value_expression(NULL);
1251 __pass_to_client(ret, RETURN_HOOK);
1252 nullify_path();
1255 static void split_ret_value(struct expression *expr)
1257 struct symbol *type;
1259 if (!expr)
1260 return;
1262 type = get_real_base_type(cur_func_sym);
1263 type = get_real_base_type(type);
1264 expr = fake_a_variable_assign(type, NULL, expr, -1);
1266 __in_fake_var_assign++;
1267 __split_expr(expr);
1268 __in_fake_var_assign--;
1271 static void fake_an_empty_default(struct position pos)
1273 static struct statement none = {};
1275 none.pos = pos;
1276 none.type = STMT_NONE;
1277 __merge_switches(top_expression(switch_expr_stack), NULL);
1278 __split_stmt(&none);
1281 static void split_compound(struct statement *stmt)
1283 struct statement *prev = NULL;
1284 struct statement *cur = NULL;
1285 struct statement *next;
1287 __push_scope_hooks();
1289 FOR_EACH_PTR(stmt->stmts, next) {
1290 /* just set them all ahead of time */
1291 stmt_set_parent_stmt(next, stmt);
1293 if (cur) {
1294 __prev_stmt = prev;
1295 __next_stmt = next;
1296 __cur_stmt = cur;
1297 __split_stmt(cur);
1299 prev = cur;
1300 cur = next;
1301 } END_FOR_EACH_PTR(next);
1302 if (cur) {
1303 __prev_stmt = prev;
1304 __cur_stmt = cur;
1305 __next_stmt = NULL;
1306 __split_stmt(cur);
1310 * For function scope, then delay calling the scope hooks until the
1311 * end of function hooks can run.
1313 if (!is_function_scope(stmt))
1314 __call_scope_hooks();
1317 void __split_label_stmt(struct statement *stmt)
1319 if (stmt->label_identifier &&
1320 stmt->label_identifier->type == SYM_LABEL &&
1321 stmt->label_identifier->ident) {
1322 loop_count |= 0x0800000;
1323 __merge_gotos(stmt->label_identifier->ident->name, stmt->label_identifier);
1327 static void find_asm_gotos(struct statement *stmt)
1329 struct symbol *sym;
1331 FOR_EACH_PTR(stmt->asm_labels, sym) {
1332 __save_gotos(sym->ident->name, sym);
1333 } END_FOR_EACH_PTR(sym);
1336 static void split_if_statement(struct statement *stmt)
1338 int known_tf;
1340 stmt_set_parent_stmt(stmt->if_true, stmt);
1341 stmt_set_parent_stmt(stmt->if_false, stmt);
1342 expr_set_parent_stmt(stmt->if_conditional, stmt);
1344 if (empty_statement(stmt->if_true) &&
1345 last_stmt_on_same_line() &&
1346 !get_macro_name(stmt->if_true->pos))
1347 sm_warning("if();");
1349 __split_whole_condition_tf(stmt->if_conditional, &known_tf);
1350 if (known_tf == true) {
1351 __split_stmt(stmt->if_true);
1352 __discard_false_states();
1353 return;
1354 } else if (known_tf == false) {
1355 __use_false_states();
1356 __split_stmt(stmt->if_false);
1357 return;
1360 __split_stmt(stmt->if_true);
1361 __push_true_states();
1362 __use_false_states();
1363 __split_stmt(stmt->if_false);
1364 __merge_true_states();
1367 static bool already_parsed_call(struct expression *call)
1369 struct expression *expr;
1371 FOR_EACH_PTR(parsed_calls, expr) {
1372 if (expr == call)
1373 return true;
1374 } END_FOR_EACH_PTR(expr);
1375 return false;
1378 static void free_parsed_call_stuff(bool free_fake_states)
1380 free_expression_stack(&parsed_calls);
1381 if (free_fake_states)
1382 __discard_fake_states(NULL);
1385 void __split_stmt(struct statement *stmt)
1387 sval_t sval;
1388 struct timeval start, stop;
1389 bool skip_after = false;
1391 gettimeofday(&start, NULL);
1393 if (!stmt)
1394 goto out;
1396 if (!__in_fake_assign)
1397 __silence_warnings_for_stmt = false;
1399 if (__bail_on_rest_of_function || is_skipped_function())
1400 return;
1402 if (out_of_memory() || taking_too_long()) {
1403 gettimeofday(&start, NULL);
1405 __bail_on_rest_of_function = 1;
1406 final_pass = 1;
1407 sm_perror("Function too hairy. Giving up. %lu seconds",
1408 start.tv_sec - fn_start_time.tv_sec);
1409 fake_a_return();
1410 final_pass = 0; /* turn off sm_msg() from here */
1411 return;
1414 indent_cnt++;
1416 add_ptr_list(&big_statement_stack, stmt);
1417 free_expression_stack(&big_expression_stack);
1418 free_parsed_call_stuff(indent_cnt == 1);
1419 set_position(stmt->pos);
1420 __pass_to_client(stmt, STMT_HOOK);
1422 switch (stmt->type) {
1423 case STMT_DECLARATION:
1424 split_declaration(stmt->declaration);
1425 break;
1426 case STMT_RETURN:
1427 expr_set_parent_stmt(stmt->ret_value, stmt);
1429 split_ret_value(stmt->ret_value);
1430 __process_post_op_stack();
1431 __call_all_scope_hooks();
1432 __pass_to_client(stmt->ret_value, RETURN_HOOK);
1433 nullify_path();
1434 break;
1435 case STMT_EXPRESSION:
1436 expr_set_parent_stmt(stmt->expression, stmt);
1437 expr_set_parent_stmt(stmt->context, stmt);
1439 __split_expr(stmt->expression);
1440 break;
1441 case STMT_COMPOUND:
1442 split_compound(stmt);
1443 break;
1444 case STMT_IF:
1445 split_if_statement(stmt);
1446 break;
1447 case STMT_ITERATOR:
1448 stmt_set_parent_stmt(stmt->iterator_pre_statement, stmt);
1449 stmt_set_parent_stmt(stmt->iterator_statement, stmt);
1450 stmt_set_parent_stmt(stmt->iterator_post_statement, stmt);
1451 expr_set_parent_stmt(stmt->iterator_pre_condition, stmt);
1452 expr_set_parent_stmt(stmt->iterator_post_condition, stmt);
1454 if (stmt->iterator_pre_condition)
1455 handle_pre_loop(stmt);
1456 else if (stmt->iterator_post_condition)
1457 handle_post_loop(stmt);
1458 else {
1459 // these are for(;;) type loops.
1460 handle_pre_loop(stmt);
1462 break;
1463 case STMT_SWITCH:
1464 stmt_set_parent_stmt(stmt->switch_statement, stmt);
1465 expr_set_parent_stmt(stmt->switch_expression, stmt);
1467 if (get_value(stmt->switch_expression, &sval)) {
1468 split_known_switch(stmt, sval);
1469 break;
1471 __split_expr(stmt->switch_expression);
1472 push_expression(&switch_expr_stack, stmt->switch_expression);
1473 __save_switch_states(top_expression(switch_expr_stack));
1474 nullify_path();
1475 __push_default();
1476 __push_breaks();
1477 __split_stmt(stmt->switch_statement);
1478 if (!__pop_default() && have_remaining_cases())
1479 fake_an_empty_default(stmt->pos);
1480 __discard_switches();
1481 __merge_breaks();
1482 pop_expression(&switch_expr_stack);
1483 break;
1484 case STMT_CASE:
1485 split_case(stmt);
1486 break;
1487 case STMT_LABEL:
1488 __split_label_stmt(stmt);
1489 __pass_to_client(stmt, STMT_HOOK_AFTER);
1490 skip_after = true;
1491 __split_stmt(stmt->label_statement);
1492 break;
1493 case STMT_GOTO:
1494 expr_set_parent_stmt(stmt->goto_expression, stmt);
1496 __split_expr(stmt->goto_expression);
1497 if (stmt->goto_label && stmt->goto_label->type == SYM_NODE) {
1498 if (!strcmp(stmt->goto_label->ident->name, "break")) {
1499 __process_breaks();
1500 } else if (!strcmp(stmt->goto_label->ident->name,
1501 "continue")) {
1502 __process_continues();
1504 } else if (stmt->goto_label &&
1505 stmt->goto_label->type == SYM_LABEL &&
1506 stmt->goto_label->ident) {
1507 __save_gotos(stmt->goto_label->ident->name, stmt->goto_label);
1509 nullify_path();
1510 if (is_last_stmt(stmt))
1511 handle_backward_goto(stmt);
1512 break;
1513 case STMT_NONE:
1514 break;
1515 case STMT_ASM:
1516 expr_set_parent_stmt(stmt->asm_string, stmt);
1518 find_asm_gotos(stmt);
1519 __pass_to_client(stmt, ASM_HOOK);
1520 __split_expr(stmt->asm_string);
1521 split_asm_ops(stmt->asm_outputs);
1522 split_asm_ops(stmt->asm_inputs);
1523 split_expr_list(stmt->asm_clobbers, NULL);
1524 break;
1525 case STMT_CONTEXT:
1526 break;
1527 case STMT_RANGE:
1528 __split_expr(stmt->range_expression);
1529 __split_expr(stmt->range_low);
1530 __split_expr(stmt->range_high);
1531 break;
1533 if (!skip_after)
1534 __pass_to_client(stmt, STMT_HOOK_AFTER);
1535 if (--indent_cnt == 1)
1536 free_parsed_call_stuff(true);
1538 out:
1539 __process_post_op_stack();
1541 gettimeofday(&stop, NULL);
1542 if (option_time_stmt && stmt)
1543 sm_msg("stmt_time%s: %ld",
1544 stmt->type == STMT_COMPOUND ? "_block" : "",
1545 stop.tv_sec - start.tv_sec);
1548 static void split_expr_list(struct expression_list *expr_list, struct expression *parent)
1550 struct expression *expr;
1552 FOR_EACH_PTR(expr_list, expr) {
1553 expr_set_parent_expr(expr, parent);
1554 __split_expr(expr);
1555 __process_post_op_stack();
1556 } END_FOR_EACH_PTR(expr);
1559 static bool cast_arg(struct symbol *type, struct expression *arg)
1561 struct symbol *orig;
1563 if (!type)
1564 return false;
1566 arg = strip_parens(arg);
1567 if (arg != strip_expr(arg))
1568 return true;
1570 orig = get_type(arg);
1571 if (!orig)
1572 return true;
1573 if (types_equiv(orig, type))
1574 return false;
1576 if (orig->type == SYM_ARRAY && type->type == SYM_PTR)
1577 return true;
1580 * I would have expected that we could just do use (orig == type) but I
1581 * guess for pointers we need to get the basetype to do that comparison.
1585 if (orig->type != SYM_PTR ||
1586 type->type != SYM_PTR) {
1587 if (type_fits(type, orig))
1588 return false;
1589 return true;
1591 orig = get_real_base_type(orig);
1592 type = get_real_base_type(type);
1593 if (orig == type)
1594 return false;
1596 return true;
1599 static struct expression *fake_a_variable_assign(struct symbol *type, struct expression *call, struct expression *expr, int nr)
1601 char buf[64];
1602 bool cast;
1604 if (!expr || !cur_func_sym)
1605 return NULL;
1607 if (already_parsed_call(call))
1608 return NULL;
1610 if (expr->type == EXPR_ASSIGNMENT)
1611 return expr;
1613 /* for va_args then we don't know the type */
1614 if (!type)
1615 type = get_type(expr);
1617 cast = cast_arg(type, expr);
1619 * Using expr_to_sym() here is a hack. We want to say that we don't
1620 * need to assign frob(foo) or frob(foo->bar) if the types are right.
1621 * It turns out faking these assignments is way more expensive than I
1622 * would have imagined. I'm not sure why exactly.
1625 if (!cast) {
1627 * if the code is "return *p;" where "p" is a user pointer then
1628 * we want to create a fake assignment so that it sets the state
1629 * in check_kernel_user_data.c.
1632 if (expr->type != EXPR_PREOP &&
1633 expr->op != '*' && expr->op != '&' &&
1634 expr_to_sym(expr))
1635 return expr;
1638 if (nr == -1)
1639 snprintf(buf, sizeof(buf), "__fake_return_%p", expr);
1640 else
1641 snprintf(buf, sizeof(buf), "__fake_param_%p_%d", call, nr);
1643 return create_fake_assign(buf, type, expr);
1646 static void split_args(struct expression *expr)
1648 struct expression *arg, *tmp;
1649 struct symbol *type;
1650 int i;
1652 i = -1;
1653 FOR_EACH_PTR(expr->args, arg) {
1654 i++;
1655 expr_set_parent_expr(arg, expr);
1656 type = get_arg_type(expr->fn, i);
1657 tmp = fake_a_variable_assign(type, expr, arg, i);
1658 if (tmp != arg)
1659 __in_fake_var_assign++;
1660 __split_expr(tmp);
1661 if (tmp != arg)
1662 __in_fake_var_assign--;
1663 __process_post_op_stack();
1664 } END_FOR_EACH_PTR(arg);
1667 static void call_cleanup_fn(void *_sym)
1669 struct symbol *sym = _sym;
1670 struct expression *call, *arg;
1671 struct expression_list *args = NULL;
1673 arg = symbol_expression(sym);
1674 arg = preop_expression(arg, '&');
1675 add_ptr_list(&args, arg);
1676 call = call_expression(sym->cleanup, args);
1678 __split_expr(call);
1681 static void add_cleanup_hook(struct symbol *sym)
1683 if (!sym->cleanup)
1684 return;
1685 add_scope_hook(&call_cleanup_fn, sym);
1688 static void split_sym(struct symbol *sym)
1690 if (!sym)
1691 return;
1692 if (!(sym->namespace & NS_SYMBOL))
1693 return;
1695 __split_stmt(sym->stmt);
1696 __split_expr(sym->array_size);
1697 if (sym->cleanup)
1698 add_cleanup_hook(sym);
1699 split_symlist(sym->arguments);
1700 split_symlist(sym->symbol_list);
1701 __split_stmt(sym->inline_stmt);
1702 split_symlist(sym->inline_symbol_list);
1705 static void split_symlist(struct symbol_list *sym_list)
1707 struct symbol *sym;
1709 FOR_EACH_PTR(sym_list, sym) {
1710 split_sym(sym);
1711 } END_FOR_EACH_PTR(sym);
1714 typedef void (fake_cb)(struct expression *expr);
1716 static int member_to_number(struct expression *expr, struct ident *member)
1718 struct symbol *type, *tmp;
1719 char *name;
1720 int i;
1722 if (!member)
1723 return -1;
1724 name = member->name;
1726 type = get_type(expr);
1727 if (!type || type->type != SYM_STRUCT)
1728 return -1;
1730 i = -1;
1731 FOR_EACH_PTR(type->symbol_list, tmp) {
1732 i++;
1733 if (!tmp->ident)
1734 continue;
1735 if (strcmp(name, tmp->ident->name) == 0)
1736 return i;
1737 } END_FOR_EACH_PTR(tmp);
1738 return -1;
1741 static struct ident *number_to_member(struct expression *expr, int num)
1743 struct symbol *type, *member;
1744 int i = 0;
1746 type = get_type(expr);
1747 if (!type || type->type != SYM_STRUCT)
1748 return NULL;
1750 FOR_EACH_PTR(type->symbol_list, member) {
1751 if (i == num)
1752 return member->ident;
1753 i++;
1754 } END_FOR_EACH_PTR(member);
1755 return NULL;
1758 static void fake_element_assigns_helper(struct expression *array, struct expression_list *expr_list, fake_cb *fake_cb);
1760 static void set_inner_struct_members(struct expression *expr, struct symbol *member)
1762 struct expression *edge_member, *assign;
1763 struct symbol *base = get_real_base_type(member);
1764 struct symbol *tmp;
1766 if (member->ident)
1767 expr = member_expression(expr, '.', member->ident);
1769 FOR_EACH_PTR(base->symbol_list, tmp) {
1770 struct symbol *type;
1772 type = get_real_base_type(tmp);
1773 if (!type)
1774 continue;
1776 edge_member = member_expression(expr, '.', tmp->ident);
1777 if (get_extra_state(edge_member))
1778 continue;
1780 if (type->type == SYM_UNION || type->type == SYM_STRUCT) {
1781 set_inner_struct_members(expr, tmp);
1782 continue;
1785 if (!tmp->ident)
1786 continue;
1788 assign = assign_expression(edge_member, '=', zero_expr());
1789 __split_expr(assign);
1790 } END_FOR_EACH_PTR(tmp);
1795 static void set_unset_to_zero(struct symbol *type, struct expression *expr)
1797 struct symbol *tmp;
1798 struct expression *member = NULL;
1799 struct expression *assign;
1801 FOR_EACH_PTR(type->symbol_list, tmp) {
1802 type = get_real_base_type(tmp);
1803 if (!type)
1804 continue;
1806 if (tmp->ident) {
1807 member = member_expression(expr, '.', tmp->ident);
1808 if (get_extra_state(member))
1809 continue;
1812 if (type->type == SYM_UNION || type->type == SYM_STRUCT) {
1813 set_inner_struct_members(expr, tmp);
1814 continue;
1816 if (type->type == SYM_ARRAY)
1817 continue;
1818 if (!tmp->ident)
1819 continue;
1821 assign = assign_expression(member, '=', zero_expr());
1822 __split_expr(assign);
1823 } END_FOR_EACH_PTR(tmp);
1826 static void fake_member_assigns_helper(struct expression *symbol, struct expression_list *members, fake_cb *fake_cb)
1828 struct expression *deref, *assign, *tmp, *right;
1829 struct symbol *struct_type, *type;
1830 struct ident *member;
1831 int member_idx;
1833 struct_type = get_type(symbol);
1834 if (!struct_type ||
1835 (struct_type->type != SYM_STRUCT && struct_type->type != SYM_UNION))
1836 return;
1839 * We're parsing an initializer that could look something like this:
1840 * struct foo foo = {
1841 * 42,
1842 * .whatever.xxx = 11,
1843 * .zzz = 12,
1844 * };
1846 * So what we have here is a list with 42, .whatever, and .zzz. We need
1847 * to break it up into left and right sides of the assignments.
1850 member_idx = 0;
1851 FOR_EACH_PTR(members, tmp) {
1852 deref = NULL;
1853 if (tmp->type == EXPR_IDENTIFIER) {
1854 member_idx = member_to_number(symbol, tmp->expr_ident);
1855 while (tmp->type == EXPR_IDENTIFIER) {
1856 member = tmp->expr_ident;
1857 tmp = tmp->ident_expression;
1858 if (deref)
1859 deref = member_expression(deref, '.', member);
1860 else
1861 deref = member_expression(symbol, '.', member);
1863 } else {
1864 member = number_to_member(symbol, member_idx);
1865 deref = member_expression(symbol, '.', member);
1867 right = tmp;
1868 member_idx++;
1869 if (right->type == EXPR_INITIALIZER) {
1870 type = get_type(deref);
1871 if (type && type->type == SYM_ARRAY)
1872 fake_element_assigns_helper(deref, right->expr_list, fake_cb);
1873 else
1874 fake_member_assigns_helper(deref, right->expr_list, fake_cb);
1875 } else {
1876 assign = assign_expression(deref, '=', right);
1877 fake_cb(assign);
1879 } END_FOR_EACH_PTR(tmp);
1881 set_unset_to_zero(struct_type, symbol);
1884 static void fake_member_assigns(struct symbol *sym, fake_cb *fake_cb)
1886 fake_member_assigns_helper(symbol_expression(sym),
1887 sym->initializer->expr_list, fake_cb);
1890 static void fake_element_assigns_helper(struct expression *array, struct expression_list *expr_list, fake_cb *fake_cb)
1892 struct expression *offset, *binop, *assign, *tmp;
1893 struct symbol *type;
1894 int idx, max;
1896 if (ptr_list_size((struct ptr_list *)expr_list) > 1000)
1897 return;
1899 max = 0;
1900 idx = 0;
1901 FOR_EACH_PTR(expr_list, tmp) {
1902 if (tmp->type == EXPR_INDEX) {
1903 if (tmp->idx_from != tmp->idx_to)
1904 return;
1905 idx = tmp->idx_from;
1906 if (idx > max)
1907 max = idx;
1908 if (!tmp->idx_expression)
1909 goto next;
1910 tmp = tmp->idx_expression;
1912 offset = value_expr(idx);
1913 binop = array_element_expression(array, offset);
1914 if (tmp->type == EXPR_INITIALIZER) {
1915 type = get_type(binop);
1916 if (type && type->type == SYM_ARRAY)
1917 fake_element_assigns_helper(binop, tmp->expr_list, fake_cb);
1918 else
1919 fake_member_assigns_helper(binop, tmp->expr_list, fake_cb);
1920 } else {
1921 assign = assign_expression(binop, '=', tmp);
1922 fake_cb(assign);
1924 next:
1925 idx++;
1926 if (idx > max)
1927 max = idx;
1928 } END_FOR_EACH_PTR(tmp);
1930 __call_array_initialized_hooks(array, max);
1933 static void fake_element_assigns(struct symbol *sym, fake_cb *fake_cb)
1935 fake_element_assigns_helper(symbol_expression(sym), sym->initializer->expr_list, fake_cb);
1938 static void fake_assign_expr(struct symbol *sym)
1940 struct expression *assign, *symbol;
1942 symbol = symbol_expression(sym);
1943 assign = assign_expression(symbol, '=', sym->initializer);
1944 __split_expr(assign);
1947 static void do_initializer_stuff(struct symbol *sym)
1949 if (!sym->initializer)
1950 return;
1952 if (sym->initializer->type == EXPR_INITIALIZER) {
1953 if (get_real_base_type(sym)->type == SYM_ARRAY)
1954 fake_element_assigns(sym, __split_expr);
1955 else
1956 fake_member_assigns(sym, __split_expr);
1957 } else {
1958 fake_assign_expr(sym);
1962 static void split_declaration(struct symbol_list *sym_list)
1964 struct symbol *sym;
1966 FOR_EACH_PTR(sym_list, sym) {
1967 __pass_to_client(sym, DECLARATION_HOOK);
1968 do_initializer_stuff(sym);
1969 __pass_to_client(sym, DECLARATION_HOOK_AFTER);
1970 split_sym(sym);
1971 } END_FOR_EACH_PTR(sym);
1974 static void call_global_assign_hooks(struct expression *assign)
1976 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1979 static void fake_global_assign(struct symbol *sym)
1981 struct expression *assign, *symbol;
1983 if (get_real_base_type(sym)->type == SYM_ARRAY) {
1984 if (sym->initializer && sym->initializer->type == EXPR_INITIALIZER) {
1985 fake_element_assigns(sym, call_global_assign_hooks);
1986 } else if (sym->initializer) {
1987 symbol = symbol_expression(sym);
1988 assign = assign_expression(symbol, '=', sym->initializer);
1989 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1990 } else {
1991 fake_element_assigns_helper(symbol_expression(sym), NULL, call_global_assign_hooks);
1993 } else if (get_real_base_type(sym)->type == SYM_STRUCT) {
1994 if (sym->initializer && sym->initializer->type == EXPR_INITIALIZER) {
1995 fake_member_assigns(sym, call_global_assign_hooks);
1996 } else if (sym->initializer) {
1997 symbol = symbol_expression(sym);
1998 assign = assign_expression(symbol, '=', sym->initializer);
1999 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
2000 } else {
2001 fake_member_assigns_helper(symbol_expression(sym), NULL, call_global_assign_hooks);
2003 } else {
2004 symbol = symbol_expression(sym);
2005 if (sym->initializer) {
2006 assign = assign_expression(symbol, '=', sym->initializer);
2007 __split_expr(assign);
2008 } else {
2009 assign = assign_expression(symbol, '=', zero_expr());
2011 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
2015 static void start_function_definition(struct symbol *sym)
2017 __in_function_def = 1;
2018 __pass_to_client(sym, FUNC_DEF_HOOK);
2019 __in_function_def = 0;
2020 __pass_to_client(sym, AFTER_DEF_HOOK);
2024 static void parse_fn_statements(struct symbol *base)
2026 __split_stmt(base->stmt);
2027 __split_stmt(base->inline_stmt);
2030 void add_function_data(unsigned long *fn_data)
2032 __add_ptr_list(&fn_data_list, fn_data);
2035 static void clear_function_data(void)
2037 unsigned long *tmp;
2039 FOR_EACH_PTR(fn_data_list, tmp) {
2040 *tmp = 0;
2041 } END_FOR_EACH_PTR(tmp);
2044 static void record_func_time(void)
2046 struct timeval stop;
2047 int func_time;
2048 char buf[32];
2050 gettimeofday(&stop, NULL);
2051 func_time = stop.tv_sec - fn_start_time.tv_sec;
2052 snprintf(buf, sizeof(buf), "%d", func_time);
2053 sql_insert_return_implies(FUNC_TIME, 0, "", buf);
2054 if (option_time && func_time > 2) {
2055 final_pass++;
2056 sm_msg("func_time: %d", func_time);
2057 final_pass--;
2061 static void split_function(struct symbol *sym)
2063 struct symbol *base_type = get_base_type(sym);
2065 if (!base_type->stmt && !base_type->inline_stmt)
2066 return;
2068 gettimeofday(&outer_fn_start_time, NULL);
2069 gettimeofday(&fn_start_time, NULL);
2070 cur_func_sym = sym;
2071 if (sym->ident)
2072 cur_func = sym->ident->name;
2073 if (option_process_function && cur_func &&
2074 strcmp(option_process_function, cur_func) != 0)
2075 return;
2076 set_position(sym->pos);
2077 clear_function_data();
2078 loop_count = 0;
2079 last_goto_statement_handled = 0;
2080 sm_debug("new function: %s\n", cur_func);
2081 __stree_id = 0;
2082 if (option_two_passes) {
2083 __unnullify_path();
2084 loop_num = 0;
2085 final_pass = 0;
2086 start_function_definition(sym);
2087 parse_fn_statements(base_type);
2088 __call_scope_hooks();
2089 nullify_path();
2091 __unnullify_path();
2092 loop_num = 0;
2093 final_pass = 1;
2094 start_function_definition(sym);
2095 parse_fn_statements(base_type);
2096 if (!__path_is_null() &&
2097 cur_func_return_type() == &void_ctype &&
2098 !__bail_on_rest_of_function) {
2099 __call_all_scope_hooks();
2100 __pass_to_client(NULL, RETURN_HOOK);
2101 nullify_path();
2103 __pass_to_client(sym, END_FUNC_HOOK);
2104 __free_scope_hooks();
2105 __pass_to_client(sym, AFTER_FUNC_HOOK);
2106 sym->parsed = true;
2108 clear_all_states();
2110 record_func_time();
2112 cur_func_sym = NULL;
2113 cur_func = NULL;
2114 free_data_info_allocs();
2115 free_expression_stack(&switch_expr_stack);
2116 __free_ptr_list((struct ptr_list **)&big_statement_stack);
2117 __bail_on_rest_of_function = 0;
2120 static void save_flow_state(void)
2122 unsigned long *tmp;
2124 __add_ptr_list(&backup, INT_PTR(loop_num << 2));
2125 __add_ptr_list(&backup, INT_PTR(loop_count << 2));
2126 __add_ptr_list(&backup, INT_PTR(final_pass << 2));
2128 __add_ptr_list(&backup, big_statement_stack);
2129 __add_ptr_list(&backup, big_expression_stack);
2130 __add_ptr_list(&backup, big_condition_stack);
2131 __add_ptr_list(&backup, switch_expr_stack);
2133 __add_ptr_list(&backup, cur_func_sym);
2135 __add_ptr_list(&backup, parsed_calls);
2137 __add_ptr_list(&backup, __prev_stmt);
2138 __add_ptr_list(&backup, __cur_stmt);
2139 __add_ptr_list(&backup, __next_stmt);
2141 FOR_EACH_PTR(fn_data_list, tmp) {
2142 __add_ptr_list(&backup, (void *)*tmp);
2143 } END_FOR_EACH_PTR(tmp);
2146 static void *pop_backup(void)
2148 void *ret;
2150 ret = last_ptr_list(backup);
2151 delete_ptr_list_last(&backup);
2152 return ret;
2155 static void restore_flow_state(void)
2157 unsigned long *tmp;
2159 FOR_EACH_PTR_REVERSE(fn_data_list, tmp) {
2160 *tmp = (unsigned long)pop_backup();
2161 } END_FOR_EACH_PTR_REVERSE(tmp);
2163 __next_stmt = pop_backup();
2164 __cur_stmt = pop_backup();
2165 __prev_stmt = pop_backup();
2167 parsed_calls = pop_backup();
2169 cur_func_sym = pop_backup();
2170 switch_expr_stack = pop_backup();
2171 big_condition_stack = pop_backup();
2172 big_expression_stack = pop_backup();
2173 big_statement_stack = pop_backup();
2174 final_pass = PTR_INT(pop_backup()) >> 2;
2175 loop_count = PTR_INT(pop_backup()) >> 2;
2176 loop_num = PTR_INT(pop_backup()) >> 2;
2179 void parse_inline(struct expression *call)
2181 struct symbol *base_type;
2182 char *cur_func_bak = cur_func; /* not aligned correctly for backup */
2183 struct timeval time_backup = fn_start_time;
2184 struct expression *orig_inline = __inline_fn;
2185 int orig_budget;
2187 if (out_of_memory() || taking_too_long())
2188 return;
2190 if (already_parsed_call(call))
2191 return;
2193 save_flow_state();
2195 __pass_to_client(call, INLINE_FN_START);
2196 final_pass = 0; /* don't print anything */
2197 __inline_fn = call;
2198 orig_budget = inline_budget;
2199 inline_budget = inline_budget - 5;
2201 base_type = get_base_type(call->fn->symbol);
2202 cur_func_sym = call->fn->symbol;
2203 if (call->fn->symbol->ident)
2204 cur_func = call->fn->symbol->ident->name;
2205 else
2206 cur_func = NULL;
2207 set_position(call->fn->symbol->pos);
2209 save_all_states();
2210 big_statement_stack = NULL;
2211 big_expression_stack = NULL;
2212 big_condition_stack = NULL;
2213 switch_expr_stack = NULL;
2214 parsed_calls = NULL;
2216 sm_debug("inline function: %s\n", cur_func);
2217 __unnullify_path();
2218 clear_function_data();
2219 loop_num = 0;
2220 loop_count = 0;
2221 start_function_definition(call->fn->symbol);
2222 parse_fn_statements(base_type);
2223 if (!__path_is_null() &&
2224 cur_func_return_type() == &void_ctype &&
2225 !__bail_on_rest_of_function) {
2226 __call_all_scope_hooks();
2227 __pass_to_client(NULL, RETURN_HOOK);
2228 nullify_path();
2230 __pass_to_client(call->fn->symbol, END_FUNC_HOOK);
2231 __free_scope_hooks();
2232 __pass_to_client(call->fn->symbol, AFTER_FUNC_HOOK);
2233 call->fn->symbol->parsed = true;
2235 free_expression_stack(&switch_expr_stack);
2236 __free_ptr_list((struct ptr_list **)&big_statement_stack);
2237 nullify_path();
2238 free_goto_stack();
2240 restore_flow_state();
2241 fn_start_time = time_backup;
2242 cur_func = cur_func_bak;
2244 restore_all_states();
2245 set_position(call->pos);
2246 __inline_fn = orig_inline;
2247 inline_budget = orig_budget;
2248 __pass_to_client(call, INLINE_FN_END);
2251 static struct symbol_list *inlines_called;
2252 static void add_inline_function(struct symbol *sym)
2254 static struct symbol_list *already_added;
2255 struct symbol *tmp;
2257 FOR_EACH_PTR(already_added, tmp) {
2258 if (tmp == sym)
2259 return;
2260 } END_FOR_EACH_PTR(tmp);
2262 add_ptr_list(&already_added, sym);
2263 add_ptr_list(&inlines_called, sym);
2266 static void process_inlines(void)
2268 struct symbol *tmp;
2270 FOR_EACH_PTR(inlines_called, tmp) {
2271 split_function(tmp);
2272 } END_FOR_EACH_PTR(tmp);
2273 free_ptr_list(&inlines_called);
2276 static struct symbol *get_last_scoped_symbol(struct symbol_list *big_list, int use_static)
2278 struct symbol *sym;
2280 FOR_EACH_PTR_REVERSE(big_list, sym) {
2281 if (!sym->scope)
2282 continue;
2283 if (use_static && sym->ctype.modifiers & MOD_STATIC)
2284 return sym;
2285 if (!use_static && !(sym->ctype.modifiers & MOD_STATIC))
2286 return sym;
2287 } END_FOR_EACH_PTR_REVERSE(sym);
2289 return NULL;
2292 static bool interesting_function(struct symbol *sym)
2294 static int prev_stream = -1;
2295 static bool prev_answer;
2296 const char *filename;
2297 int len;
2299 if (!(sym->ctype.modifiers & MOD_INLINE))
2300 return true;
2302 if (sym->pos.stream == prev_stream)
2303 return prev_answer;
2305 prev_stream = sym->pos.stream;
2306 prev_answer = false;
2308 filename = stream_name(sym->pos.stream);
2309 len = strlen(filename);
2310 if (len > 0 && filename[len - 1] == 'c')
2311 prev_answer = true;
2312 return prev_answer;
2315 static void split_inlines_in_scope(struct symbol *sym)
2317 struct symbol *base;
2318 struct symbol_list *scope_list;
2319 int stream;
2321 scope_list = sym->scope->symbols;
2322 stream = sym->pos.stream;
2324 /* find the last static symbol in the file */
2325 FOR_EACH_PTR_REVERSE(scope_list, sym) {
2326 if (sym->pos.stream != stream)
2327 continue;
2328 if (sym->type != SYM_NODE)
2329 continue;
2330 base = get_base_type(sym);
2331 if (!base)
2332 continue;
2333 if (base->type != SYM_FN)
2334 continue;
2335 if (!base->inline_stmt)
2336 continue;
2337 if (!interesting_function(sym))
2338 continue;
2339 add_inline_function(sym);
2340 } END_FOR_EACH_PTR_REVERSE(sym);
2342 process_inlines();
2345 static void split_inlines(struct symbol_list *sym_list)
2347 struct symbol *sym;
2349 sym = get_last_scoped_symbol(sym_list, 0);
2350 if (sym)
2351 split_inlines_in_scope(sym);
2352 sym = get_last_scoped_symbol(sym_list, 1);
2353 if (sym)
2354 split_inlines_in_scope(sym);
2357 static struct stree *clone_estates_perm(struct stree *orig)
2359 struct stree *ret = NULL;
2360 struct sm_state *tmp;
2362 FOR_EACH_SM(orig, tmp) {
2363 set_state_stree_perm(&ret, tmp->owner, tmp->name, tmp->sym, clone_estate_perm(tmp->state));
2364 } END_FOR_EACH_SM(tmp);
2366 return ret;
2369 struct position last_pos;
2370 static void split_c_file_functions(struct symbol_list *sym_list)
2372 struct symbol *sym;
2374 __unnullify_path();
2375 FOR_EACH_PTR(sym_list, sym) {
2376 set_position(sym->pos);
2377 if (sym->type != SYM_NODE || get_base_type(sym)->type != SYM_FN) {
2378 __pass_to_client(sym, BASE_HOOK);
2379 fake_global_assign(sym);
2380 __pass_to_client(sym, DECLARATION_HOOK_AFTER);
2382 } END_FOR_EACH_PTR(sym);
2383 global_states = clone_estates_perm(get_all_states_stree(SMATCH_EXTRA));
2384 nullify_path();
2386 FOR_EACH_PTR(sym_list, sym) {
2387 set_position(sym->pos);
2388 last_pos = sym->pos;
2389 if (!interesting_function(sym))
2390 continue;
2391 if (sym->type == SYM_NODE && get_base_type(sym)->type == SYM_FN) {
2392 split_function(sym);
2393 process_inlines();
2395 last_pos = sym->pos;
2396 } END_FOR_EACH_PTR(sym);
2397 split_inlines(sym_list);
2398 __pass_to_client(sym_list, END_FILE_HOOK);
2401 static int final_before_fake;
2402 void init_fake_env(void)
2404 if (!in_fake_env)
2405 final_before_fake = final_pass;
2406 in_fake_env++;
2407 __push_fake_cur_stree();
2408 final_pass = 0;
2411 void end_fake_env(void)
2413 __free_fake_cur_stree();
2414 in_fake_env--;
2415 if (!in_fake_env)
2416 final_pass = final_before_fake;
2419 static void open_output_files(char *base_file)
2421 char buf[256];
2423 snprintf(buf, sizeof(buf), "%s.smatch", base_file);
2424 sm_outfd = fopen(buf, "w");
2425 if (!sm_outfd)
2426 sm_fatal("Cannot open %s", buf);
2428 if (!option_info)
2429 return;
2431 snprintf(buf, sizeof(buf), "%s.smatch.sql", base_file);
2432 sql_outfd = fopen(buf, "w");
2433 if (!sql_outfd)
2434 sm_fatal("Error: Cannot open %s", buf);
2436 snprintf(buf, sizeof(buf), "%s.smatch.caller_info", base_file);
2437 caller_info_fd = fopen(buf, "w");
2438 if (!caller_info_fd)
2439 sm_fatal("Error: Cannot open %s", buf);
2442 void smatch(struct string_list *filelist)
2444 struct symbol_list *sym_list;
2445 struct timeval stop, start;
2446 char *path;
2447 int len;
2449 gettimeofday(&start, NULL);
2451 FOR_EACH_PTR_NOTAG(filelist, base_file) {
2452 path = getcwd(NULL, 0);
2453 free(full_base_file);
2454 if (path) {
2455 len = strlen(path) + 1 + strlen(base_file) + 1;
2456 full_base_file = malloc(len);
2457 snprintf(full_base_file, len, "%s/%s", path, base_file);
2458 } else {
2459 full_base_file = alloc_string(base_file);
2461 if (option_file_output)
2462 open_output_files(base_file);
2463 base_file_stream = input_stream_nr;
2464 sym_list = sparse_keep_tokens(base_file);
2465 split_c_file_functions(sym_list);
2466 } END_FOR_EACH_PTR_NOTAG(base_file);
2468 gettimeofday(&stop, NULL);
2470 set_position(last_pos);
2471 final_pass = 1;
2472 if (option_time)
2473 sm_msg("time: %lu", stop.tv_sec - start.tv_sec);
2474 if (option_mem)
2475 sm_msg("mem: %luKb", get_max_memory());