// $Id: Attr.h,v 1.17 2003/08/31 00:38:11 vern Exp $
//
// Copyright (c) 1995, 1997, 1998, 1999, 2002
//      The Regents of the University of California.  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that: (1) source code distributions
// retain the above copyright notice and this paragraph in its entirety, (2)
// distributions including binary code include the above copyright notice and
// this paragraph in its entirety in the documentation or other materials
// provided with the distribution, and (3) all advertising materials mentioning
// features or use of this software display the following acknowledgement:
// ``This product includes software developed by the University of California,
// Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
// the University nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

#ifndef attr_h
#define attr_h

#include "Obj.h"

class Expr;

// Note that there are two kinds of attributes: the kind (here) which
// modify expressions or supply metadata on types, and the kind that
// are extra metadata on every variable instance.

typedef enum {
	ATTR_OPTIONAL,
	ATTR_DEFAULT,
	ATTR_REDEF,
	ATTR_ADD_FUNC,
	ATTR_DEL_FUNC,
	ATTR_EXPIRE_FUNC,
	ATTR_EXPIRE_READ,
	ATTR_EXPIRE_WRITE,
	ATTR_EXPIRE_CREATE,
	ATTR_PERSISTENT,
#define NUM_ATTRS (int(ATTR_PERSISTENT) + 1)
} attr_tag;

class Attr : public BroObj {
public:
	Attr(attr_tag t, Expr* e = 0);
	~Attr();

	attr_tag Tag() const	{ return tag; }
	Expr* AttrExpr() const	{ return expr; }

	int RedundantAttrOkay() const
		{ return tag == ATTR_REDEF || tag == ATTR_OPTIONAL; }

	void Describe(ODesc* d) const;

protected:
	void AddTag(ODesc* d) const;

	attr_tag tag;
	Expr* expr;
};

// Manages a collection of attributes.
class Attributes : public BroObj {
public:
	Attributes(attr_list* a, BroType* t);
	~Attributes();

	void AddAttr(Attr* a);
	void AddAttrs(Attributes* a);	// Unref's 'a' when done

	Attr* FindAttr(attr_tag t) const;

	void Describe(ODesc* d) const;

protected:
	attr_list* Attrs()	{ return attrs; }
	void CheckAttr(Attr* attr);

	BroType* type;
	attr_list* attrs;
};

#endif
