| /* |
| * Symbol scoping. |
| * |
| * This is pretty trivial. |
| * |
| * Copyright (C) 2003 Transmeta Corp. |
| * 2003-2004 Linus Torvalds |
| * |
| * Licensed under the Open Software License version 1.1 |
| */ |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdio.h> |
| |
| #include "lib.h" |
| #include "allocate.h" |
| #include "symbol.h" |
| #include "scope.h" |
| |
| static struct scope builtin_scope = { .next = &builtin_scope }; |
| |
| struct scope *block_scope = &builtin_scope, // regular automatic variables etc |
| *function_scope = &builtin_scope, // labels, arguments etc |
| *file_scope = &builtin_scope, // static |
| *global_scope = &builtin_scope; // externally visible |
| |
| void bind_scope(struct symbol *sym, struct scope *scope) |
| { |
| sym->scope = scope; |
| add_symbol(&scope->symbols, sym); |
| } |
| |
| static void start_scope(struct scope **s) |
| { |
| struct scope *scope = __alloc_scope(0); |
| memset(scope, 0, sizeof(*scope)); |
| scope->next = *s; |
| *s = scope; |
| } |
| |
| void start_file_scope(void) |
| { |
| struct scope *scope = __alloc_scope(0); |
| |
| memset(scope, 0, sizeof(*scope)); |
| scope->next = &builtin_scope; |
| file_scope = scope; |
| |
| /* top-level stuff defaults to file scope, "extern" etc will choose global scope */ |
| function_scope = scope; |
| block_scope = scope; |
| } |
| |
| void start_symbol_scope(void) |
| { |
| start_scope(&block_scope); |
| } |
| |
| void start_function_scope(void) |
| { |
| start_scope(&function_scope); |
| start_scope(&block_scope); |
| } |
| |
| static void remove_symbol_scope(struct symbol *sym) |
| { |
| struct symbol **ptr = &sym->ident->symbols; |
| |
| while (*ptr != sym) |
| ptr = &(*ptr)->next_id; |
| *ptr = sym->next_id; |
| } |
| |
| static void end_scope(struct scope **s) |
| { |
| struct scope *scope = *s; |
| struct symbol_list *symbols = scope->symbols; |
| struct symbol *sym; |
| |
| *s = scope->next; |
| scope->symbols = NULL; |
| FOR_EACH_PTR(symbols, sym) { |
| remove_symbol_scope(sym); |
| } END_FOR_EACH_PTR(sym); |
| } |
| |
| void end_file_scope(void) |
| { |
| end_scope(&file_scope); |
| } |
| |
| void new_file_scope(void) |
| { |
| if (file_scope != &builtin_scope) |
| end_file_scope(); |
| start_file_scope(); |
| } |
| |
| void end_symbol_scope(void) |
| { |
| end_scope(&block_scope); |
| } |
| |
| void end_function_scope(void) |
| { |
| end_scope(&block_scope); |
| end_scope(&function_scope); |
| } |
| |
| int is_outer_scope(struct scope *scope) |
| { |
| if (scope == block_scope) |
| return 0; |
| if (scope == &builtin_scope && block_scope->next == &builtin_scope) |
| return 0; |
| return 1; |
| } |
| |