Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

Attr.cc

Go to the documentation of this file.
00001 // $Id: Attr.cc,v 1.4 2005/09/07 17:11:00 vern Exp $
00002 //
00003 // Copyright (c) 2000, 2002
00004 //      The Regents of the University of California.  All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that: (1) source code distributions
00008 // retain the above copyright notice and this paragraph in its entirety, (2)
00009 // distributions including binary code include the above copyright notice and
00010 // this paragraph in its entirety in the documentation or other materials
00011 // provided with the distribution, and (3) all advertising materials mentioning
00012 // features or use of this software display the following acknowledgement:
00013 // ``This product includes software developed by the University of California,
00014 // Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
00015 // the University nor the names of its contributors may be used to endorse
00016 // or promote products derived from this software without specific prior
00017 // written permission.
00018 // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
00019 // WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00020 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022 #include "config.h"
00023 
00024 #include "Attr.h"
00025 #include "Expr.h"
00026 #include "Serializer.h"
00027 
00028 const char* attr_name(attr_tag t)
00029         {
00030         static const char* attr_names[int(NUM_ATTRS)] = {
00031                 "&optional", "&default", "&redef",
00032                 "&rotate_interval", "&rotate_size",
00033                 "&add_func", "&delete_func", "&expire_func",
00034                 "&read_expire", "&write_expire", "&create_expire",
00035                 "&persistent", "&postprocessor", "&encrypt",
00036                 "&match",
00037         };
00038 
00039         return attr_names[int(t)];
00040         }
00041 
00042 Attr::Attr(attr_tag t, Expr* e)
00043         {
00044         tag = t;
00045         expr = e;
00046         SetLocationInfo(&start_location, &end_location);
00047         }
00048 
00049 Attr::~Attr()
00050         {
00051         Unref(expr);
00052         }
00053 
00054 void Attr::Describe(ODesc* d) const
00055         {
00056         AddTag(d);
00057 
00058         if ( expr )
00059                 {
00060                 if ( ! d->IsBinary() )
00061                         d->Add("=");
00062 
00063                 expr->Describe(d);
00064                 }
00065         }
00066 
00067 void Attr::AddTag(ODesc* d) const
00068         {
00069         if ( d->IsBinary() )
00070                 d->Add(bro_int_t(Tag()));
00071         else
00072                 d->Add(attr_name(Tag()));
00073         }
00074 
00075 Attributes::Attributes(attr_list* a, BroType* t)
00076         {
00077         attrs = new attr_list(a->length());
00078         type = t->Ref();
00079 
00080         SetLocationInfo(&start_location, &end_location);
00081 
00082         // We loop through 'a' and add each attribute individually,
00083         // rather than just taking over 'a' for ourselves, so that
00084         // the necessary checking gets done.
00085 
00086         loop_over_list(*a, i)
00087                 AddAttr((*a)[i]);
00088 
00089         delete a;
00090         }
00091 
00092 Attributes::~Attributes()
00093         {
00094         loop_over_list(*attrs, i)
00095                 Unref((*attrs)[i]);
00096 
00097         delete attrs;
00098 
00099         Unref(type);
00100         }
00101 
00102 void Attributes::AddAttr(Attr* attr)
00103         {
00104         if ( ! attrs )
00105                 attrs = new attr_list;
00106 
00107         if ( ! attr->RedundantAttrOkay() )
00108                 // We overwrite old attributes by deleting them first.
00109                 RemoveAttr(attr->Tag());
00110 
00111         attrs->append(attr);
00112         Ref(attr);
00113 
00114         // We only check the attribute after we've added it, to facilitate
00115         // generating error messages via Attributes::Describe.
00116         CheckAttr(attr);
00117 
00118         // For ADD_FUNC or DEL_FUNC, add in an implicit REDEF, since
00119         // those attributes only have meaning for a redefinable value.
00120         if ( (attr->Tag() == ATTR_ADD_FUNC || attr->Tag() == ATTR_DEL_FUNC) &&
00121              ! FindAttr(ATTR_REDEF) )
00122                 attrs->append(new Attr(ATTR_REDEF));
00123 
00124         // For DEFAULT, add an implicit OPTIONAL.
00125         if ( attr->Tag() == ATTR_DEFAULT && ! FindAttr(ATTR_OPTIONAL) )
00126                 attrs->append(new Attr(ATTR_OPTIONAL));
00127         }
00128 
00129 void Attributes::AddAttrs(Attributes* a)
00130         {
00131         attr_list* as = a->Attrs();
00132         loop_over_list(*as, i)
00133                 AddAttr((*as)[i]);
00134 
00135         Unref(a);
00136         }
00137 
00138 Attr* Attributes::FindAttr(attr_tag t) const
00139         {
00140         if ( ! attrs )
00141                 return 0;
00142 
00143         loop_over_list(*attrs, i)
00144                 {
00145                 Attr* a = (*attrs)[i];
00146                 if ( a->Tag() == t )
00147                         return a;
00148                 }
00149 
00150         return 0;
00151         }
00152 
00153 void Attributes::RemoveAttr(attr_tag t)
00154         {
00155         for ( int i = 0; i < attrs->length(); i++ )
00156                 if ( (*attrs)[i]->Tag() == t )
00157                         attrs->remove_nth(i--);
00158         }
00159 
00160 void Attributes::Describe(ODesc* d) const
00161         {
00162         if ( ! attrs )
00163                 {
00164                 d->AddCount(0);
00165                 return;
00166                 }
00167 
00168         d->AddCount(attrs->length());
00169 
00170         loop_over_list(*attrs, i)
00171                 {
00172                 if ( (d->IsReadable() || d->IsPortable()) && i > 0 )
00173                         d->Add(", ");
00174 
00175                 (*attrs)[i]->Describe(d);
00176                 }
00177         }
00178 
00179 void Attributes::CheckAttr(Attr* a)
00180         {
00181         switch ( a->Tag() ) {
00182         case ATTR_OPTIONAL:
00183         case ATTR_REDEF:
00184                 break;
00185 
00186         case ATTR_ADD_FUNC:
00187         case ATTR_DEL_FUNC:
00188                 {
00189                 int is_add = a->Tag() == ATTR_ADD_FUNC;
00190 
00191                 BroType* at = a->AttrExpr()->Type();
00192                 if ( at->Tag() != TYPE_FUNC )
00193                         {
00194                         a->AttrExpr()->Error(
00195                                 is_add ?
00196                                         "&add_func must be a function" :
00197                                         "&delete_func must be a function");
00198                         break;
00199                         }
00200 
00201                 FuncType* aft = at->AsFuncType();
00202                 if ( ! same_type(aft->YieldType(), type) )
00203                         {
00204                         a->AttrExpr()->Error(
00205                                 is_add ?
00206                                         "&add_func function must yield same type as variable" :
00207                                         "&delete_func function must yield same type as variable");
00208                         break;
00209                         }
00210                 }
00211                 break;
00212 
00213         case ATTR_DEFAULT:
00214                 {
00215                 BroType* atype = a->AttrExpr()->Type();
00216 
00217                 if ( type->Tag() != TYPE_TABLE || type->IsSet() )
00218                         {
00219                         if ( ! same_type(atype, type) )
00220                                 a->AttrExpr()->Error("&default value has inconsistent type", type);
00221                         break;
00222                         }
00223 
00224                 TableType* tt = type->AsTableType();
00225 
00226                 if ( ! same_type(atype, tt->YieldType()) )
00227                         {
00228                         // It can still be a default function.
00229                         if ( atype->Tag() == TYPE_FUNC )
00230                                 {
00231                                 FuncType* f = atype->AsFuncType();
00232                                 if ( ! f->CheckArgs(tt->IndexTypes()) ||
00233                                      ! same_type(f->YieldType(), tt->YieldType()) )
00234                                         Error("&default function type clash");
00235                                 }
00236                         else
00237                                 Error("&default value has inconsistent type");
00238                         }
00239                 }
00240                 break;
00241 
00242         case ATTR_ROTATE_INTERVAL:
00243                 if ( type->Tag() != TYPE_FILE )
00244                         Error("&rotate_interval only applicable to files");
00245                 break;
00246 
00247         case ATTR_ROTATE_SIZE:
00248                 if ( type->Tag() != TYPE_FILE )
00249                         Error("&rotate_size only applicable to files");
00250                 break;
00251 
00252         case ATTR_POSTPROCESSOR:
00253                 if ( type->Tag() != TYPE_FILE )
00254                         Error("&postprocessor only applicable to files");
00255                 break;
00256 
00257         case ATTR_ENCRYPT:
00258                 if ( type->Tag() != TYPE_FILE )
00259                         Error("&encrypt only applicable to files");
00260                 break;
00261 
00262         case ATTR_EXPIRE_READ:
00263         case ATTR_EXPIRE_WRITE:
00264         case ATTR_EXPIRE_CREATE:
00265                 if ( type->Tag() != TYPE_TABLE )
00266                         {
00267                         Error("expiration only applicable to tables");
00268                         break;
00269                         }
00270 
00271 #if 0
00272                 //### not easy to test this w/o knowing the ID.
00273                 if ( ! IsGlobal() )
00274                         Error("expiration not supported for local variables");
00275 #endif
00276                 break;
00277 
00278         case ATTR_EXPIRE_FUNC:
00279                 {
00280                 if ( type->Tag() != TYPE_TABLE )
00281                         {
00282                         Error("expiration only applicable to tables");
00283                         break;
00284                         }
00285 
00286                 const Expr* expire_func = a->AttrExpr();
00287                 const FuncType* e_ft = expire_func->Type()->AsFuncType();
00288 
00289                 if ( ((const BroType*) e_ft)->YieldType()->Tag() != TYPE_INTERVAL )
00290                         {
00291                         Error("&expire_func must yield a value of type interval");
00292                         break;
00293                         }
00294 
00295                 if ( e_ft->Args()->NumFields() != 2 )
00296                         {
00297                         Error("&expire_func function must take exactly two arguments");
00298                         break;
00299                         }
00300                 }
00301                 break;
00302 
00303         case ATTR_PERSISTENT:
00304         case ATTR_SYNCHRONIZED:
00305                 // FIXME: Check here for global ID?
00306                 break;
00307 
00308         case ATTR_MATCH:
00309                 // FIXME: Should only be on record types, but I don't
00310                 // know how to enforce this --US
00311                 break;
00312 
00313         default:
00314                 BadTag("Attributes::CheckAttr");
00315         }
00316         }
00317 
00318 bool Attributes::Serialize(SerialInfo* info) const
00319         {
00320         return SerialObj::Serialize(info);
00321         }
00322 
00323 Attributes* Attributes::Unserialize(UnserialInfo* info)
00324         {
00325         return (Attributes*) SerialObj::Unserialize(info, SER_ATTRIBUTES);
00326         }
00327 
00328 IMPLEMENT_SERIAL(Attributes, SER_ATTRIBUTES);
00329 
00330 bool Attributes::DoSerialize(SerialInfo* info) const
00331         {
00332         DO_SERIALIZE(SER_ATTRIBUTES, BroObj);
00333 
00334         info->s->WriteOpenTag("Attributes");
00335         assert(type);
00336         if ( ! (type->Serialize(info) && SERIALIZE(attrs->length())) )
00337                 return false;
00338 
00339         loop_over_list((*attrs), i)
00340                 {
00341                 Attr* a = (*attrs)[i];
00342                 SERIALIZE_OPTIONAL(a->AttrExpr())
00343                 if ( ! SERIALIZE(char(a->Tag())) )
00344                         return false;
00345                 }
00346 
00347         info->s->WriteCloseTag("Attributes");
00348         return true;
00349         }
00350 
00351 bool Attributes::DoUnserialize(UnserialInfo* info)
00352         {
00353         DO_UNSERIALIZE(BroObj);
00354 
00355         type = BroType::Unserialize(info);
00356         if ( ! type )
00357                 return false;
00358 
00359         int len;
00360         if ( ! UNSERIALIZE(&len) )
00361                 return false;
00362 
00363         attrs = new attr_list(len);
00364         while ( len-- )
00365                 {
00366                 Expr* e;
00367                 UNSERIALIZE_OPTIONAL(e, Expr::Unserialize(info))
00368 
00369                 char tag;
00370                 if ( ! UNSERIALIZE(&tag) )
00371                         {
00372                         delete e;
00373                         return false;
00374                         }
00375 
00376                 attrs->append(new Attr((attr_tag)tag, e));
00377                 }
00378 
00379         return true;
00380         }
00381 

Generated on Wed Sep 14 02:55:57 2005 for bro_docs by doxygen 1.3.5