Branch data Line data Source code
1 : : // $Id: Scope.cc 6219 2008-10-01 05:39:07Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include "ID.h"
8 : : #include "Val.h"
9 : : #include "Scope.h"
10 : :
11 : 6 : static scope_list scopes;
12 : : static Scope* top_scope;
13 : :
14 : : extern const char* GLOBAL_MODULE_NAME = "GLOBAL";
15 : :
16 : :
17 : : // Returns it without trailing "::".
18 : 34297 : string extract_module_name(const char* name)
19 : : {
20 : 34297 : string module_name = name;
21 : 34297 : string::size_type pos = module_name.rfind("::");
22 : :
23 [ + + ]: 34297 : if ( pos == string::npos )
24 : 15271 : return string(GLOBAL_MODULE_NAME);
25 : :
26 : 19026 : module_name.erase(pos);
27 : :
28 : 34297 : return module_name;
29 : : }
30 : :
31 : 26310 : string normalized_module_name(const char* module_name)
32 : : {
33 : : int mod_len;
34 [ + - ][ - + ]: 26310 : if ( (mod_len = strlen(module_name)) >= 2 &&
[ - + ]
35 : : ! strcmp(module_name + mod_len - 2, "::") )
36 : 0 : mod_len -= 2;
37 : :
38 : 26310 : return string(module_name, mod_len);
39 : : }
40 : :
41 : 56206 : string make_full_var_name(const char* module_name, const char* var_name)
42 : : {
43 [ + + ][ + + ]: 56206 : if ( ! module_name || streq(module_name, GLOBAL_MODULE_NAME) ||
[ + + ][ + + ]
44 : : strstr(var_name, "::") )
45 : 34367 : return string(var_name);
46 : :
47 : 21839 : string full_name = normalized_module_name(module_name);
48 : 21839 : full_name += "::";
49 : 21839 : full_name += var_name;
50 : :
51 : 56206 : return full_name;
52 : : }
53 : :
54 : 1128 : Scope::Scope(ID* id)
55 : : {
56 : 1128 : scope_id = id;
57 : 1128 : return_type = 0;
58 : :
59 : 1128 : local = new PDict(ID)(ORDERED);
60 : 1128 : inits = new id_list;
61 : :
62 [ + + # # ]: 1128 : if ( id )
63 : : {
64 : 1125 : BroType* id_type = id->Type();
65 : :
66 [ + - # # ]: 1125 : if ( id_type->Tag() == TYPE_ERROR )
67 : 1128 : return;
68 [ - + ][ # # ]: 1125 : else if ( id_type->Tag() != TYPE_FUNC )
69 : 0 : internal_error("bad scope id");
70 : :
71 : 1125 : Ref(id);
72 : :
73 : 1125 : FuncType* ft = id->Type()->AsFuncType();
74 : 1125 : return_type = ft->YieldType();
75 [ + + # # ]: 1125 : if ( return_type )
76 : 1128 : Ref(return_type);
77 : : }
78 : 0 : }
79 : :
80 : 0 : Scope::~Scope()
81 : : {
82 [ # # ][ # # ]: 0 : for ( int i = 0; i < local->Length(); ++i )
[ # # ]
83 : 0 : Unref(local->NthEntry(i));
84 : :
85 : 0 : Unref(scope_id);
86 : 0 : Unref(return_type);
87 [ # # # # ]: 0 : delete local;
[ # # ]
88 [ # # ][ # # ]: 0 : delete inits;
[ # # ]
89 [ # # ][ # # ]: 0 : }
[ # # ]
90 : :
91 : 20 : ID* Scope::GenerateTemporary(const char* name)
92 : : {
93 : 20 : return new ID(copy_string(name), SCOPE_FUNCTION, false);
94 : : }
95 : :
96 : 1125 : id_list* Scope::GetInits()
97 : : {
98 : 1125 : id_list* ids = inits;
99 : 1125 : inits = 0;
100 : 1125 : return ids;
101 : : }
102 : :
103 : 0 : void Scope::Describe(ODesc* d) const
104 : : {
105 [ # # ]: 0 : if ( d->IsReadable() )
106 : 0 : d->AddSP("scope");
107 : :
108 : : else
109 : : {
110 : 0 : d->Add(scope_id != 0);
111 : 0 : d->SP();
112 : 0 : d->Add(return_type != 0);
113 : 0 : d->SP();
114 : 0 : d->Add(local->Length());
115 : 0 : d->SP();
116 : : }
117 : :
118 [ # # ]: 0 : if ( scope_id )
119 : : {
120 : 0 : scope_id->Describe(d);
121 : 0 : d->NL();
122 : : }
123 : :
124 [ # # ]: 0 : if ( return_type )
125 : : {
126 : 0 : return_type->Describe(d);
127 : 0 : d->NL();
128 : : }
129 : :
130 [ # # ]: 0 : for ( int i = 0; i < local->Length(); ++i )
131 : : {
132 : 0 : ID* id = local->NthEntry(i);
133 : 0 : id->Describe(d);
134 : 0 : d->NL();
135 : : }
136 : 0 : }
137 : :
138 : 0 : TraversalCode Scope::Traverse(TraversalCallback* cb) const
139 : : {
140 : 0 : PDict(ID)* ids = GetIDs();
141 : 0 : IterCookie* iter = ids->InitForIteration();
142 : :
143 : : HashKey* key;
144 : : ID* id;
145 [ # # ]: 0 : while ( (id = ids->NextEntry(key, iter)) )
146 : : {
147 : 0 : TraversalCode tc = id->Traverse(cb);
148 [ # # # # ]: 0 : HANDLE_TC_STMT_PRE(tc);
149 : : }
150 : :
151 : 0 : return TC_CONTINUE;
152 : : }
153 : :
154 : :
155 : 33386 : ID* lookup_ID(const char* name, const char* curr_module, bool no_global)
156 : : {
157 : 33386 : string fullname = make_full_var_name(curr_module, name);
158 : 33386 : string ID_module = extract_module_name(fullname.c_str());
159 : : bool need_export = ID_module != GLOBAL_MODULE_NAME &&
160 [ + + + + ]: 33386 : ID_module != curr_module;
161 : :
162 [ + + ]: 55750 : for ( int i = scopes.length() - 1; i >= 0; --i )
163 : : {
164 : 43939 : ID* id = scopes[i]->Lookup(fullname.c_str());
165 [ + + ]: 43939 : if ( id )
166 : : {
167 [ + + ][ - + ]: 21575 : if ( need_export && ! id->IsExport() && ! in_debug )
[ # # ][ - + ]
168 : : error("identifier is not exported:",
169 : 0 : fullname.c_str());
170 : :
171 : 21575 : Ref(id);
172 : 21575 : return id;
173 : : }
174 : : }
175 : :
176 [ + - ]: 11811 : if ( ! no_global )
177 : : {
178 : 11811 : string globalname = make_full_var_name(GLOBAL_MODULE_NAME, name);
179 : 11811 : ID* id = global_scope()->Lookup(globalname.c_str());
180 [ + + ]: 11811 : if ( id )
181 : : {
182 : 3072 : Ref(id);
183 : 11811 : return id;
184 [ + + ]: 11811 : }
185 : : }
186 : :
187 : 33386 : return 0;
188 : : }
189 : :
190 : : ID* install_ID(const char* name, const char* module_name,
191 : 8914 : bool is_global, bool is_export)
192 : : {
193 [ - + ][ # # ]: 8914 : if ( scopes.length() == 0 && ! is_global )
[ - + ]
194 : 0 : internal_error("local identifier in global scope");
195 : :
196 : : IDScope scope;
197 [ + + ][ + + ]: 8914 : if ( is_export || ! module_name ||
[ + + ][ + + ]
[ + + ][ # # ]
[ + + ]
198 : : (is_global &&
199 : : normalized_module_name(module_name) == GLOBAL_MODULE_NAME) )
200 : 4729 : scope = SCOPE_GLOBAL;
201 [ + + ]: 4185 : else if ( is_global )
202 : 494 : scope = SCOPE_MODULE;
203 : : else
204 : 3691 : scope = SCOPE_FUNCTION;
205 : :
206 : 8914 : string full_name_str = make_full_var_name(module_name, name);
207 : 8914 : char* full_name = copy_string(full_name_str.c_str());
208 : :
209 : 8914 : ID* id = new ID(full_name, scope, is_export);
210 [ + + ]: 8914 : if ( SCOPE_FUNCTION != scope )
211 : 5223 : global_scope()->Insert(full_name, id);
212 : : else
213 : : {
214 : 3691 : id->SetOffset(top_scope->Length());
215 : 3691 : top_scope->Insert(full_name, id);
216 : : }
217 : :
218 : 8914 : return id;
219 : : }
220 : :
221 : 0 : void push_existing_scope(Scope* scope)
222 : : {
223 : 0 : scopes.append(scope);
224 : 0 : }
225 : :
226 : 1128 : void push_scope(ID* id)
227 : : {
228 : 1128 : top_scope = new Scope(id);
229 : 1128 : scopes.append(top_scope);
230 : 1128 : }
231 : :
232 : 1125 : Scope* pop_scope()
233 : : {
234 : 1125 : int n = scopes.length() - 1;
235 [ - + ]: 1125 : if ( n < 0 )
236 : 0 : internal_error("scope underflow");
237 : 1125 : scopes.remove_nth(n);
238 : :
239 : 1125 : Scope* old_top = top_scope;
240 : : // Don't delete the scope; keep it around for later name resolution
241 : : // in the debugger.
242 : : // ### SERIOUS MEMORY LEAK!?
243 : : // delete top_scope;
244 : :
245 [ + - ]: 1125 : top_scope = n == 0 ? 0 : scopes[n-1];
246 : :
247 : 1125 : return old_top;
248 : : }
249 : :
250 : 3190 : Scope* current_scope()
251 : : {
252 : 3190 : return top_scope;
253 : : }
254 : :
255 : 17053 : Scope* global_scope()
256 : : {
257 : 17053 : return scopes[0];
258 [ + - ][ + - ]: 6 : }
|