aboutsummaryrefslogtreecommitdiff
blob: b5ecb50142362a9f47d2a2fe80e6fffba00dac9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 * Example trivial client program that uses the sparse library
 * to tokenize, pre-process and parse a C file, and prints out
 * the results.
 *
 * Copyright (C) 2003 Linus Torvalds, all rights reserved.
 */
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>

#include "lib.h"
#include "token.h"
#include "parse.h"
#include "symbol.h"
#include "expression.h"

static void handle_switch(char *arg)
{
}

static void clean_up_statement(struct statement *stmt, void *_parent, int flags);
static void clean_up_symbol(struct symbol *sym, void *_parent, int flags);

static void simplify_statement(struct statement *stmt, struct symbol *fn)
{
	if (!stmt)
		return;
	switch (stmt->type) {
	case STMT_RETURN:
	case STMT_EXPRESSION:
		evaluate_expression(stmt->expression);
		return;
	case STMT_COMPOUND:
		symbol_iterate(stmt->syms, clean_up_symbol, fn);
		statement_iterate(stmt->stmts, clean_up_statement, fn);
		return;
	case STMT_IF:
		evaluate_expression(stmt->if_conditional);
		simplify_statement(stmt->if_true, fn);
		simplify_statement(stmt->if_false, fn);
		return;
	case STMT_ITERATOR:
		evaluate_expression(stmt->iterator_pre_condition);
		evaluate_expression(stmt->iterator_post_condition);
		simplify_statement(stmt->iterator_pre_statement, fn);
		simplify_statement(stmt->iterator_statement, fn);
		simplify_statement(stmt->iterator_post_statement, fn);
		return;
	case STMT_SWITCH:
		evaluate_expression(stmt->switch_expression);
		simplify_statement(stmt->switch_statement, fn);
		return;
	case STMT_CASE:
		evaluate_expression(stmt->case_expression);
		evaluate_expression(stmt->case_to);
		simplify_statement(stmt->case_statement, fn);
		return;
	}
}

static void clean_up_statement(struct statement *stmt, void *_parent, int flags)
{
	struct symbol *parent = _parent;
	simplify_statement(stmt, parent);
}

static void clean_up_symbol(struct symbol *sym, void *_parent, int flags)
{
	struct symbol *parent = _parent;
	struct symbol *type;

	examine_symbol_type(sym);
	type = sym->ctype.base_type;
	if (type && type->type == SYM_FN) {
		symbol_iterate(type->arguments, clean_up_symbol, parent);
		if (type->stmt)
			simplify_statement(type->stmt, sym);
	}
}

int main(int argc, char **argv)
{
	int i, fd;
	char *filename = NULL;
	struct token *token;
	struct symbol_list *list = NULL;

	// Initialize symbol stream first, so that we can add defines etc
	init_symbols();

	for (i = 1; i < argc; i++) {
		char *arg = argv[i];
		if (arg[0] == '-') {
			handle_switch(arg+1);
			continue;
		}
		filename = arg;
	}
		

	fd = open(filename, O_RDONLY);
	if (fd < 0)
		die("No such file: %s", argv[1]);

	// Tokenize the input stream
	token = tokenize(filename, fd, NULL);
	close(fd);

	// Pre-process the stream
	token = preprocess(token);

	// Parse the resulting C code
	translation_unit(token, &list);

	// Do type evaluation and simplify
	symbol_iterate(list, clean_up_symbol, NULL);

#if 1
	// Show the end result.
	show_symbol_list(list, "\n\n");
	printf("\n\n");
#endif

	// And show the allocation statistics
	show_ident_alloc();
	show_token_alloc();
	show_symbol_alloc();
	show_expression_alloc();
	show_statement_alloc();
	show_string_alloc();
	show_bytes_alloc();
	return 0;
}