math: array parameters can be NULL
[smatch.git] / lib.c
blob21634bc80dd49c8fc1fbdcc04b9f79c4e0f9bb14
1 /*
2 * 'sparse' library helper routines.
4 * Copyright (C) 2003 Transmeta Corp.
5 * 2003-2004 Linus Torvalds
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
25 #include <ctype.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <stdarg.h>
29 #include <stddef.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <assert.h>
36 #include <sys/types.h>
38 #include "lib.h"
39 #include "allocate.h"
40 #include "token.h"
41 #include "parse.h"
42 #include "symbol.h"
43 #include "expression.h"
44 #include "evaluate.h"
45 #include "scope.h"
46 #include "linearize.h"
47 #include "target.h"
48 #include "machine.h"
49 #include "version.h"
50 #include "bits.h"
52 int parse_error;
54 static void do_warn(const char *type, struct position pos, const char * fmt, va_list args)
56 static char buffer[512];
57 const char *name;
59 /* Shut up warnings if position is bad_token.pos */
60 if (pos.type == TOKEN_BAD)
61 return;
63 vsprintf(buffer, fmt, args);
64 name = stream_name(pos.stream);
66 fflush(stdout);
67 fprintf(stderr, "%s:%d:%d: %s%s%s\n",
68 name, pos.line, pos.pos, diag_prefix, type, buffer);
71 static int show_info = 1;
73 void info(struct position pos, const char * fmt, ...)
75 va_list args;
77 if (!show_info)
78 return;
79 va_start(args, fmt);
80 do_warn("", pos, fmt, args);
81 va_end(args);
84 static void do_error(struct position pos, const char * fmt, va_list args)
86 static int errors = 0;
88 parse_error = 1;
89 die_if_error = 1;
90 show_info = 1;
91 /* Shut up warnings if position is bad_token.pos */
92 if (pos.type == TOKEN_BAD)
93 return;
94 /* Shut up warnings after an error */
95 has_error |= ERROR_CURR_PHASE;
96 if (errors > 100) {
97 static int once = 0;
98 show_info = 0;
99 if (once)
100 return;
101 fmt = "too many errors";
102 once = 1;
105 do_warn("error: ", pos, fmt, args);
106 errors++;
109 void warning(struct position pos, const char * fmt, ...)
111 va_list args;
113 if (Wsparse_error) {
114 va_start(args, fmt);
115 do_error(pos, fmt, args);
116 va_end(args);
117 return;
120 if (!fmax_warnings || has_error) {
121 show_info = 0;
122 return;
125 if (!--fmax_warnings) {
126 show_info = 0;
127 fmt = "too many warnings";
130 va_start(args, fmt);
131 do_warn("warning: ", pos, fmt, args);
132 va_end(args);
135 void sparse_error(struct position pos, const char * fmt, ...)
137 va_list args;
138 va_start(args, fmt);
139 do_error(pos, fmt, args);
140 va_end(args);
143 void expression_error(struct expression *expr, const char *fmt, ...)
145 va_list args;
146 va_start(args, fmt);
147 do_error(expr->pos, fmt, args);
148 va_end(args);
149 expr->ctype = &bad_ctype;
152 NORETURN_ATTR
153 void error_die(struct position pos, const char * fmt, ...)
155 va_list args;
156 va_start(args, fmt);
157 do_warn("error: ", pos, fmt, args);
158 va_end(args);
159 exit(1);
162 NORETURN_ATTR
163 void die(const char *fmt, ...)
165 va_list args;
166 static char buffer[512];
168 va_start(args, fmt);
169 vsnprintf(buffer, sizeof(buffer), fmt, args);
170 va_end(args);
172 fprintf(stderr, "%s%s\n", diag_prefix, buffer);
173 exit(1);
176 ////////////////////////////////////////////////////////////////////////////////
178 static struct token *pre_buffer_begin = NULL;
179 static struct token **pre_buffer_next = &pre_buffer_begin;
181 void add_pre_buffer(const char *fmt, ...)
183 va_list args;
184 unsigned int size;
185 struct token *begin, *end;
186 char buffer[4096];
188 va_start(args, fmt);
189 size = vsnprintf(buffer, sizeof(buffer), fmt, args);
190 va_end(args);
191 begin = tokenize_buffer(buffer, size, &end);
192 *pre_buffer_next = begin;
193 pre_buffer_next = &end->next;
196 static void create_builtin_stream(void)
198 // Temporary hack
199 add_pre_buffer("#define _Pragma(x)\n");
201 /* add the multiarch include directories, if any */
202 if (multiarch_dir && *multiarch_dir) {
203 add_pre_buffer("#add_system \"/usr/include/%s\"\n", multiarch_dir);
204 add_pre_buffer("#add_system \"/usr/local/include/%s\"\n", multiarch_dir);
207 /* We add compiler headers path here because we have to parse
208 * the arguments to get it, falling back to default. */
209 add_pre_buffer("#add_system \"%s/include\"\n", gcc_base_dir);
210 add_pre_buffer("#add_system \"%s/include-fixed\"\n", gcc_base_dir);
212 add_pre_buffer("#define __builtin_stdarg_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
213 add_pre_buffer("#define __builtin_va_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
214 add_pre_buffer("#define __builtin_ms_va_start(a,b) ((a) = (__builtin_ms_va_list)(&(b)))\n");
215 add_pre_buffer("#define __builtin_va_arg(arg,type) ({ type __va_arg_ret = *(type *)(arg); arg += sizeof(type); __va_arg_ret; })\n");
216 add_pre_buffer("#define __builtin_va_alist (*(void *)0)\n");
217 add_pre_buffer("#define __builtin_va_arg_incr(x) ((x) + 1)\n");
218 add_pre_buffer("#define __builtin_va_copy(dest, src) ({ dest = src; (void)0; })\n");
219 add_pre_buffer("#define __builtin_ms_va_copy(dest, src) ({ dest = src; (void)0; })\n");
220 add_pre_buffer("#define __builtin_va_end(arg)\n");
221 add_pre_buffer("#define __builtin_ms_va_end(arg)\n");
222 add_pre_buffer("#define __builtin_va_arg_pack()\n");
225 static struct symbol_list *sparse_tokenstream(struct token *token)
227 int builtin = token && !token->pos.stream;
229 // Preprocess the stream
230 token = preprocess(token);
232 if (dump_macro_defs || dump_macros_only) {
233 if (!builtin)
234 dump_macro_definitions();
235 if (dump_macros_only)
236 return NULL;
239 if (preprocess_only) {
240 while (!eof_token(token)) {
241 int prec = 1;
242 struct token *next = token->next;
243 const char *separator = "";
244 if (next->pos.whitespace)
245 separator = " ";
246 if (next->pos.newline) {
247 separator = "\n\t\t\t\t\t";
248 prec = next->pos.pos;
249 if (prec > 4)
250 prec = 4;
252 printf("%s%.*s", show_token(token), prec, separator);
253 token = next;
255 putchar('\n');
257 return NULL;
260 // Parse the resulting C code
261 while (!eof_token(token))
262 token = external_declaration(token, &translation_unit_used_list, NULL);
263 return translation_unit_used_list;
266 static struct symbol_list *sparse_file(const char *filename)
268 int fd;
269 struct token *token;
271 if (strcmp(filename, "-") == 0) {
272 fd = 0;
273 } else {
274 fd = open(filename, O_RDONLY);
275 if (fd < 0)
276 die("No such file: %s", filename);
278 base_filename = filename;
280 // Tokenize the input stream
281 token = tokenize(filename, fd, NULL, includepath);
282 store_all_tokens(token);
283 close(fd);
285 return sparse_tokenstream(token);
289 * This handles the "-include" directive etc: we're in global
290 * scope, and all types/macros etc will affect all the following
291 * files.
293 * NOTE NOTE NOTE! "#undef" of anything in this stage will
294 * affect all subsequent files too, i.e. we can have non-local
295 * behaviour between files!
297 static struct symbol_list *sparse_initial(void)
299 int i;
301 // Prepend any "include" file to the stream.
302 // We're in global scope, it will affect all files!
303 for (i = 0; i < cmdline_include_nr; i++)
304 add_pre_buffer("#argv_include \"%s\"\n", cmdline_include[i]);
306 return sparse_tokenstream(pre_buffer_begin);
309 struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list **filelist)
311 char **args;
312 struct symbol_list *list;
314 // Initialize symbol stream first, so that we can add defines etc
315 init_symbols();
316 init_include_path();
318 // initialize the default target to the native 'machine'
319 target_config(MACH_NATIVE);
321 args = argv;
322 for (;;) {
323 char *arg = *++args;
324 if (!arg)
325 break;
327 if (arg[0] == '-' && arg[1]) {
328 args = handle_switch(arg+1, args);
329 continue;
331 add_ptr_list(filelist, arg);
333 handle_switch_finalize();
335 // Redirect stdout if needed
336 if (dump_macro_defs || preprocess_only)
337 do_output = 1;
338 if (do_output && outfile && strcmp(outfile, "-")) {
339 if (!freopen(outfile, "w", stdout))
340 die("error: cannot open %s: %s", outfile, strerror(errno));
343 if (fdump_ir == 0)
344 fdump_ir = PASS_FINAL;
346 list = NULL;
347 if (filelist) {
348 // Initialize type system
349 target_init();
350 init_ctype();
352 predefined_macros();
353 create_builtin_stream();
354 init_builtins(0);
356 list = sparse_initial();
359 * Protect the initial token allocations, since
360 * they need to survive all the others
362 protect_token_alloc();
365 * Evaluate the complete symbol list
366 * Note: This is not needed for normal cases.
367 * These symbols should only be predefined defines and
368 * declaratons which will be evaluated later, when needed.
369 * This is also the case when a file is directly included via
370 * '-include <file>' on the command line *AND* the file only
371 * contains defines, declarations and inline definitions.
372 * However, in the rare cases where the given file should
373 * contain some definitions, these will never be evaluated
374 * and thus won't be able to be linearized correctly.
375 * Hence the evaluate_symbol_list() here under.
377 evaluate_symbol_list(list);
378 return list;
381 struct symbol_list * sparse_keep_tokens(char *filename)
383 struct symbol_list *res;
385 /* Clear previous symbol list */
386 translation_unit_used_list = NULL;
388 new_file_scope();
389 res = sparse_file(filename);
391 /* And return it */
392 return res;
396 struct symbol_list * __sparse(char *filename)
398 struct symbol_list *res;
400 res = sparse_keep_tokens(filename);
402 /* Drop the tokens for this file after parsing */
403 clear_token_alloc();
405 /* And return it */
406 return res;
409 struct symbol_list * sparse(char *filename)
411 struct symbol_list *res = __sparse(filename);
413 if (has_error & ERROR_CURR_PHASE)
414 has_error = ERROR_PREV_PHASE;
415 /* Evaluate the complete symbol list */
416 evaluate_symbol_list(res);
418 return res;