[PATCH] escape character extension
[smatch.git] / check.c
blob33df1bd56a7403a9d37a4df3db921c2837c57695
1 /*
2 * Example trivial client program that uses the sparse library
3 * to tokenize, pre-process and parse a C file, and prints out
4 * the results.
6 * Copyright (C) 2003 Transmeta Corp.
8 * Licensed under the Open Software License version 1.1
9 */
10 #include <stdarg.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <unistd.h>
16 #include <fcntl.h>
18 #include "lib.h"
19 #include "token.h"
20 #include "parse.h"
21 #include "symbol.h"
22 #include "expression.h"
24 static unsigned int pre_buffer_size = 0;
25 static unsigned char pre_buffer[8192];
27 static int preprocess_only;
28 static char *include = NULL;
29 static int include_fd = -1;
31 static void add_pre_buffer(const char *fmt, ...)
33 va_list args;
34 unsigned int size;
36 va_start(args, fmt);
37 size = pre_buffer_size;
38 size += vsnprintf(pre_buffer + size,
39 sizeof(pre_buffer) - size,
40 fmt, args);
41 pre_buffer_size = size;
42 va_end(args);
45 static char ** handle_switch(char *arg, char **next)
47 switch (*arg) {
48 case 'D': {
49 const char *name = arg+1;
50 const char *value = "";
51 for (;;) {
52 char c;
53 c = *++arg;
54 if (!c)
55 break;
56 if (isspace(c) || c == '=') {
57 *arg = '\0';
58 value = arg+1;
59 break;
62 add_pre_buffer("#define %s %s\n", name, value);
63 return next;
66 case 'E':
67 preprocess_only = 1;
68 return next;
70 case 'I':
71 add_pre_buffer("#add_include \"%s/\"\n", arg+1);
72 return next;
73 case 'i':
74 if (*next && !strcmp(arg, "include")) {
75 char *name = *++next;
76 int fd = open(name, O_RDONLY);
77 include_fd = fd;
78 include = name;
79 if (fd < 0)
80 perror(name);
81 return next;
83 /* Fallthrough */
84 default:
85 /* Ignore unknown command line options - they're probably gcc switches */
86 break;
88 return next;
91 static void clean_up_symbol(struct symbol *sym, void *_parent, int flags)
93 check_duplicates(sym);
94 evaluate_symbol(sym);
97 int main(int argc, char **argv)
99 int fd;
100 char *filename = NULL, **args;
101 struct token *token;
103 // Initialize symbol stream first, so that we can add defines etc
104 init_symbols();
106 add_pre_buffer("#define __i386__ 1\n");
107 add_pre_buffer("#define __linux__ 1\n");
108 add_pre_buffer("#define __STDC__ 1\n");
109 add_pre_buffer("#define linux linux\n");
110 add_pre_buffer("#define __CHECKER__ 1\n");
111 add_pre_buffer("#define cond_syscall(x)\n");
112 add_pre_buffer("#define __GNUC__ 2\n");
113 add_pre_buffer("#define __GNUC_MINOR__ 95\n");
114 add_pre_buffer("#define __func__ \"function\"\n");
115 add_pre_buffer("#define __extension__\n");
116 add_pre_buffer("extern void *__builtin_memcpy(void *, const void *, unsigned long);\n");
117 add_pre_buffer("extern void * __builtin_return_address(int);\n");
118 add_pre_buffer("#define __builtin_stdarg_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
119 add_pre_buffer("#define __builtin_va_arg(arg,type) ((type)0)\n");
120 add_pre_buffer("#define __builtin_va_end(arg)\n");
122 args = argv;
123 for (;;) {
124 char *arg = *++args;
125 if (!arg)
126 break;
127 if (arg[0] == '-') {
128 args = handle_switch(arg+1, args);
129 continue;
131 filename = arg;
135 fd = open(filename, O_RDONLY);
136 if (fd < 0)
137 die("No such file: %s", filename);
139 // Tokenize the input stream
140 token = tokenize(filename, fd, NULL);
141 close(fd);
143 // Prepend any "include" file to the stream.
144 if (include_fd >= 0)
145 token = tokenize(include, include_fd, token);
147 // Prepend the initial built-in stream
148 token = tokenize_buffer(pre_buffer, pre_buffer_size, token);
150 // Pre-process the stream
151 token = preprocess(token);
153 if (preprocess_only) {
154 while (!eof_token(token)) {
155 int prec = 1;
156 struct token *next = token->next;
157 char * separator = "";
158 if (next->pos.whitespace)
159 separator = " ";
160 if (next->pos.newline) {
161 separator = "\n\t\t\t\t\t";
162 prec = next->pos.pos;
163 if (prec > 4)
164 prec = 4;
166 printf("%s%.*s", show_token(token), prec, separator);
167 token = next;
169 putchar('\n');
171 return 0;
174 // Parse the resulting C code
175 translation_unit(token, &used_list);
177 // Do type evaluation and simplify
178 symbol_iterate(used_list, clean_up_symbol, NULL);
179 return 0;