Branch data Line data Source code
1 : : // $Id: Var.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 "Var.h"
8 : : #include "Func.h"
9 : : #include "Stmt.h"
10 : : #include "Scope.h"
11 : : #include "Serializer.h"
12 : : #include "RemoteSerializer.h"
13 : : #include "EventRegistry.h"
14 : :
15 : 1628 : static Val* init_val(Expr* init, const BroType* t, Val* aggr)
16 : : {
17 : 1628 : return init->InitVal(t, aggr);
18 : : }
19 : :
20 : : static void make_var(ID* id, BroType* t, init_class c, Expr* init,
21 : 5262 : attr_list* attr, decl_type dt, int do_init)
22 : : {
23 [ + + ]: 5262 : if ( id->Type() )
24 : : {
25 [ + + ][ + - ]: 186 : if ( id->IsRedefinable() || (! init && attr) )
[ + - ][ + - ]
26 : : {
27 [ + + ]: 186 : BroObj* redef_obj = init ? (BroObj*) init : (BroObj*) t;
28 [ - + ]: 186 : if ( dt != VAR_REDEF )
29 : 186 : id->Warn("redefinition requires \"redef\"", redef_obj, 1);
30 : : }
31 : :
32 [ # # ][ # # ]: 0 : else if ( dt != VAR_REDEF || init || ! attr )
[ # # ]
33 : : {
34 : 0 : id->Error("already defined", init);
35 : 0 : return;
36 : : }
37 : : }
38 : :
39 [ + + ]: 5262 : if ( dt == VAR_REDEF )
40 : : {
41 [ - + ]: 186 : if ( ! id->Type() )
42 : : {
43 : 0 : id->Error("\"redef\" used but not previously defined");
44 : 0 : return;
45 : : }
46 : :
47 [ + + ]: 186 : if ( ! t )
48 : 184 : t = id->Type();
49 : : }
50 : :
51 [ + + ][ + - ]: 5262 : if ( id->Type() && id->Type()->Tag() != TYPE_ERROR )
[ + + ]
52 : : {
53 [ - + ][ # # ]: 186 : if ( dt != VAR_REDEF &&
[ # # ][ # # ]
[ # # ][ - + ]
54 : : (! init || ! do_init || (! t && ! (t = init_type(init)))) )
55 : : {
56 : 0 : id->Error("already defined", init);
57 : 0 : return;
58 : : }
59 : :
60 : : // Allow redeclaration in order to initialize.
61 [ - + ]: 186 : if ( ! same_type(t, id->Type()) )
62 : : {
63 : 0 : id->Error("redefinition changes type", init);
64 : 0 : return;
65 : : }
66 : : }
67 : :
68 [ + + ][ - + ]: 5262 : if ( init && optimize )
69 : 0 : init = init->Simplify(SIMPLIFY_GENERAL);
70 : :
71 [ + + ][ + + ]: 5262 : if ( t && t->IsSet() )
[ + + ]
72 : : { // Check for set with explicit elements.
73 : 251 : SetType* st = t->AsTableType()->AsSetType();
74 : 251 : ListExpr* elements = st->SetElements();
75 : :
76 [ - + ]: 251 : if ( elements )
77 : : {
78 [ # # ]: 0 : if ( init )
79 : : {
80 : 0 : id->Error("double initialization", init);
81 : 0 : return;
82 : : }
83 : :
84 : 0 : Ref(elements);
85 : 0 : init = elements;
86 : : }
87 : : }
88 : :
89 [ + + ]: 5262 : if ( ! t )
90 : : { // Take type from initialization.
91 [ - + ]: 2380 : if ( ! init )
92 : : {
93 : 0 : id->Error("no type given");
94 : 0 : return;
95 : : }
96 : :
97 : 2380 : t = init_type(init);
98 [ - + ]: 2380 : if ( ! t )
99 : : {
100 : 0 : id->SetType(error_type());
101 : 2380 : return;
102 : : }
103 : : }
104 : : else
105 : 2882 : Ref(t);
106 : :
107 : 5262 : id->SetType(t);
108 : :
109 [ + + ]: 5262 : if ( attr )
110 : 1280 : id->AddAttrs(new Attributes(attr, t));
111 : :
112 [ + + ][ + + ]: 5262 : if ( id->FindAttr(ATTR_PERSISTENT) || id->FindAttr(ATTR_SYNCHRONIZED) )
[ + + ]
113 : : {
114 [ - + ]: 18 : if ( dt == VAR_CONST )
115 : : {
116 : 0 : id->Error("&persistant/synchronized with constant");
117 : 0 : return;
118 : : }
119 : :
120 [ - + ]: 18 : if ( ! id->IsGlobal() )
121 : : {
122 : 0 : id->Error("&persistant/synchronized with non-global");
123 : 0 : return;
124 : : }
125 : : }
126 : :
127 [ + + ]: 5262 : if ( do_init )
128 : : {
129 [ + + ][ + + ]: 3893 : if ( (c == INIT_EXTRA && id->FindAttr(ATTR_ADD_FUNC)) ||
[ - + ][ # # ]
[ + + ]
130 : : (c == INIT_REMOVE && id->FindAttr(ATTR_DEL_FUNC)) )
131 : : // Just apply the function.
132 : 2 : id->SetVal(init, c);
133 : :
134 [ + + ][ + + ]: 3891 : else if ( dt != VAR_REDEF || init || ! attr )
[ - + ]
135 : : {
136 : : Val* aggr;
137 [ + + ]: 3878 : if ( t->Tag() == TYPE_RECORD )
138 : 8 : aggr = new RecordVal(t->AsRecordType());
139 : :
140 [ + + ]: 3870 : else if ( t->Tag() == TYPE_TABLE )
141 : 690 : aggr = new TableVal(t->AsTableType(), id->Attrs());
142 : :
143 [ + + ]: 3180 : else if ( t->Tag() == TYPE_VECTOR )
144 : 14 : aggr = new VectorVal(t->AsVectorType());
145 : :
146 : : else
147 : 3166 : aggr = 0;
148 : :
149 : 3878 : Val* v = 0;
150 [ + + ]: 3878 : if ( init )
151 : : {
152 : 1628 : v = init_val(init, t, aggr);
153 [ - + ]: 1628 : if ( ! v )
154 : 0 : return;
155 : : }
156 : :
157 [ + + ]: 3878 : if ( aggr )
158 : 712 : id->SetVal(aggr, c);
159 [ + + ]: 3166 : else if ( v )
160 : 1264 : id->SetVal(v, c);
161 : : }
162 : : }
163 : :
164 [ + + ]: 5262 : if ( dt == VAR_CONST )
165 : : {
166 [ + + ][ - + ]: 1336 : if ( ! init && ! id->IsRedefinable() )
[ - + ]
167 : 0 : id->Error("const variable must be initialized");
168 : :
169 : 1336 : id->SetConst();
170 : : }
171 : :
172 : 5262 : id->UpdateValAttrs();
173 : : }
174 : :
175 : :
176 : : void add_global(ID* id, BroType* t, init_class c, Expr* init,
177 : 3893 : attr_list* attr, decl_type dt)
178 : : {
179 : 3893 : make_var(id, t, c, init, attr, dt, 1);
180 : 3893 : }
181 : :
182 : : Stmt* add_local(ID* id, BroType* t, init_class c, Expr* init,
183 : 272 : attr_list* attr, decl_type dt)
184 : : {
185 : 272 : make_var(id, t, c, init, attr, dt, 0);
186 : :
187 [ + + ]: 272 : if ( init )
188 : : {
189 [ - + ]: 21 : if ( c != INIT_FULL )
190 : 0 : id->Error("can't use += / -= for initializations of local variables");
191 : :
192 : 21 : Ref(id);
193 : :
194 : : Stmt* stmt =
195 : 21 : new ExprStmt(new AssignExpr(new NameExpr(id), init, 0));
196 : 21 : stmt->SetLocationInfo(init->GetLocationInfo());
197 : :
198 : 21 : return stmt;
199 : : }
200 : :
201 : : else
202 : : {
203 [ + + ][ + + ]: 251 : if ( t->Tag() == TYPE_RECORD || t->Tag() == TYPE_TABLE ||
[ + + ][ + + ]
204 : : t->Tag() == TYPE_VECTOR )
205 : 103 : current_scope()->AddInit(id);
206 : :
207 : 272 : return new NullStmt;
208 : : }
209 : : }
210 : :
211 : 1097 : extern Expr* add_and_assign_local(ID* id, Expr* init, Val* val)
212 : : {
213 : 1097 : make_var(id, 0, INIT_FULL, init, 0, VAR_REGULAR, 0);
214 : 1097 : Ref(id);
215 : 1097 : return new AssignExpr(new NameExpr(id), init, 0, val);
216 : : }
217 : :
218 : 389 : void add_type(ID* id, BroType* t, attr_list* attr, int /* is_event */)
219 : : {
220 : 389 : id->SetType(t);
221 : 389 : id->MakeType();
222 : :
223 [ - + ]: 389 : if ( attr )
224 : 0 : id->SetAttrs(new Attributes(attr, t));
225 : 389 : }
226 : :
227 : : void begin_func(ID* id, const char* module_name, function_flavor flavor,
228 : 1125 : int is_redef, FuncType* t)
229 : : {
230 [ + + ]: 1125 : if ( flavor == FUNC_FLAVOR_EVENT )
231 : : {
232 : 575 : const BroType* yt = t->YieldType();
233 : :
234 [ + - - + ]: 575 : if ( yt && yt->Tag() != TYPE_VOID )
[ - + ]
235 : 0 : id->Error("event cannot yield a value", t);
236 : :
237 : 575 : t->ClearYieldType();
238 : : }
239 : :
240 [ + + ]: 1125 : if ( id->Type() )
241 : : {
242 [ - + ]: 596 : if ( ! same_type(id->Type(), t) )
243 : 596 : id->Type()->Error("incompatible types", t);
244 : : }
245 : :
246 [ - + ]: 529 : else if ( is_redef )
247 : 0 : id->Error("redef of not-previously-declared value");
248 : :
249 [ + + ]: 1125 : if ( id->HasVal() )
250 : : {
251 : 177 : int id_is_event = id->ID_Val()->AsFunc()->IsEvent();
252 : :
253 [ - + ]: 177 : if ( id_is_event != (flavor == FUNC_FLAVOR_EVENT) )
254 : 0 : id->Error("inconsistency between event and function", t);
255 [ + + ]: 177 : if ( id_is_event )
256 : : {
257 [ - + ]: 176 : if ( is_redef )
258 : : // Clear out value so it will be replaced.
259 : 176 : id->SetVal(0);
260 : : }
261 : : else
262 : : {
263 [ - + ]: 1 : if ( ! id->IsRedefinable() )
264 : 177 : id->Error("already defined");
265 : : }
266 : : }
267 : : else
268 : 948 : id->SetType(t);
269 : :
270 : 1125 : push_scope(id);
271 : :
272 : 1125 : RecordType* args = t->Args();
273 : 1125 : int num_args = args->NumFields();
274 [ + + ]: 3447 : for ( int i = 0; i < num_args; ++i )
275 : : {
276 : 2322 : TypeDecl* arg_i = args->FieldDecl(i);
277 : 2322 : ID* arg_id = lookup_ID(arg_i->id, module_name);
278 : :
279 [ + + - + ]: 2322 : if ( arg_id && ! arg_id->IsGlobal() )
[ - + ]
280 : 0 : arg_id->Error("argument name used twice");
281 : :
282 : : arg_id = install_ID(copy_string(arg_i->id), module_name,
283 : 2322 : false, false);
284 : 2322 : arg_id->SetType(arg_i->type->Ref());
285 : : }
286 : 1125 : }
287 : :
288 : 1125 : void end_func(Stmt* body, attr_list* attrs)
289 : : {
290 : 1125 : int frame_size = current_scope()->Length();
291 : 1125 : id_list* inits = current_scope()->GetInits();
292 : :
293 : 1125 : Scope* scope = pop_scope();
294 : 1125 : ID* id = scope->ScopeID();
295 : :
296 : 1125 : int priority = 0;
297 [ + + ]: 1125 : if ( attrs )
298 : : {
299 [ + + ]: 28 : loop_over_list(*attrs, i)
300 : : {
301 : 14 : Attr* a = (*attrs)[i];
302 [ - + ]: 14 : if ( a->Tag() != ATTR_PRIORITY )
303 : : {
304 : 0 : a->Error("illegal attribute for function body");
305 : 0 : continue;
306 : : }
307 : :
308 : 14 : Val* v = a->AttrExpr()->Eval(0);
309 [ - + ]: 14 : if ( ! v )
310 : : {
311 : 0 : a->Error("cannot evaluate attribute expression");
312 : 0 : continue;
313 : : }
314 : :
315 [ + + ][ - + ]: 14 : if ( ! IsIntegral(v->Type()->Tag()) )
[ # # ][ - + ]
316 : : {
317 : 0 : a->Error("expression is not of integral type");
318 : 0 : continue;
319 : : }
320 : :
321 : 14 : priority = v->InternalInt();
322 : : }
323 : : }
324 : :
325 [ + + ]: 1125 : if ( id->HasVal() )
326 : 177 : id->ID_Val()->AsFunc()->AddBody(body, inits, frame_size, priority);
327 : : else
328 : : {
329 : 948 : Func* f = new BroFunc(id, body, inits, frame_size);
330 : 948 : id->SetVal(new Val(f));
331 : 948 : id->SetConst();
332 : : }
333 : :
334 : 1125 : id->ID_Val()->AsFunc()->SetScope(scope);
335 : 1125 : }
336 : :
337 : 55 : Val* internal_val(const char* name)
338 : : {
339 : 55 : ID* id = lookup_ID(name, GLOBAL_MODULE_NAME);
340 [ - + ]: 55 : if ( ! id )
341 : 0 : internal_error("internal variable %s missing", name);
342 : :
343 : 55 : return id->ID_Val();
344 : : }
345 : :
346 : 123 : Val* opt_internal_val(const char* name)
347 : : {
348 : 123 : ID* id = lookup_ID(name, GLOBAL_MODULE_NAME);
349 [ + + ]: 123 : return id ? id->ID_Val() : 0;
350 : : }
351 : :
352 : 44 : double opt_internal_double(const char* name)
353 : : {
354 : 44 : Val* v = opt_internal_val(name);
355 [ + + ]: 44 : return v ? v->InternalDouble() : 0.0;
356 : : }
357 : :
358 : 67 : bro_int_t opt_internal_int(const char* name)
359 : : {
360 : 67 : Val* v = opt_internal_val(name);
361 [ + + ]: 67 : return v ? v->InternalInt() : 0;
362 : : }
363 : :
364 : 0 : bro_uint_t opt_internal_unsigned(const char* name)
365 : : {
366 : 0 : Val* v = opt_internal_val(name);
367 [ # # ]: 0 : return v ? v->InternalUnsigned() : 0;
368 : : }
369 : :
370 : 7 : StringVal* opt_internal_string(const char* name)
371 : : {
372 : 7 : Val* v = opt_internal_val(name);
373 [ + + ]: 7 : return v ? v->AsStringVal() : 0;
374 : : }
375 : :
376 : 4 : TableVal* opt_internal_table(const char* name)
377 : : {
378 : 4 : Val* v = opt_internal_val(name);
379 [ + + ]: 4 : return v ? v->AsTableVal() : 0;
380 : : }
381 : :
382 : 7 : ListVal* internal_list_val(const char* name)
383 : : {
384 : 7 : ID* id = lookup_ID(name, GLOBAL_MODULE_NAME);
385 [ - + ]: 7 : if ( ! id )
386 : 0 : return 0;
387 : :
388 : 7 : Val* v = id->ID_Val();
389 [ + - ]: 7 : if ( v )
390 : : {
391 [ - + ]: 7 : if ( v->Type()->Tag() == TYPE_LIST )
392 : 0 : return (ListVal*) v;
393 : :
394 [ + - ]: 7 : else if ( v->Type()->IsSet() )
395 : : {
396 : 7 : TableVal* tv = v->AsTableVal();
397 : 7 : ListVal* lv = tv->ConvertToPureList();
398 : 7 : return lv;
399 : : }
400 : :
401 : : else
402 : 0 : internal_error("internal variable %s is not a list", name);
403 : : }
404 : :
405 : 7 : return 0;
406 : : }
407 : :
408 : 452 : BroType* internal_type(const char* name)
409 : : {
410 : 452 : ID* id = lookup_ID(name, GLOBAL_MODULE_NAME);
411 [ - + ]: 452 : if ( ! id )
412 : 0 : internal_error("internal type %s missing", name);
413 : :
414 : 452 : return id->Type();
415 : : }
416 : :
417 : 5 : Func* internal_func(const char* name)
418 : : {
419 : 5 : Val* v = internal_val(name);
420 [ - + ]: 5 : if ( v )
421 : 0 : return v->AsFunc();
422 : : else
423 : 5 : return 0;
424 : : }
425 : :
426 : 988 : EventHandlerPtr internal_handler(const char* name)
427 : : {
428 : : // If there already is an entry in the registry, we have a
429 : : // local handler on the script layer.
430 : 988 : EventHandler* h = event_registry->Lookup(name);
431 [ + + ]: 988 : if ( h )
432 : : {
433 : 16 : h->SetUsed();
434 : 16 : return h;
435 : : }
436 : :
437 : 1960 : h = new EventHandler(name);
438 : 972 : event_registry->Register(h);
439 : :
440 : 972 : h->SetUsed();
441 : :
442 : 972 : return h;
443 [ + - ][ + - ]: 6 : }
|