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
36 #include <sys/types.h>
43 #include "expression.h"
46 #include "linearize.h"
54 static int prettify(const char **fnamep
)
56 const char *name
= *fnamep
;
57 int len
= strlen(name
);
59 if (len
> 2 && !memcmp(name
, "./", 2)) {
68 static const char *show_include_chain(int stream
, const char *base
)
70 static char buffer
[200];
73 while ((stream
= stream_prev(stream
)) >= 0) {
74 const char *p
= stream_name(stream
);
80 pretty_len
= prettify(&p
);
85 * At worst, we'll need " (through %s, ...)" in addition to the
88 if (pretty_len
+ len
+ 20 > sizeof(buffer
)) {
91 memcpy(buffer
+len
, ", ...", 5);
97 memcpy(buffer
, " (through ", 10);
104 memcpy(buffer
+len
, p
, pretty_len
);
115 static const char *show_stream_name(struct position pos
)
117 const char *name
= stream_name(pos
.stream
);
118 static const char *last
;
120 if (name
== base_filename
)
126 fprintf(stderr
, "%s: note: in included file%s:\n",
128 show_include_chain(pos
.stream
, base_filename
));
132 static void do_warn(const char *type
, struct position pos
, const char * fmt
, va_list args
)
134 static char buffer
[512];
136 /* Shut up warnings if position is bad_token.pos */
137 if (pos
.type
== TOKEN_BAD
)
140 vsprintf(buffer
, fmt
, args
);
143 fprintf(stderr
, "%s:%d:%d: %s%s%s\n",
144 show_stream_name(pos
), pos
.line
, pos
.pos
,
145 diag_prefix
, type
, buffer
);
148 static int show_info
= 1;
150 void info(struct position pos
, const char * fmt
, ...)
157 do_warn("", pos
, fmt
, args
);
161 static void do_error(struct position pos
, const char * fmt
, va_list args
)
163 static int errors
= 0;
168 /* Shut up warnings if position is bad_token.pos */
169 if (pos
.type
== TOKEN_BAD
)
171 /* Shut up warnings after an error */
172 has_error
|= ERROR_CURR_PHASE
;
173 if (errors
> fmax_errors
) {
178 fmt
= "too many errors";
182 do_warn("error: ", pos
, fmt
, args
);
186 void warning(struct position pos
, const char * fmt
, ...)
192 do_error(pos
, fmt
, args
);
197 if (!fmax_warnings
|| has_error
) {
202 if (!--fmax_warnings
) {
204 fmt
= "too many warnings";
208 do_warn("warning: ", pos
, fmt
, args
);
212 void sparse_error(struct position pos
, const char * fmt
, ...)
216 do_error(pos
, fmt
, args
);
220 void expression_error(struct expression
*expr
, const char *fmt
, ...)
224 do_error(expr
->pos
, fmt
, args
);
226 expr
->ctype
= &bad_ctype
;
230 void error_die(struct position pos
, const char * fmt
, ...)
234 do_warn("error: ", pos
, fmt
, args
);
240 void die(const char *fmt
, ...)
243 static char buffer
[512];
246 vsnprintf(buffer
, sizeof(buffer
), fmt
, args
);
249 fprintf(stderr
, "%s%s\n", diag_prefix
, buffer
);
253 ////////////////////////////////////////////////////////////////////////////////
255 static struct token
*pre_buffer_begin
= NULL
;
256 static struct token
**pre_buffer_next
= &pre_buffer_begin
;
258 void add_pre_buffer(const char *fmt
, ...)
262 struct token
*begin
, *end
;
266 size
= vsnprintf(buffer
, sizeof(buffer
), fmt
, args
);
268 begin
= tokenize_buffer(buffer
, size
, &end
);
269 *pre_buffer_next
= begin
;
270 pre_buffer_next
= &end
->next
;
273 static void create_builtin_stream(void)
276 add_pre_buffer("#define _Pragma(x)\n");
278 /* add the multiarch include directories, if any */
279 if (multiarch_dir
&& *multiarch_dir
) {
280 add_pre_buffer("#add_system \"/usr/include/%s\"\n", multiarch_dir
);
281 add_pre_buffer("#add_system \"/usr/local/include/%s\"\n", multiarch_dir
);
284 /* We add compiler headers path here because we have to parse
285 * the arguments to get it, falling back to default. */
286 add_pre_buffer("#add_system \"%s/include\"\n", gcc_base_dir
);
287 add_pre_buffer("#add_system \"%s/include-fixed\"\n", gcc_base_dir
);
289 add_pre_buffer("#define __builtin_stdarg_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
290 add_pre_buffer("#define __builtin_va_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
291 add_pre_buffer("#define __builtin_ms_va_start(a,b) ((a) = (__builtin_ms_va_list)(&(b)))\n");
292 add_pre_buffer("#define __builtin_va_arg(arg,type) ({ type __va_arg_ret = *(type *)(arg); arg += sizeof(type); __va_arg_ret; })\n");
293 add_pre_buffer("#define __builtin_va_alist (*(void *)0)\n");
294 add_pre_buffer("#define __builtin_va_arg_incr(x) ((x) + 1)\n");
295 add_pre_buffer("#define __builtin_va_copy(dest, src) ({ dest = src; (void)0; })\n");
296 add_pre_buffer("#define __builtin_ms_va_copy(dest, src) ({ dest = src; (void)0; })\n");
297 add_pre_buffer("#define __builtin_va_end(arg)\n");
298 add_pre_buffer("#define __builtin_ms_va_end(arg)\n");
299 add_pre_buffer("#define __builtin_va_arg_pack()\n");
302 static struct symbol_list
*sparse_tokenstream(struct token
*token
)
304 int builtin
= token
&& !token
->pos
.stream
;
306 // Preprocess the stream
307 token
= preprocess(token
);
309 if (dump_macro_defs
|| dump_macros_only
) {
311 dump_macro_definitions();
312 if (dump_macros_only
)
316 if (preprocess_only
) {
317 while (!eof_token(token
)) {
319 struct token
*next
= token
->next
;
320 const char *separator
= "";
321 if (next
->pos
.whitespace
)
323 if (next
->pos
.newline
) {
324 separator
= "\n\t\t\t\t\t";
325 prec
= next
->pos
.pos
;
329 printf("%s%.*s", show_token(token
), prec
, separator
);
337 // Parse the resulting C code
338 while (!eof_token(token
))
339 token
= external_declaration(token
, &translation_unit_used_list
, NULL
);
340 return translation_unit_used_list
;
343 static struct symbol_list
*sparse_file(const char *filename
)
348 if (strcmp(filename
, "-") == 0) {
351 fd
= open(filename
, O_RDONLY
);
353 die("No such file: %s", filename
);
355 base_filename
= filename
;
357 // Tokenize the input stream
358 token
= tokenize(NULL
, filename
, fd
, NULL
, includepath
);
359 store_all_tokens(token
);
363 return sparse_tokenstream(token
);
367 * This handles the "-include" directive etc: we're in global
368 * scope, and all types/macros etc will affect all the following
371 * NOTE NOTE NOTE! "#undef" of anything in this stage will
372 * affect all subsequent files too, i.e. we can have non-local
373 * behaviour between files!
375 static struct symbol_list
*sparse_initial(void)
379 // Prepend any "include" file to the stream.
380 // We're in global scope, it will affect all files!
381 for (i
= 0; i
< cmdline_include_nr
; i
++)
382 add_pre_buffer("#argv_include \"%s\"\n", cmdline_include
[i
]);
384 return sparse_tokenstream(pre_buffer_begin
);
387 struct symbol_list
*sparse_initialize(int argc
, char **argv
, struct string_list
**filelist
)
390 struct symbol_list
*list
;
392 base_filename
= "command-line";
394 // Initialize symbol stream first, so that we can add defines etc
398 // initialize the default target to the native 'machine'
399 target_config(MACH_NATIVE
);
407 if (arg
[0] == '-' && arg
[1]) {
408 args
= handle_switch(arg
+1, args
);
411 add_ptr_list(filelist
, arg
);
413 handle_switch_finalize();
415 // Redirect stdout if needed
416 if (dump_macro_defs
|| preprocess_only
)
418 if (do_output
&& outfile
&& strcmp(outfile
, "-")) {
419 if (!freopen(outfile
, "w", stdout
))
420 die("error: cannot open %s: %s", outfile
, strerror(errno
));
424 fdump_ir
= PASS_FINAL
;
428 // Initialize type system
433 create_builtin_stream();
436 list
= sparse_initial();
439 * Protect the initial token allocations, since
440 * they need to survive all the others
442 protect_token_alloc();
445 * Evaluate the complete symbol list
446 * Note: This is not needed for normal cases.
447 * These symbols should only be predefined defines and
448 * declaratons which will be evaluated later, when needed.
449 * This is also the case when a file is directly included via
450 * '-include <file>' on the command line *AND* the file only
451 * contains defines, declarations and inline definitions.
452 * However, in the rare cases where the given file should
453 * contain some definitions, these will never be evaluated
454 * and thus won't be able to be linearized correctly.
455 * Hence the evaluate_symbol_list() here under.
457 evaluate_symbol_list(list
);
461 struct symbol_list
* sparse_keep_tokens(char *filename
)
463 struct symbol_list
*res
;
465 /* Clear previous symbol list */
466 translation_unit_used_list
= NULL
;
469 res
= sparse_file(filename
);
476 struct symbol_list
* __sparse(char *filename
)
478 struct symbol_list
*res
;
480 res
= sparse_keep_tokens(filename
);
482 /* Drop the tokens for this file after parsing */
489 struct symbol_list
* sparse(char *filename
)
491 struct symbol_list
*res
= __sparse(filename
);
493 if (has_error
& ERROR_CURR_PHASE
)
494 has_error
= ERROR_PREV_PHASE
;
495 /* Evaluate the complete symbol list */
496 evaluate_symbol_list(res
);