1/*
2 * Symbol scoping.
3 *
4 * This is pretty trivial.
5 *
6 * Copyright (C) 2003 Transmeta Corp.
7 *               2003-2004 Linus Torvalds
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27#include <stdlib.h>
28#include <string.h>
29#include <stdio.h>
30
31#include "lib.h"
32#include "allocate.h"
33#include "symbol.h"
34#include "scope.h"
35
36static struct scope builtin_scope = { .next = &builtin_scope };
37
38struct scope	*block_scope = &builtin_scope,		// regular automatic variables etc
39		*function_scope = &builtin_scope,	// labels, arguments etc
40		*file_scope = &builtin_scope,		// static
41		*global_scope = &builtin_scope;		// externally visible
42
43void bind_scope(struct symbol *sym, struct scope *scope)
44{
45	sym->scope = scope;
46	add_symbol(&scope->symbols, sym);
47}
48
49void rebind_scope(struct symbol *sym, struct scope *new)
50{
51	struct scope *old = sym->scope;
52
53	if (old == new)
54		return;
55
56	if (old)
57		delete_ptr_list_entry((struct ptr_list**) &old->symbols, sym, 1);
58
59	bind_scope(sym, new);
60}
61
62static void start_scope(struct scope **s, struct position pos)
63{
64	struct scope *scope = __alloc_scope(0);
65	memset(scope, 0, sizeof(*scope));
66	scope->token = __alloc_token(0);
67	scope->token->pos = pos;
68	scope->next = *s;
69	*s = scope;
70}
71
72void start_file_scope(void)
73{
74	struct scope *scope = __alloc_scope(0);
75
76	memset(scope, 0, sizeof(*scope));
77	scope->next = &builtin_scope;
78	file_scope = scope;
79
80	/* top-level stuff defaults to file scope, "extern" etc will choose global scope */
81	function_scope = scope;
82	block_scope = scope;
83}
84
85void start_symbol_scope(struct position pos)
86{
87	start_scope(&block_scope, pos);
88}
89
90void start_function_scope(struct position pos)
91{
92	start_scope(&function_scope, pos);
93	start_scope(&block_scope, pos);
94}
95
96static void remove_symbol_scope(struct symbol *sym)
97{
98	struct symbol **ptr = &sym->ident->symbols;
99
100	while (*ptr != sym)
101		ptr = &(*ptr)->next_id;
102	*ptr = sym->next_id;
103}
104
105static void end_scope(struct scope **s)
106{
107	struct scope *scope = *s;
108	struct symbol_list *symbols = scope->symbols;
109	struct symbol *sym;
110
111	*s = scope->next;
112	scope->symbols = NULL;
113	FOR_EACH_PTR(symbols, sym) {
114		remove_symbol_scope(sym);
115	} END_FOR_EACH_PTR(sym);
116}
117
118void end_file_scope(void)
119{
120	end_scope(&file_scope);
121}
122
123void new_file_scope(void)
124{
125	if (file_scope != &builtin_scope)
126		end_file_scope();
127	start_file_scope();
128}
129
130void end_symbol_scope(void)
131{
132	end_scope(&block_scope);
133}
134
135void end_function_scope(void)
136{
137	end_scope(&block_scope);
138	end_scope(&function_scope);
139}
140
141int is_outer_scope(struct scope *scope)
142{
143	if (scope == block_scope)
144		return 0;
145	if (scope == &builtin_scope && block_scope->next == &builtin_scope)
146		return 0;
147	return 1;
148}
149
150