Branch data Line data Source code
1 : : // $Id: Attr.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 "Attr.h"
8 : : #include "Expr.h"
9 : : #include "Serializer.h"
10 : :
11 : 0 : const char* attr_name(attr_tag t)
12 : : {
13 : : static const char* attr_names[int(NUM_ATTRS)] = {
14 : : "&optional", "&default", "&redef",
15 : : "&rotate_interval", "&rotate_size",
16 : : "&add_func", "&delete_func", "&expire_func",
17 : : "&read_expire", "&write_expire", "&create_expire",
18 : : "&persistent", "&synchronized", "&postprocessor",
19 : : "&encrypt", "&match", "&disable_print_hook",
20 : : "&raw_output", "&mergeable", "&priority",
21 : : "&group", "(&tracked)",
22 : : };
23 : :
24 : 0 : return attr_names[int(t)];
25 : : }
26 : :
27 : 1845 : Attr::Attr(attr_tag t, Expr* e)
28 : : {
29 : 1845 : tag = t;
30 : 1845 : expr = e;
31 : 1845 : SetLocationInfo(&start_location, &end_location);
32 : 1845 : }
33 : :
34 : 0 : Attr::~Attr()
35 : : {
36 : 0 : Unref(expr);
37 [ # # ][ # # ]: 0 : }
[ # # ]
38 : :
39 : 0 : void Attr::Describe(ODesc* d) const
40 : : {
41 : 0 : AddTag(d);
42 : :
43 [ # # ]: 0 : if ( expr )
44 : : {
45 [ # # ]: 0 : if ( ! d->IsBinary() )
46 : 0 : d->Add("=");
47 : :
48 : 0 : expr->Describe(d);
49 : : }
50 : 0 : }
51 : :
52 : 0 : void Attr::AddTag(ODesc* d) const
53 : : {
54 [ # # ]: 0 : if ( d->IsBinary() )
55 : 0 : d->Add(static_cast<bro_int_t>(Tag()));
56 : : else
57 : 0 : d->Add(attr_name(Tag()));
58 : 0 : }
59 : :
60 : 1510 : Attributes::Attributes(attr_list* a, BroType* t)
61 : : {
62 : 1510 : attrs = new attr_list(a->length());
63 : 1510 : type = t->Ref();
64 : :
65 : 1510 : SetLocationInfo(&start_location, &end_location);
66 : :
67 : : // We loop through 'a' and add each attribute individually,
68 : : // rather than just taking over 'a' for ourselves, so that
69 : : // the necessary checking gets done.
70 : :
71 [ + + ][ # # ]: 3137 : loop_over_list(*a, i)
72 : 1627 : AddAttr((*a)[i]);
73 : :
74 [ + - ][ # # ]: 1510 : delete a;
75 : 1510 : }
76 : :
77 : 16 : Attributes::~Attributes()
78 : : {
79 [ + + ][ # # ]: 34 : loop_over_list(*attrs, i)
[ # # ]
80 : 18 : Unref((*attrs)[i]);
81 : :
82 [ + - ][ # # ]: 16 : delete attrs;
[ # # ]
83 : :
84 : 16 : Unref(type);
85 [ + - ][ # # ]: 16 : }
[ # # ]
86 : :
87 : 1645 : void Attributes::AddAttr(Attr* attr)
88 : : {
89 [ - + ]: 1645 : if ( ! attrs )
90 : 0 : attrs = new attr_list;
91 : :
92 [ + + ]: 1645 : if ( ! attr->RedundantAttrOkay() )
93 : : // We overwrite old attributes by deleting them first.
94 : 514 : RemoveAttr(attr->Tag());
95 : :
96 : 1645 : attrs->append(attr);
97 : 1645 : Ref(attr);
98 : :
99 : : // We only check the attribute after we've added it, to facilitate
100 : : // generating error messages via Attributes::Describe.
101 : 1645 : CheckAttr(attr);
102 : :
103 : : // For ADD_FUNC or DEL_FUNC, add in an implicit REDEF, since
104 : : // those attributes only have meaning for a redefinable value.
105 [ + + - + ]: 1645 : if ( (attr->Tag() == ATTR_ADD_FUNC || attr->Tag() == ATTR_DEL_FUNC) &&
[ + - ][ + + ]
106 : : ! FindAttr(ATTR_REDEF) )
107 : 6 : attrs->append(new Attr(ATTR_REDEF));
108 : :
109 : : // For DEFAULT, add an implicit OPTIONAL.
110 [ + + ][ + + ]: 1645 : if ( attr->Tag() == ATTR_DEFAULT && ! FindAttr(ATTR_OPTIONAL) )
[ + + ]
111 : 198 : attrs->append(new Attr(ATTR_OPTIONAL));
112 : 1645 : }
113 : :
114 : 16 : void Attributes::AddAttrs(Attributes* a)
115 : : {
116 : 16 : attr_list* as = a->Attrs();
117 [ + + ]: 34 : loop_over_list(*as, i)
118 : 18 : AddAttr((*as)[i]);
119 : :
120 : 16 : Unref(a);
121 : 16 : }
122 : :
123 : 156094 : Attr* Attributes::FindAttr(attr_tag t) const
124 : : {
125 [ - + ]: 156094 : if ( ! attrs )
126 : 0 : return 0;
127 : :
128 [ + + ]: 306500 : loop_over_list(*attrs, i)
129 : : {
130 : 201981 : Attr* a = (*attrs)[i];
131 [ + + ]: 201981 : if ( a->Tag() == t )
132 : 51575 : return a;
133 : : }
134 : :
135 : 156094 : return 0;
136 : : }
137 : :
138 : 514 : void Attributes::RemoveAttr(attr_tag t)
139 : : {
140 [ + + ]: 681 : for ( int i = 0; i < attrs->length(); i++ )
141 [ + + ]: 167 : if ( (*attrs)[i]->Tag() == t )
142 : 8 : attrs->remove_nth(i--);
143 : 514 : }
144 : :
145 : 0 : void Attributes::Describe(ODesc* d) const
146 : : {
147 [ # # ]: 0 : if ( ! attrs )
148 : : {
149 : 0 : d->AddCount(0);
150 : 0 : return;
151 : : }
152 : :
153 : 0 : d->AddCount(attrs->length());
154 : :
155 [ # # ]: 0 : loop_over_list(*attrs, i)
156 : : {
157 [ # # ][ # # ]: 0 : if ( (d->IsReadable() || d->IsPortable()) && i > 0 )
[ # # ][ # # ]
158 : 0 : d->Add(", ");
159 : :
160 : 0 : (*attrs)[i]->Describe(d);
161 : : }
162 : : }
163 : :
164 : 1645 : void Attributes::CheckAttr(Attr* a)
165 : : {
166 [ + + + - - : 1645 : switch ( a->Tag() ) {
- - + + +
- - + - +
- ]
167 : : case ATTR_OPTIONAL:
168 : : case ATTR_REDEF:
169 : 1131 : break;
170 : :
171 : : case ATTR_ADD_FUNC:
172 : : case ATTR_DEL_FUNC:
173 : : {
174 : 6 : int is_add = a->Tag() == ATTR_ADD_FUNC;
175 : :
176 : 6 : BroType* at = a->AttrExpr()->Type();
177 [ - + ]: 6 : if ( at->Tag() != TYPE_FUNC )
178 : : {
179 : : a->AttrExpr()->Error(
180 : : is_add ?
181 : : "&add_func must be a function" :
182 [ # # ]: 0 : "&delete_func must be a function");
183 : 0 : break;
184 : : }
185 : :
186 : 6 : FuncType* aft = at->AsFuncType();
187 [ - + ]: 6 : if ( ! same_type(aft->YieldType(), type) )
188 : : {
189 : : a->AttrExpr()->Error(
190 : : is_add ?
191 : : "&add_func function must yield same type as variable" :
192 [ # # ]: 0 : "&delete_func function must yield same type as variable");
193 : 0 : break;
194 : : }
195 : : }
196 : 6 : break;
197 : :
198 : : case ATTR_DEFAULT:
199 : : {
200 : 202 : BroType* atype = a->AttrExpr()->Type();
201 : :
202 [ + + - + ]: 202 : if ( type->Tag() != TYPE_TABLE || type->IsSet() )
[ + + ]
203 : : {
204 [ - + ]: 118 : if ( ! same_type(atype, type) )
205 : 0 : a->AttrExpr()->Error("&default value has inconsistent type", type);
206 : 118 : break;
207 : : }
208 : :
209 : 84 : TableType* tt = type->AsTableType();
210 : :
211 [ + + ]: 84 : if ( ! same_type(atype, tt->YieldType()) )
212 : : {
213 : : // It can still be a default function.
214 [ + - ]: 15 : if ( atype->Tag() == TYPE_FUNC )
215 : : {
216 : 15 : FuncType* f = atype->AsFuncType();
217 [ + - - + ]: 15 : if ( ! f->CheckArgs(tt->IndexTypes()) ||
[ - + ]
218 : : ! same_type(f->YieldType(), tt->YieldType()) )
219 : 15 : Error("&default function type clash");
220 : : }
221 : : else
222 : 0 : Error("&default value has inconsistent type");
223 : : }
224 : : }
225 : 84 : break;
226 : :
227 : : case ATTR_ROTATE_INTERVAL:
228 [ # # ]: 0 : if ( type->Tag() != TYPE_FILE )
229 : 0 : Error("&rotate_interval only applicable to files");
230 : 0 : break;
231 : :
232 : : case ATTR_ROTATE_SIZE:
233 [ # # ]: 0 : if ( type->Tag() != TYPE_FILE )
234 : 0 : Error("&rotate_size only applicable to files");
235 : 0 : break;
236 : :
237 : : case ATTR_POSTPROCESSOR:
238 [ # # ]: 0 : if ( type->Tag() != TYPE_FILE )
239 : 0 : Error("&postprocessor only applicable to files");
240 : 0 : break;
241 : :
242 : : case ATTR_ENCRYPT:
243 [ # # ]: 0 : if ( type->Tag() != TYPE_FILE )
244 : 0 : Error("&encrypt only applicable to files");
245 : 0 : break;
246 : :
247 : : case ATTR_EXPIRE_READ:
248 : : case ATTR_EXPIRE_WRITE:
249 : : case ATTR_EXPIRE_CREATE:
250 [ - + ]: 140 : if ( type->Tag() != TYPE_TABLE )
251 : : {
252 : 0 : Error("expiration only applicable to tables");
253 : 0 : break;
254 : : }
255 : :
256 : : #if 0
257 : : //### not easy to test this w/o knowing the ID.
258 : : if ( ! IsGlobal() )
259 : : Error("expiration not supported for local variables");
260 : : #endif
261 : 140 : break;
262 : :
263 : : case ATTR_EXPIRE_FUNC:
264 : : {
265 [ - + ]: 19 : if ( type->Tag() != TYPE_TABLE )
266 : : {
267 : 0 : Error("expiration only applicable to tables");
268 : 0 : break;
269 : : }
270 : :
271 : 19 : const Expr* expire_func = a->AttrExpr();
272 : 19 : const FuncType* e_ft = expire_func->Type()->AsFuncType();
273 : :
274 [ - + ]: 19 : if ( ((const BroType*) e_ft)->YieldType()->Tag() != TYPE_INTERVAL )
275 : : {
276 : 0 : Error("&expire_func must yield a value of type interval");
277 : 0 : break;
278 : : }
279 : :
280 [ - + ]: 19 : if ( e_ft->Args()->NumFields() != 2 )
281 : : {
282 : 0 : Error("&expire_func function must take exactly two arguments");
283 : 0 : break;
284 : : }
285 : :
286 : : // ### Should type-check arguments to make sure first is
287 : : // table type and second is table index type.
288 : : }
289 : 19 : break;
290 : :
291 : : case ATTR_PERSISTENT:
292 : : case ATTR_SYNCHRONIZED:
293 : : case ATTR_TRACKED:
294 : : // FIXME: Check here for global ID?
295 : 20 : break;
296 : :
297 : : case ATTR_DISABLE_PRINT_HOOK:
298 [ # # ]: 0 : if ( type->Tag() != TYPE_FILE )
299 : 0 : Error("&disable_print_hook only applicable to files");
300 : 0 : break;
301 : :
302 : : case ATTR_RAW_OUTPUT:
303 [ # # ]: 0 : if ( type->Tag() != TYPE_FILE )
304 : 0 : Error("&raw_output only applicable to files");
305 : 0 : break;
306 : :
307 : : case ATTR_MERGEABLE:
308 [ - + ]: 19 : if ( type->Tag() != TYPE_TABLE )
309 : 0 : Error("&mergeable only applicable to tables/sets");
310 : 19 : break;
311 : :
312 : : case ATTR_PRIORITY:
313 : 0 : Error("&priority only applicable to event bodies");
314 : 0 : break;
315 : :
316 : : case ATTR_GROUP:
317 [ + - ][ - + ]: 108 : if ( type->Tag() != TYPE_FUNC ||
[ - + ]
318 : : ! type->AsFuncType()->IsEvent() )
319 : : {
320 : 0 : Error("&group only applicable to events");
321 : 0 : break;
322 : : }
323 : 108 : break;
324 : :
325 : : default:
326 : 0 : BadTag("Attributes::CheckAttr", attr_name(a->Tag()));
327 : : }
328 : 1645 : }
329 : :
330 : 7 : bool Attributes::Serialize(SerialInfo* info) const
331 : : {
332 : 7 : return SerialObj::Serialize(info);
333 : : }
334 : :
335 : 0 : Attributes* Attributes::Unserialize(UnserialInfo* info)
336 : : {
337 : 0 : return (Attributes*) SerialObj::Unserialize(info, SER_ATTRIBUTES);
338 : : }
339 : :
340 : 15 : IMPLEMENT_SERIAL(Attributes, SER_ATTRIBUTES);
341 : :
342 : 6 : bool Attributes::DoSerialize(SerialInfo* info) const
343 : : {
344 [ + - ][ - + ]: 6 : DO_SERIALIZE(SER_ATTRIBUTES, BroObj);
345 : :
346 : 6 : info->s->WriteOpenTag("Attributes");
347 [ - + ]: 6 : assert(type);
348 [ + - ][ - + ]: 6 : if ( ! (type->Serialize(info) && SERIALIZE(attrs->length())) )
[ - + ]
349 : 0 : return false;
350 : :
351 [ + + ]: 19 : loop_over_list((*attrs), i)
352 : : {
353 : 13 : Attr* a = (*attrs)[i];
354 [ + + + - ]: 13 : SERIALIZE_OPTIONAL(a->AttrExpr())
[ - + ][ - + ]
[ - + ][ - + ]
355 [ - + ]: 13 : if ( ! SERIALIZE(char(a->Tag())) )
356 : 0 : return false;
357 : : }
358 : :
359 : 6 : info->s->WriteCloseTag("Attributes");
360 : 6 : return true;
361 : : }
362 : :
363 : 0 : bool Attributes::DoUnserialize(UnserialInfo* info)
364 : : {
365 [ # # ]: 0 : DO_UNSERIALIZE(BroObj);
366 : :
367 : 0 : type = BroType::Unserialize(info);
368 [ # # ]: 0 : if ( ! type )
369 : 0 : return false;
370 : :
371 : : int len;
372 [ # # ]: 0 : if ( ! UNSERIALIZE(&len) )
373 : 0 : return false;
374 : :
375 : 0 : attrs = new attr_list(len);
376 [ # # ]: 0 : while ( len-- )
377 : : {
378 : : Expr* e;
379 [ # # ][ # # ]: 0 : UNSERIALIZE_OPTIONAL(e, Expr::Unserialize(info))
[ # # ]
380 : :
381 : : char tag;
382 [ # # ]: 0 : if ( ! UNSERIALIZE(&tag) )
383 : : {
384 [ # # ]: 0 : delete e;
385 : 0 : return false;
386 : : }
387 : :
388 : 0 : attrs->append(new Attr((attr_tag)tag, e));
389 : : }
390 : :
391 : 0 : return true;
392 [ + - ][ + - ]: 6 : }
393 : 3 :
|