chunk: change the API a bit
[smatch.git] / smatch_flow.c
blobf23b4f4e1292cc250390bc5e499aaba168a1d123
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 final_pass;
30 int __inline_call;
31 struct expression *__inline_fn;
33 static int __smatch_lineno = 0;
35 static char *base_file;
36 static const char *filename;
37 static char *pathname;
38 static char *full_filename;
39 static char *cur_func;
40 static unsigned int loop_count;
41 static int last_goto_statement_handled;
42 int __expr_stmt_count;
43 int __in_function_def;
44 static struct expression_list *switch_expr_stack = NULL;
45 static struct expression_list *post_op_stack = NULL;
47 struct expression_list *big_expression_stack;
48 struct statement_list *big_statement_stack;
49 struct statement *__prev_stmt;
50 struct statement *__cur_stmt;
51 struct statement *__next_stmt;
52 int __in_pre_condition = 0;
53 int __bail_on_rest_of_function = 0;
54 static struct timeval fn_start_time;
55 char *get_function(void) { return cur_func; }
56 int get_lineno(void) { return __smatch_lineno; }
57 int inside_loop(void) { return !!loop_count; }
58 int definitely_inside_loop(void) { return !!(loop_count & ~0x80000000); }
59 struct expression *get_switch_expr(void) { return top_expression(switch_expr_stack); }
60 int in_expression_statement(void) { return !!__expr_stmt_count; }
62 static void split_symlist(struct symbol_list *sym_list);
63 static void split_declaration(struct symbol_list *sym_list);
64 static void split_expr_list(struct expression_list *expr_list, struct expression *parent);
65 static void add_inline_function(struct symbol *sym);
66 static void parse_inline(struct expression *expr);
68 int option_assume_loops = 0;
69 int option_known_conditions = 0;
70 int option_two_passes = 0;
71 struct symbol *cur_func_sym = NULL;
72 struct stree *global_states;
74 long long valid_ptr_min = 4096;
75 long long valid_ptr_max = 2117777777;
76 sval_t valid_ptr_min_sval = {
77 .type = &ptr_ctype,
78 {.value = 4096},
80 sval_t valid_ptr_max_sval = {
81 .type = &ptr_ctype,
82 {.value = LONG_MAX - 100000},
85 static void set_valid_ptr_max(void)
87 if (type_bits(&ptr_ctype) == 32)
88 valid_ptr_max = 2117777777;
89 else if (type_bits(&ptr_ctype) == 64)
90 valid_ptr_max = 2117777777777777777LL;
92 valid_ptr_max_sval.value = valid_ptr_max;
95 int outside_of_function(void)
97 return cur_func_sym == NULL;
100 const char *get_filename(void)
102 if (option_info)
103 return base_file;
104 if (option_full_path)
105 return full_filename;
106 return filename;
109 const char *get_base_file(void)
111 return base_file;
114 static void set_position(struct position pos)
116 int len;
117 static int prev_stream = -1;
119 if (pos.stream == 0 && pos.line == 0)
120 return;
122 __smatch_lineno = pos.line;
124 if (pos.stream == prev_stream)
125 return;
127 filename = stream_name(pos.stream);
129 free(full_filename);
130 pathname = getcwd(NULL, 0);
131 if (pathname) {
132 len = strlen(pathname) + 1 + strlen(filename) + 1;
133 full_filename = malloc(len);
134 snprintf(full_filename, len, "%s/%s", pathname, filename);
135 } else {
136 full_filename = alloc_string(filename);
138 free(pathname);
141 static void set_parent(struct expression *expr, struct expression *parent)
143 if (!expr)
144 return;
145 expr->parent = parent;
148 int is_assigned_call(struct expression *expr)
150 struct expression *tmp;
152 FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) {
153 if (tmp->type == EXPR_ASSIGNMENT && tmp->op == '=' &&
154 strip_expr(tmp->right) == expr)
155 return 1;
156 if (tmp->pos.line < expr->pos.line)
157 return 0;
158 } END_FOR_EACH_PTR_REVERSE(tmp);
159 return 0;
162 static int is_inline_func(struct expression *expr)
164 if (expr->type != EXPR_SYMBOL || !expr->symbol)
165 return 0;
166 if (expr->symbol->ctype.modifiers & MOD_INLINE)
167 return 1;
168 return 0;
171 static int is_noreturn_func(struct expression *expr)
173 if (expr->type != EXPR_SYMBOL || !expr->symbol)
174 return 0;
175 if (expr->symbol->ctype.modifiers & MOD_NORETURN)
176 return 1;
177 return 0;
180 int inlinable(struct expression *expr)
182 struct symbol *sym;
183 struct statement *last_stmt = NULL;
185 if (__inline_fn) /* don't nest */
186 return 0;
188 if (expr->type != EXPR_SYMBOL || !expr->symbol)
189 return 0;
190 if (is_no_inline_function(expr->symbol->ident->name))
191 return 0;
192 sym = get_base_type(expr->symbol);
193 if (sym->stmt && sym->stmt->type == STMT_COMPOUND) {
194 if (ptr_list_size((struct ptr_list *)sym->stmt->stmts) > 10)
195 return 0;
196 if (sym->stmt->type != STMT_COMPOUND)
197 return 0;
198 last_stmt = last_ptr_list((struct ptr_list *)sym->stmt->stmts);
200 if (sym->inline_stmt && sym->inline_stmt->type == STMT_COMPOUND) {
201 if (ptr_list_size((struct ptr_list *)sym->inline_stmt->stmts) > 10)
202 return 0;
203 if (sym->inline_stmt->type != STMT_COMPOUND)
204 return 0;
205 last_stmt = last_ptr_list((struct ptr_list *)sym->inline_stmt->stmts);
208 if (!last_stmt)
209 return 0;
211 /* the magic numbers in this function are pulled out of my bum. */
212 if (last_stmt->pos.line > sym->pos.line + 20)
213 return 0;
215 return 1;
218 void __process_post_op_stack(void)
220 struct expression *expr;
222 FOR_EACH_PTR(post_op_stack, expr) {
223 __pass_to_client(expr, OP_HOOK);
224 } END_FOR_EACH_PTR(expr);
226 __free_ptr_list((struct ptr_list **)&post_op_stack);
229 static int handle_comma_assigns(struct expression *expr)
231 struct expression *right;
232 struct expression *assign;
234 right = strip_expr(expr->right);
235 if (right->type != EXPR_COMMA)
236 return 0;
238 __split_expr(right->left);
239 __process_post_op_stack();
241 assign = assign_expression(expr->left, right->right);
242 __split_expr(assign);
244 return 1;
247 static int prev_expression_is_getting_address(struct expression *expr)
249 struct expression *parent;
251 do {
252 parent = expr->parent;
254 if (!parent)
255 return 0;
256 if (parent->type == EXPR_PREOP && parent->op == '&')
257 return 1;
258 if (parent->type == EXPR_PREOP && parent->op == '(')
259 goto next;
260 if (parent->type == EXPR_DEREF && parent->op == '.')
261 goto next;
263 return 0;
264 next:
265 expr = parent;
266 } while (1);
269 void __split_expr(struct expression *expr)
271 if (!expr)
272 return;
274 // sm_msg(" Debug expr_type %d %s", expr->type, show_special(expr->op));
276 if (__in_fake_assign && expr->type != EXPR_ASSIGNMENT)
277 return;
278 if (__in_fake_assign >= 4) /* don't allow too much nesting */
279 return;
281 push_expression(&big_expression_stack, expr);
282 set_position(expr->pos);
283 __pass_to_client(expr, EXPR_HOOK);
285 switch (expr->type) {
286 case EXPR_PREOP:
287 set_parent(expr->unop, expr);
289 if (expr->op == '*' &&
290 !prev_expression_is_getting_address(expr))
291 __pass_to_client(expr, DEREF_HOOK);
292 __split_expr(expr->unop);
293 __pass_to_client(expr, OP_HOOK);
294 break;
295 case EXPR_POSTOP:
296 set_parent(expr->unop, expr);
298 __split_expr(expr->unop);
299 push_expression(&post_op_stack, expr);
300 break;
301 case EXPR_STATEMENT:
302 __expr_stmt_count++;
303 __split_stmt(expr->statement);
304 __expr_stmt_count--;
305 break;
306 case EXPR_LOGICAL:
307 case EXPR_COMPARE:
308 set_parent(expr->left, expr);
309 set_parent(expr->right, expr);
311 __pass_to_client(expr, LOGIC_HOOK);
312 __handle_logic(expr);
313 break;
314 case EXPR_BINOP:
315 set_parent(expr->left, expr);
316 set_parent(expr->right, expr);
318 __pass_to_client(expr, BINOP_HOOK);
319 case EXPR_COMMA:
320 set_parent(expr->left, expr);
321 set_parent(expr->right, expr);
323 __split_expr(expr->left);
324 __process_post_op_stack();
325 __split_expr(expr->right);
326 break;
327 case EXPR_ASSIGNMENT: {
328 struct expression *tmp;
330 set_parent(expr->left, expr);
331 set_parent(expr->right, expr);
333 if (!expr->right)
334 break;
336 __pass_to_client(expr, RAW_ASSIGNMENT_HOOK);
338 /* foo = !bar() */
339 if (__handle_condition_assigns(expr))
340 break;
341 /* foo = (x < 5 ? foo : 5); */
342 if (__handle_select_assigns(expr))
343 break;
344 /* foo = ({frob(); frob(); frob(); 1;}) */
345 if (__handle_expr_statement_assigns(expr))
346 break;
347 /* foo = (3, 4); */
348 if (handle_comma_assigns(expr))
349 break;
351 __split_expr(expr->right);
352 if (outside_of_function())
353 __pass_to_client(expr, GLOBAL_ASSIGNMENT_HOOK);
354 else
355 __pass_to_client(expr, ASSIGNMENT_HOOK);
357 __fake_struct_member_assignments(expr);
359 tmp = strip_expr(expr->right);
360 if (expr->op == '=' && tmp->type == EXPR_CALL) {
361 __pass_to_client(expr, CALL_ASSIGNMENT_HOOK);
362 if (!is_fake_call(tmp))
363 __pass_to_client(tmp, FUNCTION_CALL_HOOK_AFTER);
365 if (get_macro_name(tmp->pos) &&
366 get_macro_name(expr->pos) != get_macro_name(tmp->pos))
367 __pass_to_client(expr, MACRO_ASSIGNMENT_HOOK);
368 __split_expr(expr->left);
369 break;
371 case EXPR_DEREF:
372 set_parent(expr->deref, expr);
374 __pass_to_client(expr, DEREF_HOOK);
375 __split_expr(expr->deref);
376 break;
377 case EXPR_SLICE:
378 set_parent(expr->base, expr);
380 __split_expr(expr->base);
381 break;
382 case EXPR_CAST:
383 case EXPR_FORCE_CAST:
384 set_parent(expr->cast_expression, expr);
386 __pass_to_client(expr, CAST_HOOK);
387 __split_expr(expr->cast_expression);
388 break;
389 case EXPR_SIZEOF:
390 if (expr->cast_expression)
391 __pass_to_client(strip_parens(expr->cast_expression),
392 SIZEOF_HOOK);
393 break;
394 case EXPR_OFFSETOF:
395 case EXPR_ALIGNOF:
396 evaluate_expression(expr);
397 break;
398 case EXPR_CONDITIONAL:
399 case EXPR_SELECT:
400 set_parent(expr->conditional, expr);
401 set_parent(expr->cond_true, expr);
402 set_parent(expr->cond_false, expr);
404 if (known_condition_true(expr->conditional)) {
405 __split_expr(expr->cond_true);
406 break;
408 if (known_condition_false(expr->conditional)) {
409 __split_expr(expr->cond_false);
410 break;
412 __pass_to_client(expr, SELECT_HOOK);
413 __split_whole_condition(expr->conditional);
414 __split_expr(expr->cond_true);
415 __push_true_states();
416 __use_false_states();
417 __split_expr(expr->cond_false);
418 __merge_true_states();
419 break;
420 case EXPR_CALL:
421 set_parent(expr->fn, expr);
423 if (sym_name_is("__builtin_constant_p", expr->fn))
424 break;
425 split_expr_list(expr->args, expr);
426 __split_expr(expr->fn);
427 if (is_inline_func(expr->fn))
428 add_inline_function(expr->fn->symbol);
429 if (inlinable(expr->fn))
430 __inline_call = 1;
431 __process_post_op_stack();
432 __pass_to_client(expr, FUNCTION_CALL_HOOK);
433 __inline_call = 0;
434 if (inlinable(expr->fn)) {
435 parse_inline(expr);
437 __pass_to_client(expr, CALL_HOOK_AFTER_INLINE);
438 if (!is_assigned_call(expr))
439 __pass_to_client(expr, FUNCTION_CALL_HOOK_AFTER);
440 if (is_noreturn_func(expr->fn))
441 nullify_path();
442 break;
443 case EXPR_INITIALIZER:
444 split_expr_list(expr->expr_list, expr);
445 break;
446 case EXPR_IDENTIFIER:
447 set_parent(expr->ident_expression, expr);
448 __split_expr(expr->ident_expression);
449 break;
450 case EXPR_INDEX:
451 set_parent(expr->idx_expression, expr);
452 __split_expr(expr->idx_expression);
453 break;
454 case EXPR_POS:
455 set_parent(expr->init_expr, expr);
456 __split_expr(expr->init_expr);
457 break;
458 case EXPR_SYMBOL:
459 __pass_to_client(expr, SYM_HOOK);
460 break;
461 case EXPR_STRING:
462 __pass_to_client(expr, STRING_HOOK);
463 break;
464 default:
465 break;
467 pop_expression(&big_expression_stack);
470 static int is_forever_loop(struct statement *stmt)
472 struct expression *expr;
474 expr = strip_expr(stmt->iterator_pre_condition);
475 if (!expr)
476 expr = stmt->iterator_post_condition;
477 if (!expr) {
478 /* this is a for(;;) loop... */
479 return 1;
482 if (expr->type == EXPR_VALUE && expr->value == 1)
483 return 1;
485 return 0;
488 static int loop_num;
489 static char *get_loop_name(int num)
491 char buf[256];
493 snprintf(buf, 255, "-loop%d", num);
494 buf[255] = '\0';
495 return alloc_sname(buf);
499 * Pre Loops are while and for loops.
501 static void handle_pre_loop(struct statement *stmt)
503 int once_through; /* we go through the loop at least once */
504 struct sm_state *extra_sm = NULL;
505 int unchanged = 0;
506 char *loop_name;
507 struct stree *stree = NULL;
508 struct sm_state *sm = NULL;
510 loop_name = get_loop_name(loop_num);
511 loop_num++;
513 __split_stmt(stmt->iterator_pre_statement);
514 __prev_stmt = stmt->iterator_pre_statement;
516 once_through = implied_condition_true(stmt->iterator_pre_condition);
518 loop_count++;
519 __push_continues();
520 __push_breaks();
522 __merge_gotos(loop_name);
524 extra_sm = __extra_handle_canonical_loops(stmt, &stree);
525 __in_pre_condition++;
526 __pass_to_client(stmt, PRELOOP_HOOK);
527 __split_whole_condition(stmt->iterator_pre_condition);
528 __in_pre_condition--;
529 FOR_EACH_SM(stree, sm) {
530 set_state(sm->owner, sm->name, sm->sym, sm->state);
531 } END_FOR_EACH_SM(sm);
532 free_stree(&stree);
533 if (extra_sm)
534 extra_sm = get_sm_state(extra_sm->owner, extra_sm->name, extra_sm->sym);
536 if (option_assume_loops)
537 once_through = 1;
539 __split_stmt(stmt->iterator_statement);
540 __warn_on_silly_pre_loops();
541 if (is_forever_loop(stmt)) {
542 __merge_continues();
543 __save_gotos(loop_name);
545 __push_fake_cur_stree();
546 __split_stmt(stmt->iterator_post_statement);
547 stree = __pop_fake_cur_stree();
549 __discard_false_states();
550 __use_breaks();
552 if (!__path_is_null())
553 __merge_stree_into_cur(stree);
554 free_stree(&stree);
555 } else {
556 __merge_continues();
557 unchanged = __iterator_unchanged(extra_sm);
558 __split_stmt(stmt->iterator_post_statement);
559 __prev_stmt = stmt->iterator_post_statement;
560 __cur_stmt = stmt;
562 __save_gotos(loop_name);
563 __in_pre_condition++;
564 __split_whole_condition(stmt->iterator_pre_condition);
565 __in_pre_condition--;
566 nullify_path();
567 __merge_false_states();
568 if (once_through)
569 __discard_false_states();
570 else
571 __merge_false_states();
573 if (extra_sm && unchanged)
574 __extra_pre_loop_hook_after(extra_sm,
575 stmt->iterator_post_statement,
576 stmt->iterator_pre_condition);
577 __merge_breaks();
579 loop_count--;
583 * Post loops are do {} while();
585 static void handle_post_loop(struct statement *stmt)
587 char *loop_name;
589 loop_name = get_loop_name(loop_num);
590 loop_num++;
591 loop_count++;
593 __push_continues();
594 __push_breaks();
595 __merge_gotos(loop_name);
596 __split_stmt(stmt->iterator_statement);
597 __merge_continues();
598 if (!is_zero(stmt->iterator_post_condition))
599 __save_gotos(loop_name);
601 if (is_forever_loop(stmt)) {
602 __use_breaks();
603 } else {
604 __split_whole_condition(stmt->iterator_post_condition);
605 __use_false_states();
606 __merge_breaks();
608 loop_count--;
611 static int empty_statement(struct statement *stmt)
613 if (!stmt)
614 return 0;
615 if (stmt->type == STMT_EXPRESSION && !stmt->expression)
616 return 1;
617 return 0;
620 static int last_stmt_on_same_line(void)
622 struct statement *stmt;
623 int i = 0;
625 FOR_EACH_PTR_REVERSE(big_statement_stack, stmt) {
626 if (!i++)
627 continue;
628 if (stmt->pos.line == get_lineno())
629 return 1;
630 return 0;
631 } END_FOR_EACH_PTR_REVERSE(stmt);
632 return 0;
635 static void split_asm_constraints(struct expression_list *expr_list)
637 struct expression *expr;
638 int state = 0;
640 FOR_EACH_PTR(expr_list, expr) {
641 switch (state) {
642 case 0: /* identifier */
643 case 1: /* constraint */
644 state++;
645 continue;
646 case 2: /* expression */
647 state = 0;
648 __split_expr(expr);
649 continue;
651 } END_FOR_EACH_PTR(expr);
654 static int is_case_val(struct statement *stmt, sval_t sval)
656 sval_t case_sval;
658 if (stmt->type != STMT_CASE)
659 return 0;
660 if (!stmt->case_expression) {
661 __set_default();
662 return 1;
664 if (!get_value(stmt->case_expression, &case_sval))
665 return 0;
666 if (case_sval.value == sval.value)
667 return 1;
668 return 0;
671 static void split_known_switch(struct statement *stmt, sval_t sval)
673 struct statement *tmp;
675 __split_expr(stmt->switch_expression);
677 push_expression(&switch_expr_stack, stmt->switch_expression);
678 __save_switch_states(top_expression(switch_expr_stack));
679 nullify_path();
680 __push_default();
681 __push_breaks();
683 stmt = stmt->switch_statement;
685 __push_scope_hooks();
686 FOR_EACH_PTR(stmt->stmts, tmp) {
687 __smatch_lineno = tmp->pos.line;
688 if (is_case_val(tmp, sval)) {
689 __merge_switches(top_expression(switch_expr_stack),
690 stmt->case_expression);
691 __pass_case_to_client(top_expression(switch_expr_stack),
692 stmt->case_expression);
694 if (__path_is_null())
695 continue;
696 __split_stmt(tmp);
697 if (__path_is_null()) {
698 __set_default();
699 goto out;
701 } END_FOR_EACH_PTR(tmp);
702 out:
703 __call_scope_hooks();
704 if (!__pop_default())
705 __merge_switches(top_expression(switch_expr_stack),
706 NULL);
707 __discard_switches();
708 __merge_breaks();
709 pop_expression(&switch_expr_stack);
712 static int taking_too_long(void)
714 int ms;
716 ms = ms_since(&fn_start_time);
717 if (ms > 1000 * 60 * 5) /* five minutes */
718 return 1;
719 return 0;
722 static int is_last_stmt(struct statement *cur_stmt)
724 struct symbol *fn = get_base_type(cur_func_sym);
725 struct statement *stmt;
727 if (!fn)
728 return 0;
729 stmt = fn->stmt;
730 if (!stmt)
731 stmt = fn->inline_stmt;
732 if (!stmt || stmt->type != STMT_COMPOUND)
733 return 0;
734 stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
735 if (stmt && stmt->type == STMT_LABEL)
736 stmt = stmt->label_statement;
737 if (stmt == cur_stmt)
738 return 1;
739 return 0;
742 static void handle_backward_goto(struct statement *goto_stmt)
744 const char *goto_name, *label_name;
745 struct statement *func_stmt;
746 struct symbol *base_type = get_base_type(cur_func_sym);
747 struct statement *tmp;
748 int found = 0;
750 if (!option_info)
751 return;
752 if (last_goto_statement_handled)
753 return;
754 last_goto_statement_handled = 1;
756 if (!goto_stmt->goto_label ||
757 goto_stmt->goto_label->type != SYM_LABEL ||
758 !goto_stmt->goto_label->ident)
759 return;
760 goto_name = goto_stmt->goto_label->ident->name;
762 func_stmt = base_type->stmt;
763 if (!func_stmt)
764 func_stmt = base_type->inline_stmt;
765 if (!func_stmt)
766 return;
767 if (func_stmt->type != STMT_COMPOUND)
768 return;
770 FOR_EACH_PTR(func_stmt->stmts, tmp) {
771 if (!found) {
772 if (tmp->type != STMT_LABEL)
773 continue;
774 if (!tmp->label_identifier ||
775 tmp->label_identifier->type != SYM_LABEL ||
776 !tmp->label_identifier->ident)
777 continue;
778 label_name = tmp->label_identifier->ident->name;
779 if (strcmp(goto_name, label_name) != 0)
780 continue;
781 found = 1;
783 __split_stmt(tmp);
784 } END_FOR_EACH_PTR(tmp);
787 static void fake_a_return(void)
789 struct symbol *return_type;
791 nullify_path();
792 __unnullify_path();
794 return_type = get_real_base_type(cur_func_sym);
795 return_type = get_real_base_type(return_type);
796 if (return_type != &void_ctype) {
797 __pass_to_client(unknown_value_expression(NULL), RETURN_HOOK);
798 nullify_path();
801 __pass_to_client(cur_func_sym, END_FUNC_HOOK);
802 __pass_to_client(cur_func_sym, AFTER_FUNC_HOOK);
805 static void split_compound(struct statement *stmt)
807 struct statement *prev = NULL;
808 struct statement *cur = NULL;
809 struct statement *next;
811 __push_scope_hooks();
813 FOR_EACH_PTR(stmt->stmts, next) {
814 if (cur) {
815 __prev_stmt = prev;
816 __next_stmt = next;
817 __cur_stmt = cur;
818 __split_stmt(cur);
820 prev = cur;
821 cur = next;
822 } END_FOR_EACH_PTR(next);
823 if (cur) {
824 __prev_stmt = prev;
825 __cur_stmt = cur;
826 __next_stmt = NULL;
827 __split_stmt(cur);
830 __call_scope_hooks();
833 void __split_stmt(struct statement *stmt)
835 sval_t sval;
837 if (!stmt)
838 goto out;
840 if (__bail_on_rest_of_function || out_of_memory() || taking_too_long()) {
841 static char *printed = NULL;
843 __bail_on_rest_of_function = 1;
844 if (printed != cur_func)
845 sm_msg("Function too hairy. Giving up.");
846 fake_a_return();
847 final_pass = 0; /* turn off sm_msg() from here */
848 printed = cur_func;
849 return;
852 add_ptr_list(&big_statement_stack, stmt);
853 free_expression_stack(&big_expression_stack);
854 set_position(stmt->pos);
855 __pass_to_client(stmt, STMT_HOOK);
857 switch (stmt->type) {
858 case STMT_DECLARATION:
859 split_declaration(stmt->declaration);
860 break;
861 case STMT_RETURN:
862 __split_expr(stmt->ret_value);
863 __pass_to_client(stmt->ret_value, RETURN_HOOK);
864 __process_post_op_stack();
865 nullify_path();
866 break;
867 case STMT_EXPRESSION:
868 __split_expr(stmt->expression);
869 break;
870 case STMT_COMPOUND:
871 split_compound(stmt);
872 break;
873 case STMT_IF:
874 if (known_condition_true(stmt->if_conditional)) {
875 __split_stmt(stmt->if_true);
876 break;
878 if (known_condition_false(stmt->if_conditional)) {
879 __split_stmt(stmt->if_false);
880 break;
882 if (option_known_conditions &&
883 implied_condition_true(stmt->if_conditional)) {
884 sm_info("this condition is true.");
885 __split_stmt(stmt->if_true);
886 break;
888 if (option_known_conditions &&
889 implied_condition_false(stmt->if_conditional)) {
890 sm_info("this condition is false.");
891 __split_stmt(stmt->if_false);
892 break;
894 __split_whole_condition(stmt->if_conditional);
895 __split_stmt(stmt->if_true);
896 if (empty_statement(stmt->if_true) &&
897 last_stmt_on_same_line() &&
898 !get_macro_name(stmt->if_true->pos))
899 sm_msg("warn: if();");
900 __push_true_states();
901 __use_false_states();
902 __split_stmt(stmt->if_false);
903 __merge_true_states();
904 break;
905 case STMT_ITERATOR:
906 if (stmt->iterator_pre_condition)
907 handle_pre_loop(stmt);
908 else if (stmt->iterator_post_condition)
909 handle_post_loop(stmt);
910 else {
911 // these are for(;;) type loops.
912 handle_pre_loop(stmt);
914 break;
915 case STMT_SWITCH:
916 if (get_value(stmt->switch_expression, &sval)) {
917 split_known_switch(stmt, sval);
918 break;
920 __split_expr(stmt->switch_expression);
921 push_expression(&switch_expr_stack, stmt->switch_expression);
922 __save_switch_states(top_expression(switch_expr_stack));
923 nullify_path();
924 __push_default();
925 __push_breaks();
926 __split_stmt(stmt->switch_statement);
927 if (!__pop_default())
928 __merge_switches(top_expression(switch_expr_stack),
929 NULL);
930 __discard_switches();
931 __merge_breaks();
932 pop_expression(&switch_expr_stack);
933 break;
934 case STMT_CASE:
935 __merge_switches(top_expression(switch_expr_stack),
936 stmt->case_expression);
937 __pass_case_to_client(top_expression(switch_expr_stack),
938 stmt->case_expression);
939 if (!stmt->case_expression)
940 __set_default();
941 __split_expr(stmt->case_expression);
942 __split_expr(stmt->case_to);
943 __split_stmt(stmt->case_statement);
944 break;
945 case STMT_LABEL:
946 if (stmt->label_identifier &&
947 stmt->label_identifier->type == SYM_LABEL &&
948 stmt->label_identifier->ident) {
949 loop_count |= 0x80000000;
950 __merge_gotos(stmt->label_identifier->ident->name);
952 __split_stmt(stmt->label_statement);
953 break;
954 case STMT_GOTO:
955 __split_expr(stmt->goto_expression);
956 if (stmt->goto_label && stmt->goto_label->type == SYM_NODE) {
957 if (!strcmp(stmt->goto_label->ident->name, "break")) {
958 __process_breaks();
959 } else if (!strcmp(stmt->goto_label->ident->name,
960 "continue")) {
961 __process_continues();
963 } else if (stmt->goto_label &&
964 stmt->goto_label->type == SYM_LABEL &&
965 stmt->goto_label->ident) {
966 __save_gotos(stmt->goto_label->ident->name);
968 nullify_path();
969 if (is_last_stmt(stmt))
970 handle_backward_goto(stmt);
971 break;
972 case STMT_NONE:
973 break;
974 case STMT_ASM:
975 __pass_to_client(stmt, ASM_HOOK);
976 __split_expr(stmt->asm_string);
977 split_asm_constraints(stmt->asm_outputs);
978 split_asm_constraints(stmt->asm_inputs);
979 split_asm_constraints(stmt->asm_clobbers);
980 break;
981 case STMT_CONTEXT:
982 break;
983 case STMT_RANGE:
984 __split_expr(stmt->range_expression);
985 __split_expr(stmt->range_low);
986 __split_expr(stmt->range_high);
987 break;
989 __pass_to_client(stmt, STMT_HOOK_AFTER);
990 out:
991 __process_post_op_stack();
994 static void split_expr_list(struct expression_list *expr_list, struct expression *parent)
996 struct expression *expr;
998 FOR_EACH_PTR(expr_list, expr) {
999 set_parent(expr, parent);
1000 __split_expr(expr);
1001 __process_post_op_stack();
1002 } END_FOR_EACH_PTR(expr);
1005 static void split_sym(struct symbol *sym)
1007 if (!sym)
1008 return;
1009 if (!(sym->namespace & NS_SYMBOL))
1010 return;
1012 __split_stmt(sym->stmt);
1013 __split_expr(sym->array_size);
1014 split_symlist(sym->arguments);
1015 split_symlist(sym->symbol_list);
1016 __split_stmt(sym->inline_stmt);
1017 split_symlist(sym->inline_symbol_list);
1020 static void split_symlist(struct symbol_list *sym_list)
1022 struct symbol *sym;
1024 FOR_EACH_PTR(sym_list, sym) {
1025 split_sym(sym);
1026 } END_FOR_EACH_PTR(sym);
1029 typedef void (fake_cb)(struct expression *expr);
1031 static int member_to_number(struct expression *expr, struct ident *member)
1033 struct symbol *type, *tmp;
1034 char *name;
1035 int i;
1037 if (!member)
1038 return -1;
1039 name = member->name;
1041 type = get_type(expr);
1042 if (!type || type->type != SYM_STRUCT)
1043 return -1;
1045 i = -1;
1046 FOR_EACH_PTR(type->symbol_list, tmp) {
1047 i++;
1048 if (!tmp->ident)
1049 continue;
1050 if (strcmp(name, tmp->ident->name) == 0)
1051 return i;
1052 } END_FOR_EACH_PTR(tmp);
1053 return -1;
1056 static struct ident *number_to_member(struct expression *expr, int num)
1058 struct symbol *type, *member;
1059 int i = 0;
1061 type = get_type(expr);
1062 if (!type || type->type != SYM_STRUCT)
1063 return NULL;
1065 FOR_EACH_PTR(type->symbol_list, member) {
1066 if (i == num)
1067 return member->ident;
1068 i++;
1069 } END_FOR_EACH_PTR(member);
1070 return NULL;
1073 static void fake_element_assigns_helper(struct expression *array, struct expression_list *expr_list, fake_cb *fake_cb);
1075 struct member_set {
1076 struct ident *ident;
1077 int set;
1080 static struct member_set *alloc_member_set(struct symbol *type)
1082 struct member_set *member_set;
1083 struct symbol *member;
1084 int member_count;
1085 int member_idx;
1087 member_count = ptr_list_size((struct ptr_list *)type->symbol_list);
1088 member_set = malloc(member_count * sizeof(*member_set));
1089 member_idx = 0;
1090 FOR_EACH_PTR(type->symbol_list, member) {
1091 member_set[member_idx].ident = member->ident;
1092 member_set[member_idx].set = 0;
1093 member_idx++;
1094 } END_FOR_EACH_PTR(member);
1096 return member_set;
1099 static void mark_member_as_set(struct symbol *type, struct member_set *member_set, struct ident *ident)
1101 int member_count = ptr_list_size((struct ptr_list *)type->symbol_list);
1102 int i;
1104 for (i = 0; i < member_count; i++) {
1105 if (member_set[i].ident == ident) {
1106 member_set[i].set = 1;
1107 return;
1110 // crap. this is buggy.
1111 // sm_msg("internal smatch error in initializer %s.%s", type->ident->name, ident->name);
1114 static void set_inner_struct_members(struct expression *expr, struct symbol *member)
1116 struct expression *edge_member, *assign;
1117 struct symbol *base = get_real_base_type(member);
1118 struct symbol *tmp;
1120 if (member->ident)
1121 expr = member_expression(expr, '.', member->ident);
1123 FOR_EACH_PTR(base->symbol_list, tmp) {
1124 struct symbol *type;
1126 type = get_real_base_type(tmp);
1127 if (!type)
1128 continue;
1130 if (tmp->ident) {
1131 edge_member = member_expression(expr, '.', tmp->ident);
1132 if (get_state_expr(SMATCH_EXTRA, edge_member))
1133 continue;
1136 if (type->type == SYM_UNION || type->type == SYM_STRUCT) {
1137 set_inner_struct_members(expr, tmp);
1138 continue;
1141 if (!tmp->ident)
1142 continue;
1144 assign = assign_expression(edge_member, zero_expr());
1145 __split_expr(assign);
1146 } END_FOR_EACH_PTR(tmp);
1151 static void set_unset_to_zero(struct symbol *type, struct expression *expr)
1153 struct symbol *tmp;
1154 struct expression *member, *assign;
1155 int op = '*';
1157 if (expr->type == EXPR_PREOP && expr->op == '&') {
1158 expr = strip_expr(expr->unop);
1159 op = '.';
1162 FOR_EACH_PTR(type->symbol_list, tmp) {
1163 type = get_real_base_type(tmp);
1164 if (!type)
1165 continue;
1167 if (tmp->ident) {
1168 member = member_expression(expr, op, tmp->ident);
1169 if (get_state_expr(SMATCH_EXTRA, member))
1170 continue;
1173 if (type->type == SYM_UNION || type->type == SYM_STRUCT) {
1174 set_inner_struct_members(expr, tmp);
1175 continue;
1177 if (type->type == SYM_ARRAY)
1178 continue;
1179 if (!tmp->ident)
1180 continue;
1182 assign = assign_expression(member, zero_expr());
1183 __split_expr(assign);
1184 } END_FOR_EACH_PTR(tmp);
1187 static void fake_member_assigns_helper(struct expression *symbol, struct expression_list *members, fake_cb *fake_cb)
1189 struct expression *deref, *assign, *tmp;
1190 struct symbol *struct_type, *type;
1191 struct ident *member;
1192 int member_idx;
1193 struct member_set *member_set;
1195 struct_type = get_type(symbol);
1196 if (!struct_type ||
1197 (struct_type->type != SYM_STRUCT && struct_type->type != SYM_UNION))
1198 return;
1200 member_set = alloc_member_set(struct_type);
1202 member_idx = 0;
1203 FOR_EACH_PTR(members, tmp) {
1204 member = number_to_member(symbol, member_idx);
1205 while (tmp->type == EXPR_IDENTIFIER) {
1206 member = tmp->expr_ident;
1207 member_idx = member_to_number(symbol, member);
1208 tmp = tmp->ident_expression;
1210 mark_member_as_set(struct_type, member_set, member);
1211 member_idx++;
1212 deref = member_expression(symbol, '.', member);
1213 if (tmp->type == EXPR_INITIALIZER) {
1214 type = get_type(deref);
1215 if (type && type->type == SYM_ARRAY)
1216 fake_element_assigns_helper(deref, tmp->expr_list, fake_cb);
1217 else
1218 fake_member_assigns_helper(deref, tmp->expr_list, fake_cb);
1219 } else {
1220 assign = assign_expression(deref, tmp);
1221 fake_cb(assign);
1223 } END_FOR_EACH_PTR(tmp);
1225 set_unset_to_zero(struct_type, symbol);
1228 static void fake_member_assigns(struct symbol *sym, fake_cb *fake_cb)
1230 fake_member_assigns_helper(symbol_expression(sym),
1231 sym->initializer->expr_list, fake_cb);
1234 static void fake_element_assigns_helper(struct expression *array, struct expression_list *expr_list, fake_cb *fake_cb)
1236 struct expression *offset, *binop, *assign, *tmp;
1237 struct symbol *type;
1238 int idx;
1240 if (ptr_list_size((struct ptr_list *)expr_list) > 1000)
1241 return;
1243 idx = 0;
1244 FOR_EACH_PTR(expr_list, tmp) {
1245 if (tmp->type == EXPR_INDEX) {
1246 if (tmp->idx_from != tmp->idx_to)
1247 return;
1248 idx = tmp->idx_from;
1249 if (!tmp->idx_expression)
1250 goto next;
1251 tmp = tmp->idx_expression;
1253 offset = value_expr(idx);
1254 binop = array_element_expression(array, offset);
1255 if (tmp->type == EXPR_INITIALIZER) {
1256 type = get_type(binop);
1257 if (type && type->type == SYM_ARRAY)
1258 fake_element_assigns_helper(binop, tmp->expr_list, fake_cb);
1259 else
1260 fake_member_assigns_helper(binop, tmp->expr_list, fake_cb);
1261 } else {
1262 assign = assign_expression(binop, tmp);
1263 fake_cb(assign);
1265 next:
1266 idx++;
1267 } END_FOR_EACH_PTR(tmp);
1270 static void fake_element_assigns(struct symbol *sym, fake_cb *fake_cb)
1272 fake_element_assigns_helper(symbol_expression(sym), sym->initializer->expr_list, fake_cb);
1275 static void fake_assign_expr(struct symbol *sym)
1277 struct expression *assign, *symbol;
1279 symbol = symbol_expression(sym);
1280 assign = assign_expression(symbol, sym->initializer);
1281 __split_expr(assign);
1284 static void call_split_expr(struct expression *expr)
1286 __split_expr(expr);
1289 static void do_initializer_stuff(struct symbol *sym)
1291 if (!sym->initializer)
1292 return;
1294 if (sym->initializer->type == EXPR_INITIALIZER) {
1295 if (get_real_base_type(sym)->type == SYM_ARRAY)
1296 fake_element_assigns(sym, call_split_expr);
1297 else
1298 fake_member_assigns(sym, call_split_expr);
1299 } else {
1300 fake_assign_expr(sym);
1304 static void split_declaration(struct symbol_list *sym_list)
1306 struct symbol *sym;
1308 FOR_EACH_PTR(sym_list, sym) {
1309 __pass_to_client(sym, DECLARATION_HOOK);
1310 do_initializer_stuff(sym);
1311 split_sym(sym);
1312 } END_FOR_EACH_PTR(sym);
1315 static void call_global_assign_hooks(struct expression *assign)
1317 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1320 static void fake_global_assign(struct symbol *sym)
1322 struct expression *assign, *symbol;
1324 if (get_real_base_type(sym)->type == SYM_ARRAY) {
1325 if (sym->initializer && sym->initializer->type == EXPR_INITIALIZER) {
1326 fake_element_assigns(sym, call_global_assign_hooks);
1327 } else if (sym->initializer) {
1328 symbol = symbol_expression(sym);
1329 assign = assign_expression(symbol, sym->initializer);
1330 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1331 } else {
1332 fake_element_assigns_helper(symbol_expression(sym), NULL, call_global_assign_hooks);
1334 } else if (get_real_base_type(sym)->type == SYM_STRUCT) {
1335 if (sym->initializer && sym->initializer->type == EXPR_INITIALIZER) {
1336 fake_member_assigns(sym, call_global_assign_hooks);
1337 } else if (sym->initializer) {
1338 symbol = symbol_expression(sym);
1339 assign = assign_expression(symbol, sym->initializer);
1340 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1341 } else {
1342 fake_member_assigns_helper(symbol_expression(sym), NULL, call_global_assign_hooks);
1344 } else {
1345 symbol = symbol_expression(sym);
1346 if (sym->initializer)
1347 assign = assign_expression(symbol, sym->initializer);
1348 else
1349 assign = assign_expression(symbol, zero_expr());
1350 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1354 static void start_function_definition(struct symbol *sym)
1356 __in_function_def = 1;
1357 __pass_to_client(sym, FUNC_DEF_HOOK);
1358 __in_function_def = 0;
1359 __pass_to_client(sym, AFTER_DEF_HOOK);
1363 static void split_function(struct symbol *sym)
1365 struct symbol *base_type = get_base_type(sym);
1367 if (!base_type->stmt && !base_type->inline_stmt)
1368 return;
1370 gettimeofday(&fn_start_time, NULL);
1371 cur_func_sym = sym;
1372 if (sym->ident)
1373 cur_func = sym->ident->name;
1374 __smatch_lineno = sym->pos.line;
1375 loop_count = 0;
1376 last_goto_statement_handled = 0;
1377 sm_debug("new function: %s\n", cur_func);
1378 __stree_id = 0;
1379 if (option_two_passes) {
1380 __unnullify_path();
1381 loop_num = 0;
1382 final_pass = 0;
1383 start_function_definition(sym);
1384 __split_stmt(base_type->stmt);
1385 __split_stmt(base_type->inline_stmt);
1386 nullify_path();
1388 __unnullify_path();
1389 loop_num = 0;
1390 final_pass = 1;
1391 start_function_definition(sym);
1392 __split_stmt(base_type->stmt);
1393 __split_stmt(base_type->inline_stmt);
1394 __pass_to_client(sym, END_FUNC_HOOK);
1395 __pass_to_client(sym, AFTER_FUNC_HOOK);
1397 clear_all_states();
1398 cur_func_sym = NULL;
1399 cur_func = NULL;
1400 free_data_info_allocs();
1401 free_expression_stack(&switch_expr_stack);
1402 __free_ptr_list((struct ptr_list **)&big_statement_stack);
1403 __bail_on_rest_of_function = 0;
1406 static void parse_inline(struct expression *call)
1408 struct symbol *base_type;
1409 int loop_num_bak = loop_num;
1410 int final_pass_bak = final_pass;
1411 char *cur_func_bak = cur_func;
1412 struct statement_list *big_statement_stack_bak = big_statement_stack;
1413 struct expression_list *big_expression_stack_bak = big_expression_stack;
1414 struct expression_list *switch_expr_stack_bak = switch_expr_stack;
1415 struct symbol *cur_func_sym_bak = cur_func_sym;
1417 __pass_to_client(call, INLINE_FN_START);
1418 final_pass = 0; /* don't print anything */
1419 __inline_fn = call;
1421 base_type = get_base_type(call->fn->symbol);
1422 cur_func_sym = call->fn->symbol;
1423 if (call->fn->symbol->ident)
1424 cur_func = call->fn->symbol->ident->name;
1425 else
1426 cur_func = NULL;
1427 set_position(call->fn->symbol->pos);
1429 save_all_states();
1430 big_statement_stack = NULL;
1431 big_expression_stack = NULL;
1432 switch_expr_stack = NULL;
1434 sm_debug("inline function: %s\n", cur_func);
1435 __unnullify_path();
1436 loop_num = 0;
1437 start_function_definition(call->fn->symbol);
1438 __split_stmt(base_type->stmt);
1439 __split_stmt(base_type->inline_stmt);
1440 __pass_to_client(call->fn->symbol, END_FUNC_HOOK);
1441 __pass_to_client(call->fn->symbol, AFTER_FUNC_HOOK);
1443 free_expression_stack(&switch_expr_stack);
1444 __free_ptr_list((struct ptr_list **)&big_statement_stack);
1445 nullify_path();
1446 free_goto_stack();
1448 loop_num = loop_num_bak;
1449 final_pass = final_pass_bak;
1450 cur_func_sym = cur_func_sym_bak;
1451 cur_func = cur_func_bak;
1452 big_statement_stack = big_statement_stack_bak;
1453 big_expression_stack = big_expression_stack_bak;
1454 switch_expr_stack = switch_expr_stack_bak;
1456 restore_all_states();
1457 set_position(call->pos);
1458 __inline_fn = NULL;
1459 __pass_to_client(call, INLINE_FN_END);
1462 static struct symbol_list *inlines_called;
1463 static void add_inline_function(struct symbol *sym)
1465 static struct symbol_list *already_added;
1466 struct symbol *tmp;
1468 FOR_EACH_PTR(already_added, tmp) {
1469 if (tmp == sym)
1470 return;
1471 } END_FOR_EACH_PTR(tmp);
1473 add_ptr_list(&already_added, sym);
1474 add_ptr_list(&inlines_called, sym);
1477 static void process_inlines(void)
1479 struct symbol *tmp;
1481 FOR_EACH_PTR(inlines_called, tmp) {
1482 split_function(tmp);
1483 } END_FOR_EACH_PTR(tmp);
1484 free_ptr_list(&inlines_called);
1487 static struct symbol *get_last_scoped_symbol(struct symbol_list *big_list, int use_static)
1489 struct symbol *sym;
1491 FOR_EACH_PTR_REVERSE(big_list, sym) {
1492 if (!sym->scope)
1493 continue;
1494 if (use_static && sym->ctype.modifiers & MOD_STATIC)
1495 return sym;
1496 if (!use_static && !(sym->ctype.modifiers & MOD_STATIC))
1497 return sym;
1498 } END_FOR_EACH_PTR_REVERSE(sym);
1500 return NULL;
1503 static void split_inlines_in_scope(struct symbol *sym)
1505 struct symbol *base;
1506 struct symbol_list *scope_list;
1507 int stream;
1509 scope_list = sym->scope->symbols;
1510 stream = sym->pos.stream;
1512 /* find the last static symbol in the file */
1513 FOR_EACH_PTR_REVERSE(scope_list, sym) {
1514 if (sym->pos.stream != stream)
1515 continue;
1516 if (sym->type != SYM_NODE)
1517 continue;
1518 base = get_base_type(sym);
1519 if (!base)
1520 continue;
1521 if (base->type != SYM_FN)
1522 continue;
1523 if (!base->inline_stmt)
1524 continue;
1525 add_inline_function(sym);
1526 } END_FOR_EACH_PTR_REVERSE(sym);
1528 process_inlines();
1531 static void split_inlines(struct symbol_list *sym_list)
1533 struct symbol *sym;
1535 sym = get_last_scoped_symbol(sym_list, 0);
1536 if (sym)
1537 split_inlines_in_scope(sym);
1538 sym = get_last_scoped_symbol(sym_list, 1);
1539 if (sym)
1540 split_inlines_in_scope(sym);
1543 static struct stree *clone_estates_perm(struct stree *orig)
1545 struct stree *ret = NULL;
1546 struct sm_state *tmp;
1548 FOR_EACH_SM(orig, tmp) {
1549 set_state_stree_perm(&ret, tmp->owner, tmp->name, tmp->sym, clone_estate_perm(tmp->state));
1550 } END_FOR_EACH_SM(tmp);
1552 return ret;
1555 static void split_functions(struct symbol_list *sym_list)
1557 struct symbol *sym;
1559 __unnullify_path();
1560 FOR_EACH_PTR(sym_list, sym) {
1561 set_position(sym->pos);
1562 if (sym->type != SYM_NODE || get_base_type(sym)->type != SYM_FN) {
1563 __pass_to_client(sym, BASE_HOOK);
1564 fake_global_assign(sym);
1566 } END_FOR_EACH_PTR(sym);
1567 global_states = clone_estates_perm(get_all_states_stree(SMATCH_EXTRA));
1568 nullify_path();
1570 FOR_EACH_PTR(sym_list, sym) {
1571 set_position(sym->pos);
1572 if (sym->type == SYM_NODE && get_base_type(sym)->type == SYM_FN) {
1573 split_function(sym);
1574 process_inlines();
1576 } END_FOR_EACH_PTR(sym);
1577 split_inlines(sym_list);
1578 __pass_to_client(sym_list, END_FILE_HOOK);
1581 void smatch(int argc, char **argv)
1584 struct string_list *filelist = NULL;
1585 struct symbol_list *sym_list;
1587 if (argc < 2) {
1588 printf("Usage: smatch [--debug] <filename.c>\n");
1589 exit(1);
1591 sparse_initialize(argc, argv, &filelist);
1592 set_valid_ptr_max();
1593 FOR_EACH_PTR_NOTAG(filelist, base_file) {
1594 if (option_file_output) {
1595 char buf[256];
1597 snprintf(buf, sizeof(buf), "%s.smatch", base_file);
1598 sm_outfd = fopen(buf, "w");
1599 if (!sm_outfd) {
1600 printf("Error: Cannot open %s\n", base_file);
1601 exit(1);
1604 sym_list = sparse_keep_tokens(base_file);
1605 split_functions(sym_list);
1606 } END_FOR_EACH_PTR_NOTAG(base_file);