1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * 'sparse' library helper routines.
3f08c3bdfSopenharmony_ci *
4f08c3bdfSopenharmony_ci * Copyright (C) 2003 Transmeta Corp.
5f08c3bdfSopenharmony_ci *               2003-2004 Linus Torvalds
6f08c3bdfSopenharmony_ci *
7f08c3bdfSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
8f08c3bdfSopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
9f08c3bdfSopenharmony_ci * in the Software without restriction, including without limitation the rights
10f08c3bdfSopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11f08c3bdfSopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
12f08c3bdfSopenharmony_ci * furnished to do so, subject to the following conditions:
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci * The above copyright notice and this permission notice shall be included in
15f08c3bdfSopenharmony_ci * all copies or substantial portions of the Software.
16f08c3bdfSopenharmony_ci *
17f08c3bdfSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18f08c3bdfSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f08c3bdfSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20f08c3bdfSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21f08c3bdfSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22f08c3bdfSopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23f08c3bdfSopenharmony_ci * THE SOFTWARE.
24f08c3bdfSopenharmony_ci */
25f08c3bdfSopenharmony_ci#include <ctype.h>
26f08c3bdfSopenharmony_ci#include <errno.h>
27f08c3bdfSopenharmony_ci#include <fcntl.h>
28f08c3bdfSopenharmony_ci#include <stdarg.h>
29f08c3bdfSopenharmony_ci#include <stddef.h>
30f08c3bdfSopenharmony_ci#include <stdio.h>
31f08c3bdfSopenharmony_ci#include <stdlib.h>
32f08c3bdfSopenharmony_ci#include <string.h>
33f08c3bdfSopenharmony_ci#include <unistd.h>
34f08c3bdfSopenharmony_ci#include <assert.h>
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci#include <sys/types.h>
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_ci#include "lib.h"
39f08c3bdfSopenharmony_ci#include "allocate.h"
40f08c3bdfSopenharmony_ci#include "token.h"
41f08c3bdfSopenharmony_ci#include "parse.h"
42f08c3bdfSopenharmony_ci#include "symbol.h"
43f08c3bdfSopenharmony_ci#include "expression.h"
44f08c3bdfSopenharmony_ci#include "evaluate.h"
45f08c3bdfSopenharmony_ci#include "scope.h"
46f08c3bdfSopenharmony_ci#include "linearize.h"
47f08c3bdfSopenharmony_ci#include "target.h"
48f08c3bdfSopenharmony_ci#include "machine.h"
49f08c3bdfSopenharmony_ci#include "bits.h"
50f08c3bdfSopenharmony_ci
51f08c3bdfSopenharmony_cistatic int prettify(const char **fnamep)
52f08c3bdfSopenharmony_ci{
53f08c3bdfSopenharmony_ci	const char *name = *fnamep;
54f08c3bdfSopenharmony_ci	int len = strlen(name);
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_ci	if (len > 2 && !memcmp(name, "./", 2)) {
57f08c3bdfSopenharmony_ci		name += 2;
58f08c3bdfSopenharmony_ci		len -= 2;
59f08c3bdfSopenharmony_ci	}
60f08c3bdfSopenharmony_ci
61f08c3bdfSopenharmony_ci	*fnamep = name;
62f08c3bdfSopenharmony_ci	return len;
63f08c3bdfSopenharmony_ci}
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_cistatic const char *show_include_chain(int stream, const char *base)
66f08c3bdfSopenharmony_ci{
67f08c3bdfSopenharmony_ci	static char buffer[200];
68f08c3bdfSopenharmony_ci	int len = 0;
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_ci	while ((stream = stream_prev(stream)) >= 0) {
71f08c3bdfSopenharmony_ci		const char *p = stream_name(stream);
72f08c3bdfSopenharmony_ci		int pretty_len;
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_ci		if (p == base)
75f08c3bdfSopenharmony_ci			break;
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_ci		pretty_len = prettify(&p);
78f08c3bdfSopenharmony_ci		if (pretty_len <= 0)
79f08c3bdfSopenharmony_ci			break;
80f08c3bdfSopenharmony_ci
81f08c3bdfSopenharmony_ci		/*
82f08c3bdfSopenharmony_ci		 * At worst, we'll need " (through %s, ...)" in addition to the
83f08c3bdfSopenharmony_ci		 * new filename
84f08c3bdfSopenharmony_ci		 */
85f08c3bdfSopenharmony_ci		if (pretty_len + len + 20 > sizeof(buffer)) {
86f08c3bdfSopenharmony_ci			if (!len)
87f08c3bdfSopenharmony_ci				return "";
88f08c3bdfSopenharmony_ci			memcpy(buffer+len, ", ...", 5);
89f08c3bdfSopenharmony_ci			len += 5;
90f08c3bdfSopenharmony_ci			break;
91f08c3bdfSopenharmony_ci		}
92f08c3bdfSopenharmony_ci
93f08c3bdfSopenharmony_ci		if (!len) {
94f08c3bdfSopenharmony_ci			memcpy(buffer, " (through ", 10);
95f08c3bdfSopenharmony_ci			len = 10;
96f08c3bdfSopenharmony_ci		} else {
97f08c3bdfSopenharmony_ci			buffer[len++] = ',';
98f08c3bdfSopenharmony_ci			buffer[len++] = ' ';
99f08c3bdfSopenharmony_ci		}
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ci		memcpy(buffer+len, p, pretty_len);
102f08c3bdfSopenharmony_ci		len += pretty_len;
103f08c3bdfSopenharmony_ci	}
104f08c3bdfSopenharmony_ci	if (!len)
105f08c3bdfSopenharmony_ci		return "";
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	buffer[len] = ')';
108f08c3bdfSopenharmony_ci	buffer[len+1] = 0;
109f08c3bdfSopenharmony_ci	return buffer;
110f08c3bdfSopenharmony_ci}
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_cistatic const char *show_stream_name(struct position pos)
113f08c3bdfSopenharmony_ci{
114f08c3bdfSopenharmony_ci	const char *name = stream_name(pos.stream);
115f08c3bdfSopenharmony_ci	static const char *last;
116f08c3bdfSopenharmony_ci
117f08c3bdfSopenharmony_ci	if (name == base_filename)
118f08c3bdfSopenharmony_ci		return name;
119f08c3bdfSopenharmony_ci	if (name == last)
120f08c3bdfSopenharmony_ci		return name;
121f08c3bdfSopenharmony_ci	last = name;
122f08c3bdfSopenharmony_ci
123f08c3bdfSopenharmony_ci	fprintf(stderr, "%s: note: in included file%s:\n",
124f08c3bdfSopenharmony_ci		base_filename,
125f08c3bdfSopenharmony_ci		show_include_chain(pos.stream, base_filename));
126f08c3bdfSopenharmony_ci	return name;
127f08c3bdfSopenharmony_ci}
128f08c3bdfSopenharmony_ci
129f08c3bdfSopenharmony_cistatic void do_warn(const char *type, struct position pos, const char * fmt, va_list args)
130f08c3bdfSopenharmony_ci{
131f08c3bdfSopenharmony_ci	static char buffer[512];
132f08c3bdfSopenharmony_ci
133f08c3bdfSopenharmony_ci	/* Shut up warnings if position is bad_token.pos */
134f08c3bdfSopenharmony_ci	if (pos.type == TOKEN_BAD)
135f08c3bdfSopenharmony_ci		return;
136f08c3bdfSopenharmony_ci
137f08c3bdfSopenharmony_ci	vsprintf(buffer, fmt, args);
138f08c3bdfSopenharmony_ci
139f08c3bdfSopenharmony_ci	fflush(stdout);
140f08c3bdfSopenharmony_ci	fprintf(stderr, "%s:%d:%d: %s%s%s\n",
141f08c3bdfSopenharmony_ci		show_stream_name(pos), pos.line, pos.pos,
142f08c3bdfSopenharmony_ci		diag_prefix, type, buffer);
143f08c3bdfSopenharmony_ci}
144f08c3bdfSopenharmony_ci
145f08c3bdfSopenharmony_cistatic int show_info = 1;
146f08c3bdfSopenharmony_ci
147f08c3bdfSopenharmony_civoid info(struct position pos, const char * fmt, ...)
148f08c3bdfSopenharmony_ci{
149f08c3bdfSopenharmony_ci	va_list args;
150f08c3bdfSopenharmony_ci
151f08c3bdfSopenharmony_ci	if (!show_info)
152f08c3bdfSopenharmony_ci		return;
153f08c3bdfSopenharmony_ci	va_start(args, fmt);
154f08c3bdfSopenharmony_ci	do_warn("", pos, fmt, args);
155f08c3bdfSopenharmony_ci	va_end(args);
156f08c3bdfSopenharmony_ci}
157f08c3bdfSopenharmony_ci
158f08c3bdfSopenharmony_cistatic void do_error(struct position pos, const char * fmt, va_list args)
159f08c3bdfSopenharmony_ci{
160f08c3bdfSopenharmony_ci	static int errors = 0;
161f08c3bdfSopenharmony_ci        die_if_error = 1;
162f08c3bdfSopenharmony_ci	show_info = 1;
163f08c3bdfSopenharmony_ci	/* Shut up warnings if position is bad_token.pos */
164f08c3bdfSopenharmony_ci	if (pos.type == TOKEN_BAD)
165f08c3bdfSopenharmony_ci		return;
166f08c3bdfSopenharmony_ci	/* Shut up warnings after an error */
167f08c3bdfSopenharmony_ci	has_error |= ERROR_CURR_PHASE;
168f08c3bdfSopenharmony_ci	if (errors > fmax_errors) {
169f08c3bdfSopenharmony_ci		static int once = 0;
170f08c3bdfSopenharmony_ci		show_info = 0;
171f08c3bdfSopenharmony_ci		if (once)
172f08c3bdfSopenharmony_ci			return;
173f08c3bdfSopenharmony_ci		fmt = "too many errors";
174f08c3bdfSopenharmony_ci		once = 1;
175f08c3bdfSopenharmony_ci	}
176f08c3bdfSopenharmony_ci
177f08c3bdfSopenharmony_ci	do_warn("error: ", pos, fmt, args);
178f08c3bdfSopenharmony_ci	errors++;
179f08c3bdfSopenharmony_ci}
180f08c3bdfSopenharmony_ci
181f08c3bdfSopenharmony_civoid warning(struct position pos, const char * fmt, ...)
182f08c3bdfSopenharmony_ci{
183f08c3bdfSopenharmony_ci	va_list args;
184f08c3bdfSopenharmony_ci
185f08c3bdfSopenharmony_ci	if (Wsparse_error) {
186f08c3bdfSopenharmony_ci		va_start(args, fmt);
187f08c3bdfSopenharmony_ci		do_error(pos, fmt, args);
188f08c3bdfSopenharmony_ci		va_end(args);
189f08c3bdfSopenharmony_ci		return;
190f08c3bdfSopenharmony_ci	}
191f08c3bdfSopenharmony_ci
192f08c3bdfSopenharmony_ci	if (!fmax_warnings || has_error) {
193f08c3bdfSopenharmony_ci		show_info = 0;
194f08c3bdfSopenharmony_ci		return;
195f08c3bdfSopenharmony_ci	}
196f08c3bdfSopenharmony_ci
197f08c3bdfSopenharmony_ci	if (!--fmax_warnings) {
198f08c3bdfSopenharmony_ci		show_info = 0;
199f08c3bdfSopenharmony_ci		fmt = "too many warnings";
200f08c3bdfSopenharmony_ci	}
201f08c3bdfSopenharmony_ci
202f08c3bdfSopenharmony_ci	va_start(args, fmt);
203f08c3bdfSopenharmony_ci	do_warn("warning: ", pos, fmt, args);
204f08c3bdfSopenharmony_ci	va_end(args);
205f08c3bdfSopenharmony_ci}
206f08c3bdfSopenharmony_ci
207f08c3bdfSopenharmony_civoid sparse_error(struct position pos, const char * fmt, ...)
208f08c3bdfSopenharmony_ci{
209f08c3bdfSopenharmony_ci	va_list args;
210f08c3bdfSopenharmony_ci	va_start(args, fmt);
211f08c3bdfSopenharmony_ci	do_error(pos, fmt, args);
212f08c3bdfSopenharmony_ci	va_end(args);
213f08c3bdfSopenharmony_ci}
214f08c3bdfSopenharmony_ci
215f08c3bdfSopenharmony_civoid expression_error(struct expression *expr, const char *fmt, ...)
216f08c3bdfSopenharmony_ci{
217f08c3bdfSopenharmony_ci	va_list args;
218f08c3bdfSopenharmony_ci	va_start(args, fmt);
219f08c3bdfSopenharmony_ci	do_error(expr->pos, fmt, args);
220f08c3bdfSopenharmony_ci	va_end(args);
221f08c3bdfSopenharmony_ci	expr->ctype = &bad_ctype;
222f08c3bdfSopenharmony_ci}
223f08c3bdfSopenharmony_ci
224f08c3bdfSopenharmony_ciNORETURN_ATTR
225f08c3bdfSopenharmony_civoid error_die(struct position pos, const char * fmt, ...)
226f08c3bdfSopenharmony_ci{
227f08c3bdfSopenharmony_ci	va_list args;
228f08c3bdfSopenharmony_ci	va_start(args, fmt);
229f08c3bdfSopenharmony_ci	do_warn("error: ", pos, fmt, args);
230f08c3bdfSopenharmony_ci	va_end(args);
231f08c3bdfSopenharmony_ci	exit(1);
232f08c3bdfSopenharmony_ci}
233f08c3bdfSopenharmony_ci
234f08c3bdfSopenharmony_ciNORETURN_ATTR
235f08c3bdfSopenharmony_civoid die(const char *fmt, ...)
236f08c3bdfSopenharmony_ci{
237f08c3bdfSopenharmony_ci	va_list args;
238f08c3bdfSopenharmony_ci	static char buffer[512];
239f08c3bdfSopenharmony_ci
240f08c3bdfSopenharmony_ci	va_start(args, fmt);
241f08c3bdfSopenharmony_ci	vsnprintf(buffer, sizeof(buffer), fmt, args);
242f08c3bdfSopenharmony_ci	va_end(args);
243f08c3bdfSopenharmony_ci
244f08c3bdfSopenharmony_ci	fprintf(stderr, "%s%s\n", diag_prefix, buffer);
245f08c3bdfSopenharmony_ci	exit(1);
246f08c3bdfSopenharmony_ci}
247f08c3bdfSopenharmony_ci
248f08c3bdfSopenharmony_ci////////////////////////////////////////////////////////////////////////////////
249f08c3bdfSopenharmony_ci
250f08c3bdfSopenharmony_cistatic struct token *pre_buffer_begin = NULL;
251f08c3bdfSopenharmony_cistatic struct token **pre_buffer_next = &pre_buffer_begin;
252f08c3bdfSopenharmony_ci
253f08c3bdfSopenharmony_civoid add_pre_buffer(const char *fmt, ...)
254f08c3bdfSopenharmony_ci{
255f08c3bdfSopenharmony_ci	va_list args;
256f08c3bdfSopenharmony_ci	unsigned int size;
257f08c3bdfSopenharmony_ci	struct token *begin, *end;
258f08c3bdfSopenharmony_ci	char buffer[4096];
259f08c3bdfSopenharmony_ci
260f08c3bdfSopenharmony_ci	va_start(args, fmt);
261f08c3bdfSopenharmony_ci	size = vsnprintf(buffer, sizeof(buffer), fmt, args);
262f08c3bdfSopenharmony_ci	va_end(args);
263f08c3bdfSopenharmony_ci	begin = tokenize_buffer(buffer, size, &end);
264f08c3bdfSopenharmony_ci	*pre_buffer_next = begin;
265f08c3bdfSopenharmony_ci	pre_buffer_next = &end->next;
266f08c3bdfSopenharmony_ci}
267f08c3bdfSopenharmony_ci
268f08c3bdfSopenharmony_cistatic void create_builtin_stream(void)
269f08c3bdfSopenharmony_ci{
270f08c3bdfSopenharmony_ci	// Temporary hack
271f08c3bdfSopenharmony_ci	add_pre_buffer("#define _Pragma(x)\n");
272f08c3bdfSopenharmony_ci
273f08c3bdfSopenharmony_ci	/* add the multiarch include directories, if any */
274f08c3bdfSopenharmony_ci	if (multiarch_dir && *multiarch_dir) {
275f08c3bdfSopenharmony_ci		add_pre_buffer("#add_system \"/usr/include/%s\"\n", multiarch_dir);
276f08c3bdfSopenharmony_ci		add_pre_buffer("#add_system \"/usr/local/include/%s\"\n", multiarch_dir);
277f08c3bdfSopenharmony_ci	}
278f08c3bdfSopenharmony_ci
279f08c3bdfSopenharmony_ci	/* We add compiler headers path here because we have to parse
280f08c3bdfSopenharmony_ci	 * the arguments to get it, falling back to default. */
281f08c3bdfSopenharmony_ci	add_pre_buffer("#add_system \"%s/include\"\n", gcc_base_dir);
282f08c3bdfSopenharmony_ci	add_pre_buffer("#add_system \"%s/include-fixed\"\n", gcc_base_dir);
283f08c3bdfSopenharmony_ci
284f08c3bdfSopenharmony_ci	add_pre_buffer("#define __builtin_stdarg_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
285f08c3bdfSopenharmony_ci	add_pre_buffer("#define __builtin_va_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
286f08c3bdfSopenharmony_ci	add_pre_buffer("#define __builtin_ms_va_start(a,b) ((a) = (__builtin_ms_va_list)(&(b)))\n");
287f08c3bdfSopenharmony_ci	add_pre_buffer("#define __builtin_va_arg(arg,type)  ({ type __va_arg_ret = *(type *)(arg); arg += sizeof(type); __va_arg_ret; })\n");
288f08c3bdfSopenharmony_ci	add_pre_buffer("#define __builtin_va_alist (*(void *)0)\n");
289f08c3bdfSopenharmony_ci	add_pre_buffer("#define __builtin_va_arg_incr(x) ((x) + 1)\n");
290f08c3bdfSopenharmony_ci	add_pre_buffer("#define __builtin_va_copy(dest, src) ({ dest = src; (void)0; })\n");
291f08c3bdfSopenharmony_ci	add_pre_buffer("#define __builtin_ms_va_copy(dest, src) ({ dest = src; (void)0; })\n");
292f08c3bdfSopenharmony_ci	add_pre_buffer("#define __builtin_va_end(arg)\n");
293f08c3bdfSopenharmony_ci	add_pre_buffer("#define __builtin_ms_va_end(arg)\n");
294f08c3bdfSopenharmony_ci	add_pre_buffer("#define __builtin_va_arg_pack()\n");
295f08c3bdfSopenharmony_ci}
296f08c3bdfSopenharmony_ci
297f08c3bdfSopenharmony_cistatic struct symbol_list *sparse_tokenstream(struct token *token)
298f08c3bdfSopenharmony_ci{
299f08c3bdfSopenharmony_ci	int builtin = token && !token->pos.stream;
300f08c3bdfSopenharmony_ci
301f08c3bdfSopenharmony_ci	// Preprocess the stream
302f08c3bdfSopenharmony_ci	token = preprocess(token);
303f08c3bdfSopenharmony_ci
304f08c3bdfSopenharmony_ci	if (dump_macro_defs || dump_macros_only) {
305f08c3bdfSopenharmony_ci		if (!builtin)
306f08c3bdfSopenharmony_ci			dump_macro_definitions();
307f08c3bdfSopenharmony_ci		if (dump_macros_only)
308f08c3bdfSopenharmony_ci			return NULL;
309f08c3bdfSopenharmony_ci	}
310f08c3bdfSopenharmony_ci
311f08c3bdfSopenharmony_ci	if (preprocess_only) {
312f08c3bdfSopenharmony_ci		while (!eof_token(token)) {
313f08c3bdfSopenharmony_ci			int prec = 1;
314f08c3bdfSopenharmony_ci			struct token *next = token->next;
315f08c3bdfSopenharmony_ci			const char *separator = "";
316f08c3bdfSopenharmony_ci			if (next->pos.whitespace)
317f08c3bdfSopenharmony_ci				separator = " ";
318f08c3bdfSopenharmony_ci			if (next->pos.newline) {
319f08c3bdfSopenharmony_ci				separator = "\n\t\t\t\t\t";
320f08c3bdfSopenharmony_ci				prec = next->pos.pos;
321f08c3bdfSopenharmony_ci				if (prec > 4)
322f08c3bdfSopenharmony_ci					prec = 4;
323f08c3bdfSopenharmony_ci			}
324f08c3bdfSopenharmony_ci			printf("%s%.*s", show_token(token), prec, separator);
325f08c3bdfSopenharmony_ci			token = next;
326f08c3bdfSopenharmony_ci		}
327f08c3bdfSopenharmony_ci		putchar('\n');
328f08c3bdfSopenharmony_ci
329f08c3bdfSopenharmony_ci		return NULL;
330f08c3bdfSopenharmony_ci	}
331f08c3bdfSopenharmony_ci
332f08c3bdfSopenharmony_ci	// Parse the resulting C code
333f08c3bdfSopenharmony_ci	while (!eof_token(token))
334f08c3bdfSopenharmony_ci		token = external_declaration(token, &translation_unit_used_list, NULL);
335f08c3bdfSopenharmony_ci	return translation_unit_used_list;
336f08c3bdfSopenharmony_ci}
337f08c3bdfSopenharmony_ci
338f08c3bdfSopenharmony_cistatic struct symbol_list *sparse_file(const char *filename)
339f08c3bdfSopenharmony_ci{
340f08c3bdfSopenharmony_ci	int fd;
341f08c3bdfSopenharmony_ci	struct token *token;
342f08c3bdfSopenharmony_ci
343f08c3bdfSopenharmony_ci	if (strcmp(filename, "-") == 0) {
344f08c3bdfSopenharmony_ci		fd = 0;
345f08c3bdfSopenharmony_ci	} else {
346f08c3bdfSopenharmony_ci		fd = open(filename, O_RDONLY);
347f08c3bdfSopenharmony_ci		if (fd < 0)
348f08c3bdfSopenharmony_ci			die("No such file: %s", filename);
349f08c3bdfSopenharmony_ci	}
350f08c3bdfSopenharmony_ci	base_filename = filename;
351f08c3bdfSopenharmony_ci
352f08c3bdfSopenharmony_ci	// Tokenize the input stream
353f08c3bdfSopenharmony_ci	token = tokenize(NULL, filename, fd, NULL, includepath);
354f08c3bdfSopenharmony_ci	close(fd);
355f08c3bdfSopenharmony_ci
356f08c3bdfSopenharmony_ci	return sparse_tokenstream(token);
357f08c3bdfSopenharmony_ci}
358f08c3bdfSopenharmony_ci
359f08c3bdfSopenharmony_ci/*
360f08c3bdfSopenharmony_ci * This handles the "-include" directive etc: we're in global
361f08c3bdfSopenharmony_ci * scope, and all types/macros etc will affect all the following
362f08c3bdfSopenharmony_ci * files.
363f08c3bdfSopenharmony_ci *
364f08c3bdfSopenharmony_ci * NOTE NOTE NOTE! "#undef" of anything in this stage will
365f08c3bdfSopenharmony_ci * affect all subsequent files too, i.e. we can have non-local
366f08c3bdfSopenharmony_ci * behaviour between files!
367f08c3bdfSopenharmony_ci */
368f08c3bdfSopenharmony_cistatic struct symbol_list *sparse_initial(void)
369f08c3bdfSopenharmony_ci{
370f08c3bdfSopenharmony_ci	int i;
371f08c3bdfSopenharmony_ci
372f08c3bdfSopenharmony_ci	// Prepend any "include" file to the stream.
373f08c3bdfSopenharmony_ci	// We're in global scope, it will affect all files!
374f08c3bdfSopenharmony_ci	for (i = 0; i < cmdline_include_nr; i++)
375f08c3bdfSopenharmony_ci		add_pre_buffer("#argv_include \"%s\"\n", cmdline_include[i]);
376f08c3bdfSopenharmony_ci
377f08c3bdfSopenharmony_ci	return sparse_tokenstream(pre_buffer_begin);
378f08c3bdfSopenharmony_ci}
379f08c3bdfSopenharmony_ci
380f08c3bdfSopenharmony_cistruct symbol_list *sparse_initialize(int argc, char **argv, struct string_list **filelist)
381f08c3bdfSopenharmony_ci{
382f08c3bdfSopenharmony_ci	char **args;
383f08c3bdfSopenharmony_ci	struct symbol_list *list;
384f08c3bdfSopenharmony_ci
385f08c3bdfSopenharmony_ci	base_filename = "command-line";
386f08c3bdfSopenharmony_ci
387f08c3bdfSopenharmony_ci	// Initialize symbol stream first, so that we can add defines etc
388f08c3bdfSopenharmony_ci	init_symbols();
389f08c3bdfSopenharmony_ci
390f08c3bdfSopenharmony_ci	// initialize the default target to the native 'machine'
391f08c3bdfSopenharmony_ci	target_config(MACH_NATIVE);
392f08c3bdfSopenharmony_ci
393f08c3bdfSopenharmony_ci	args = argv;
394f08c3bdfSopenharmony_ci	for (;;) {
395f08c3bdfSopenharmony_ci		char *arg = *++args;
396f08c3bdfSopenharmony_ci		if (!arg)
397f08c3bdfSopenharmony_ci			break;
398f08c3bdfSopenharmony_ci
399f08c3bdfSopenharmony_ci		if (arg[0] == '-' && arg[1]) {
400f08c3bdfSopenharmony_ci			args = handle_switch(arg+1, args);
401f08c3bdfSopenharmony_ci			continue;
402f08c3bdfSopenharmony_ci		}
403f08c3bdfSopenharmony_ci		add_ptr_list(filelist, arg);
404f08c3bdfSopenharmony_ci	}
405f08c3bdfSopenharmony_ci	handle_switch_finalize();
406f08c3bdfSopenharmony_ci
407f08c3bdfSopenharmony_ci	// Redirect stdout if needed
408f08c3bdfSopenharmony_ci	if (dump_macro_defs || preprocess_only)
409f08c3bdfSopenharmony_ci		do_output = 1;
410f08c3bdfSopenharmony_ci	if (do_output && outfile && strcmp(outfile, "-")) {
411f08c3bdfSopenharmony_ci		if (!freopen(outfile, "w", stdout))
412f08c3bdfSopenharmony_ci			die("error: cannot open %s: %s", outfile, strerror(errno));
413f08c3bdfSopenharmony_ci	}
414f08c3bdfSopenharmony_ci
415f08c3bdfSopenharmony_ci	if (fdump_ir == 0)
416f08c3bdfSopenharmony_ci		fdump_ir = PASS_FINAL;
417f08c3bdfSopenharmony_ci
418f08c3bdfSopenharmony_ci	list = NULL;
419f08c3bdfSopenharmony_ci	if (filelist) {
420f08c3bdfSopenharmony_ci		// Initialize type system
421f08c3bdfSopenharmony_ci		target_init();
422f08c3bdfSopenharmony_ci		init_ctype();
423f08c3bdfSopenharmony_ci
424f08c3bdfSopenharmony_ci		predefined_macros();
425f08c3bdfSopenharmony_ci		create_builtin_stream();
426f08c3bdfSopenharmony_ci		init_builtins(0);
427f08c3bdfSopenharmony_ci
428f08c3bdfSopenharmony_ci		list = sparse_initial();
429f08c3bdfSopenharmony_ci
430f08c3bdfSopenharmony_ci		/*
431f08c3bdfSopenharmony_ci		 * Protect the initial token allocations, since
432f08c3bdfSopenharmony_ci		 * they need to survive all the others
433f08c3bdfSopenharmony_ci		 */
434f08c3bdfSopenharmony_ci		protect_token_alloc();
435f08c3bdfSopenharmony_ci	}
436f08c3bdfSopenharmony_ci	/*
437f08c3bdfSopenharmony_ci	 * Evaluate the complete symbol list
438f08c3bdfSopenharmony_ci	 * Note: This is not needed for normal cases.
439f08c3bdfSopenharmony_ci	 *	 These symbols should only be predefined defines and
440f08c3bdfSopenharmony_ci	 *	 declaratons which will be evaluated later, when needed.
441f08c3bdfSopenharmony_ci	 *	 This is also the case when a file is directly included via
442f08c3bdfSopenharmony_ci	 *	 '-include <file>' on the command line *AND* the file only
443f08c3bdfSopenharmony_ci	 *	 contains defines, declarations and inline definitions.
444f08c3bdfSopenharmony_ci	 *	 However, in the rare cases where the given file should
445f08c3bdfSopenharmony_ci	 *	 contain some definitions, these will never be evaluated
446f08c3bdfSopenharmony_ci	 *	 and thus won't be able to be linearized correctly.
447f08c3bdfSopenharmony_ci	 *	 Hence the evaluate_symbol_list() here under.
448f08c3bdfSopenharmony_ci	 */
449f08c3bdfSopenharmony_ci	evaluate_symbol_list(list);
450f08c3bdfSopenharmony_ci	return list;
451f08c3bdfSopenharmony_ci}
452f08c3bdfSopenharmony_ci
453f08c3bdfSopenharmony_cistruct symbol_list * sparse_keep_tokens(char *filename)
454f08c3bdfSopenharmony_ci{
455f08c3bdfSopenharmony_ci	struct symbol_list *res;
456f08c3bdfSopenharmony_ci
457f08c3bdfSopenharmony_ci	/* Clear previous symbol list */
458f08c3bdfSopenharmony_ci	translation_unit_used_list = NULL;
459f08c3bdfSopenharmony_ci
460f08c3bdfSopenharmony_ci	new_file_scope();
461f08c3bdfSopenharmony_ci	res = sparse_file(filename);
462f08c3bdfSopenharmony_ci
463f08c3bdfSopenharmony_ci	/* And return it */
464f08c3bdfSopenharmony_ci	return res;
465f08c3bdfSopenharmony_ci}
466f08c3bdfSopenharmony_ci
467f08c3bdfSopenharmony_ci
468f08c3bdfSopenharmony_cistruct symbol_list * __sparse(char *filename)
469f08c3bdfSopenharmony_ci{
470f08c3bdfSopenharmony_ci	struct symbol_list *res;
471f08c3bdfSopenharmony_ci
472f08c3bdfSopenharmony_ci	res = sparse_keep_tokens(filename);
473f08c3bdfSopenharmony_ci
474f08c3bdfSopenharmony_ci	/* Drop the tokens for this file after parsing */
475f08c3bdfSopenharmony_ci	clear_token_alloc();
476f08c3bdfSopenharmony_ci
477f08c3bdfSopenharmony_ci	/* And return it */
478f08c3bdfSopenharmony_ci	return res;
479f08c3bdfSopenharmony_ci}
480f08c3bdfSopenharmony_ci
481f08c3bdfSopenharmony_cistruct symbol_list * sparse(char *filename)
482f08c3bdfSopenharmony_ci{
483f08c3bdfSopenharmony_ci	struct symbol_list *res = __sparse(filename);
484f08c3bdfSopenharmony_ci
485f08c3bdfSopenharmony_ci	if (has_error & ERROR_CURR_PHASE)
486f08c3bdfSopenharmony_ci		has_error = ERROR_PREV_PHASE;
487f08c3bdfSopenharmony_ci	/* Evaluate the complete symbol list */
488f08c3bdfSopenharmony_ci	evaluate_symbol_list(res);
489f08c3bdfSopenharmony_ci
490f08c3bdfSopenharmony_ci	return res;
491f08c3bdfSopenharmony_ci}
492