/*** * * Copyright (c) 1988 by Sun Microsystems, Inc. * @(#)sh_class.h 22.1 89/08/10 Copyright 1988 Sun Micro * * SH_CLASS.H - Class Support Macros * * The CLASS package provides a way to create and manipulate * general purpose objects. It supports memory allocation and * freeing and maintains a reference count and a types for each object. * Objects can be fixed size or may grow dynamically. This package * is documented more fully in the Shapes Internal Documentation * (see the Object Extension chapter). * ***/ #ifndef _SH_CLASS #define CLASS_MAX 50 #define CLASS_NOSUPER sh_class_none #define CLASS_THIS 0xff #define CLASS_VARIABLE 0xfe typedef void *OBJID; typedef OBJID (*CLASS_OPER)(); typedef Unsgn8 CLASS_TYPE; typedef Unsgn8 CLASS_ID; /* * Class descriptor */ typedef struct { CLASS_TYPE type; /* type of class (implementation) */ CLASS_ID id; /* class identifier */ } CLASS; /* * Class definition table entry */ typedef struct { CLASS_ID super; /* super class */ CLASS_OPER *opers; /* operators */ } CLASS_DEF; /*** * * Object Header * Each allocated object in the system has a header as follows. * The object type determines whether object id numbers, integers or * both are stored in the object. The class tells how the data is * interpreted by the system (what it means). * ***/ struct obj_hdr { unsigned int obj_flags : 8; /* object flags */ unsigned int obj_size : 24; /* object size (bytes) */ CLASS obj_class; /* class of object */ Unsgn16 obj_use; /* object use count */ CLASS_OPER *obj_func; /* object operator dispatch table */ }; /* * Class table entry */ #define CLASS_NONE 0 struct class { CLASS CLASS_SUPER; /* super class */ CLASS_ID CLASS_BASE; /* base super class */ Unsgn8 CLASS_NUMOPERS; /* number of operators */ Unsgn16 CLASS_SIZE; /* byte size of class data area */ CLASS_OPER *CLASS_OPERS; /* default operator set */ }; #define Define_Class(class, super, nops, size, ops, base) { \ { 0, CAT(CLASS_,super) }, CAT(CLASS_,base), nops, size, ops } /*** * * CLASS Operations * * Get_Class(class, attr) Get class attribute * * Set_Class(class, attr, val) Set class attribute * * Call_Class((CLASS_ID) id, op)(obj, ...) * Invoke an operator from a particular class. Both the type and id * of the class are given in the "class" argument. * * Call_Obj((OBJID) obj, (CLASS_ID) id, op)(obj, ...) * Invoke an operator from a class, taking the type from * the object. The "class" argument gives the ID of the class only. * ****/ #define Set_Class sh_Set_Class #define Get_Class(c, a) CAT(a,get)(sh_class_type[(c).type][(c).id]) #define Call_Class(t, i, o) (*sh_class_type[t][i].CLASS_OPERS[o]) #define Call_Obj(obj, id, op) (*sh_class_type[Get_Obj(obj, OBJ_CLASS_TYPE)][id].CLASS_OPERS[op]) /*** * * CLASS ATTRIBUTES * * CLASS_SIZE byte size of object in the class * CLASS_NUMOPERS number of class operators * CLASS_SUPER CLASS of superclass * CLASS_BASE CLASS_ID of lowest level superclass * CLASS_OPER default operator set * ****/ #define CLASS_SIZEget(c) (c.CLASS_SIZE) #define CLASS_SUPERget(c) (c.CLASS_SUPER) #define CLASS_BASEget(c) (c.CLASS_BASE) #define CLASS_OPERSget(c) (c.CLASS_OPERS) #define CLASS_NUMOPERSget(c) (c.CLASS_NUMOPERS) typedef enum { CLASS_SIZE, CLASS_NUMOPERS, CLASS_SUPER, CLASS_BASE, CLASS_OPERS, } CLASS_attr; /**** * * USER LEVEL OBJECT ACCESS MACROS * * Get_Obj(obj, attr) get object attribute * Set_Obj(obj, attr, val) set object attribute * Use_Obj(obj) reference object * Destroy_Obj(obj) dereference object * Assign_Obj(ptr, obj) assign object to pointer * Size_Obj(obj, s) change object size to S bytes * Extend_Obj(obj, s) extend object size by S additional bytes * Copy_Obj(obj, s) make copy of object (S bytes) * OneRef_Obj(obj) returns true of object has one reference only * ****/ /*** * * OBJECT ATTRIBUTES * * OBJ_SIZE byte size of object * OBJ_FLAGS object flag information * OBJ_CLASS CLASS of object * OBJ_CLASS_ID CLASS_ID of object * OBJ_CLASS_TYPE CLASS_TYPE of object * OBJ_BASE CLASS_ID of lowest level superclass * OBJ_KEY general object key * * Get_Obj(objid, attr) * Get object attribute * * Set_Obj(objid, attr, val) * Set object attribute * * Class_Obj(objid, classid) * Initialize object header * * Static_Obj(name, cstruct) * Declare "name" to be an object whose internal structure * is of type "cstruct". name_hdr references the object header. * ****/ #define Get_Obj(o, a) CAT(a,get)(((struct obj_hdr *) (o)) - 1) #define OBJ_SIZEget(o) ((o)->obj_size) #define OBJ_FLAGSget(o) ((o)->obj_flags) #define OBJ_CLASSget(o) ((o)->obj_class) #define OBJ_CLASS_IDget(o) ((o)->obj_class.id) #define OBJ_CLASS_TYPEget(o) ((o)->obj_class.type) #define OBJ_USEget(o) ((o)->obj_use) #define OBJ_OPERSget(o) ((o)->obj_func) #define OBJ_BASEget(o) Get_Class((o)->obj_class, CLASS_BASE) #define OBJ_KEYget(o) (*((OBJ_KEY *) ((o) + 1))) #define GetOper_Obj(o,i) (Get_Obj(o, OBJ_OPERS)[i]) #define Set_Obj(o, a, v) CAT(a,set)(((struct obj_hdr *) (o) - 1), v) #define OBJ_KEYset(o, v) (*((OBJ_KEY *) (o + 1)) = (v)) #define OBJ_SIZEset(o, v) Size_Obj(o + 1, v) #define OBJ_FLAGSset(o, v) ((o)->obj_flags |= (v)) #define OBJ_CLASSset(o, v) ( \ (o->obj_func = Get_Class(v, CLASS_OPERS)), (o->obj_class = v)) #define OBJ_CLASS_TYPEset(o, v) ( \ (o->obj_class.type = v), \ (o->obj_func = Get_Class(o->obj_class, CLASS_OPERS))) #define OBJ_CLASS_IDset(o, v) ( \ (o->obj_class.id = v), \ (o->obj_func = Get_Class(o->obj_class, CLASS_OPERS))) #define Static_Obj(name, cstruct) \ struct obj_hdr CAT(name,_hdr); \ cstruct name #define Class_Obj(o, c) { \ (((struct obj_hdr *) (o)) - 1)->obj_flags = 0; \ (((struct obj_hdr *) (o)) - 1)->obj_size = \ sh_class_type[0][c].CLASS_SIZE; \ (((struct obj_hdr *) (o)) - 1)->obj_class.type = 0; \ Set_Obj(o, OBJ_CLASS_ID, c); } /**** * * Use_Obj(obj) * Reference (increment the use count) the given object. * Check for wrap-around. * ****/ #define Use_Obj(obj) ((++Get_Obj(obj, OBJ_USE) == 0) && --Get_Obj(obj, OBJ_USE)) #define OneRef_Obj(obj) (Get_Obj(obj, OBJ_USE) == 2) /*** * * VOID Destroy_Obj(objid) * Decrement reference count and garbage collect object if necessary * Returns zero if object was not removed, else non-zero. * ***/ #define Destroy_Obj(o) ((o) && \ (--((((struct obj_hdr *) (o)) - 1)->obj_use) <= 1) && \ sh_Kill_Obj(o)) /*** * * OBJID Init_Obj(obj, root, type) * Initialize object * ***/ #define Init_Obj(o,r,t) (GetOper_Obj(o,1)(o,r,t)) /**** * * Assign_Obj(objptr, obj) * Assigns an object to a pointer. The old object referred to by the * pointer is removed (dereferenced) and the new object is referenced. * THIS MACRO HAS SIDE EFFECTS. It expands both arguments more than once. * ****/ #define Assign_Obj(OBJPTR, NEW) do { \ register OBJID OLD = *((OBJID *) (OBJPTR)); \ if (NEW) Use_Obj(NEW); \ Destroy_Obj(OLD); \ *((OBJID *) (OBJPTR)) = (OBJID) (NEW); \ } while(0) /**** * * OBJID Extend_Obj(obj, n) * Extend the given object by N bytes. May return a new object. * ****/ #define Extend_Obj(obj, n) Size_Obj(obj, (n) + Get_Obj(obj, OBJ_SIZE)) /*** * * Object Flags * OBJ_NOSHRINK indicates the object cannot be "shrunk". * That is, the Size_Obj operation cannot make the object * smaller, only larger. * OBJ_NOKILL indicates the object cannot be removed. * ***/ #define OBJ_NOSHRINK 1 #define OBJ_NOKILL 2 /**** * * Object KEY operations * A key is an attribute that uniquely describes the state of an object. * Each object has a general key (xxx_KEY attribute). Whenever any * attribute in an object is modified, its KEY attribute changes. * ****/ #define GET_KEY() (++sh_key) #define NEW_KEY(o) (Get_Obj(o, OBJ_KEY) = GET_KEY()) /**** * * External Routines (all begin with sh_) * ****/ #define Create_Class sh_Create_Class #define NewType_Class sh_NewType_Class #define Create_Obj sh_Create_Obj #define Temp_Obj sh_Temp_Obj #define New_Obj sh_New_Obj #define Size_Obj sh_Size_Obj #define Copy_Obj sh_Copy_Obj /*** * * General Globals * ***/ extern CLASS_TYPE NewType_Class(); /* make new class type */ extern CLASS_ID Create_Class(); /* make new class */ extern OBJID Create_Obj(); /* make "used" object */ extern OBJID Temp_Obj(); /* make temporary object */ extern OBJID New_Obj(); /* allocate memory for object */ extern OBJID Size_Obj(); /* resize object */ extern OBJID Copy_Obj(); /* copy object */ extern void sh_Set_Class(); /* set class attribute */ extern CLASS sh_class_none; /* class with 0 type and 0 id */ extern Unsgn8 sh_obj_dbg; extern OBJ_KEY sh_key; extern struct class *sh_class_type[]; #define _SH_CLASS #endif /* _SH_CLASS */