Listing 1 Macros which add object-oriented extensions to Standards C.
/******* OBJECTS.H Copyright 1992 Gregory Colvin ******** This program may be distributed free with this notice. **********************************************************/ #ifndef OBJECTS_H #define OBJECTS_H #include <assert.h> #include <stdlib.h> #include <string.h> #ifndef _cplusplus /* Not C++, assume C */ /if !defined(_MSDOS_) || defined(_STDC_) #define near /* near pointers are DOS extension */ #endif /* Base class for all objects: */ typedef struct{ char near *name; int initialized; void (*destroy)(void); int (*isA)(const char *className); } ObjectMethods; extern ObjectMethods ObjectTable; void ObjectInitClass(void); typedef struct Object { ObjectMethods near *methods; } Object; void Object_construct(void); void Object_destruct(void); /* Manage "this" pointer stack for methods: */ extern Object * near *pThis; #define MAX_PUSH 512 #if 1 #define PREV_THIS()(*(pThis-1)) #define PUSH_THIS(pObj) (*--pThis = (Object*)(pObj)) #define GET_THIS(Class) ((Class*)*pThis) #define GET_THIS_SAFE(Class) \ (assert(IS_A(*pThis,Class)),GET_THIS(Class)) #define POP_THIS()(*pThis++) #define POP_THIS_SAFE(Class) \ (assert(IS_A(*pThis,Class)),(Class*)POP_THIS()) #else #define PREV_THIS() (*(Object**)_DI) #define PUSH_THIS (pObj) ((* (Object**)_DI) = pObj) #define GET_THIS(Class) (*(Class**)_DI) #define GET_THIS_SAFE(Class) \ (assert(IS_A(GET_THIS(Class),Class)),GET_THIS(Class)) #define POP_THIS() (*(Object**)_DI) #define POP_THIS_SAFE(Class) GET_THIS_SAFE(Class) #endif /* Begin class methods declaration: */ #define DCL_METHODS(Class,Base,ConstructorArguments) \ typedef struct Class##DataStruct Class; \ void Class##_construct ConstructorArguments; \ void Class##_destruct(void); \ struct Class##MethodStruct { \ Base##Methods base; /* Declare and redeclare methods: */ /define DCL_METHOD(Name,Arguments,Return) \ Return (*Name)Arguments /define DCL_ABSTRACT(Name,Arguments,Return) \ Return (*Name)Arguments #define REDCL_METHOD(Name, Arguments, Return) \ void dummy_##Name /* End class methods or class type declaration: */ #define END_METHODS }; /* Begin class members declaration: */ #define DCL_MEMBERS(Class,Base) \ typedef struct Class##MethodStruct Class##Methods; \ extern Class##Methods Class##Table; \ extern void Class##InitClass(void); \ struct Class##DataStruct { \ Base base; #define END_MEMBERS }; /* Begin class type definition: */ #define DEF_CLASS(Class,Base) \ Class##Methods Class##Table = { 0, 0 }; \ int Class##_isA(const char *className) { \ int yes= !strcmp(#Class,className); \ if (!yes) \ yes = ((ObjectMethods*)(&Base##Table))->isA(className); \ return yes; \ } \ void Class##_destroy(void) { \ Class##_destruct(); \ ((ObjectMethods*) (&Base##Table))->destroy(); \ } \ void Class##InitClass(void) { \ ObjectMethods *objTable= (ObjectMethods*)&Class##Table; \ Base##Methods *baseTable= (Base##Methods*)&Class##Table; \ Base##InitClass(); \ if (objTable->initialized) \ return; \ *baseTable = Base##Table; \ objTable->name = #Class; \ REDEF_METHOD(Class,Object,isA); \ REDEF_METHOD(Class,Object,destroy); /* Set and reset methods within a class definition: */ #define DEF_ABSTRACT(Base,Method) \ (Base##Table.Method = 0) #define DEF_METHOD(Base,Method) \ (Base##Table.Method = Base##_##Method) #define REDEF_METHOD(Class,Base,Method) \ (((Base##Methods *)(&Class##Table))-->Method \ = Class##_##Method) /* End class type definition: */ #define END_CLASS } /* Initialize a class before use: */ #define USE(Class) Class##InitClass() /* Begin class method implementation: */ #define METHOD(Class,Name,Arguments,Return) \ Return Class##_##Name Arguments { \ Class *this = POP_THIS_SAFE(Class); /* End class method implementation: */ #define END_METHOD } /* Begin class constructor implementation: */ /define CONSTRUCTOR(Class,Arguments) \ void Class##_construct Arguments { \ Class *this= GET_THIS(Class); \ ObjectMethods *Methods= \ (ObjectMethods *)&Class##Table; /* Must construct Base first in class constructor: */ #define CONSTRUCT(Base,Arguments) \ Base##_construct Arguments; \ ((Object *)this)->methods = Methods; { /* End class constructor implementation: */ #define END_CONSTRUCTOR }} /* Begin class destructor implementation: */ #define DESTRUCTOR(Class) \ void Class##_destruct(void) { \ Class *this = GET_THIS_SAFE(Class); \ ((Object *)this)->methods = \ (ObjectMethods *)&Class##Table; { /* End class destructor implementation: */ #define END_DESTRUCTOR }} /* Monomorphic access to a method of a class: */ #define CALL(pObj,Class,Base,Name,Arguments) \ ((PUSH_THIS(pObj), \ (Base##Methods *)(&Class##Table))->Name Arguments \ ) /* Polymorphic access to a method of a class: */ #define SEND(pObj,Base,Name,Arguments) \ (((Base##Methods*) \ (PUSH_THIS(pObj)->methods))->Name Arguments) /* Construct a new object on the heap: */ #define NEW(Class,Arguments) \ (PUSH_THIS(malloc(sizeof(Class)))), \ Class##_construct Arguments, \ POP_THIS_SAFE(Class))) /* Construct a new object on the stack: */ #define PUSH(ObjName,Class,Arguments) \ Class auto_##ObjName; \ Class *ObjName = (Class*) \ (PUSH_THIS(&auto_##ObjName), \ Class##_construct Arguments, \ POP_THIS_SAFE(Class)) /* Destroy an object on the heap: */ #define DELETE(pObj) \ (SEND(pObj,Object,destroy,()), free(POP_THIS()) /* Destroy an object on the stack: */ #define POP(pObj) SEND(pObj,Object,destroy, ()) /* Test whether object is a member of named class: */ #define IS_A(pObj,Class) \ ((((Object *)pObj)->methods)->isA(#Class)) /* Access to the class name of an object: */ #define CLASS_NAME(pObj) \ (((ObjectTable*)(((Object *)(pObj))->methods))->name) #else /* C++ */ /* Base class for all objects: */ struct Object { virtual int isA(const char *className); virtual const char *classname(); }; /* Begin class methods declaration: */ #define DCL_METHODS(Class,Base,ConstructorArguments) \ struct Class : Base { \ Class ConstructorArguments; \ virtual ~Class(); \ virtual int isA(const char *className); \ virtual const char *classname(); /* Declare and redeclare methods: */ #define DCL_METHOD(Name,Arguments,Return) \ virtual Return Name Arguments #define DCL_ABSTRACT(Name,Arguments,Return) \ virtual Return Name Arguments=0 #define REDCL_METHOD(Name,Arguments,Return) \ virtual Return Name Arguments /*End class methods declaration: */ #define END_METHODS /* Begin class members declaration: */ #define DCL_MEMBERS(Class,Base) /* End class type declaration: */ #define END_MEMBERS }; /* Begin class type definition: */ #define DEF_CLASS(Class,Base) \ const char *Class::classname() { \ return #Class; \ } \ int Class::isA(const char *className) { \ if (strcmp(#Class,className)) \ return Base::isA(#Class); \ return 1; \ } \ /* Set and reset methods within a class definition: */ #define DEF_ABSTRACT(Base,Method) /define DEF_METHOD(Base,Method) #define REDEF_METHOD(Class,Base,Method) /*End class type definition: */ /define END_CLASS /*Initialize a class before use: */ #define USE(Class) /* Begin class method implementation: */ #define METHOD(Class,Name,Arguments,Return) \ Return Class::Name Arguments { /*End class method implementation: */ #define END METHOD } /* Begin class constructor implementation: */ #define CONSTRUCTOR(Class,Arguments) Class::Class Arguments: /*Must construct Base first in class constructor: */ #define CONSTRUCT(Base,Arguments) Base Arguments { /* End class constructor implementation: */ #define END_CONSTRUCTOR } /* Begin class desstructor implementation: */ #define DESTRUCTOR(Class) Class::~Class(){ /* End class destructor implementation: */ #define END_DESTRUCTOR } /* Monomorphic access to a method of a class: */ #define CALL(pObj,Class,Base,Name,Arguments) \ (pObj->Class::Name Arguments) /* Polymorphic access to a method of a class: */ /define SEND(pObj,Base,Name,Arguments) \ (pObj->Name Arguments) /*Construct a new object on the heap: */ #define CREATE(Class) new Class /* Construct a new object on the stack: */ #define PUSH(ObjName,Class,Arguments) \ Class auto##ObjName Arguments; \ Class *ObjName= &auto##ObjName /* Destroy an object on the heap: */ #define DELETE(pObj) \ delete(pObj) /* Destroy an object on the stack: */ #define POP(pObj) /* Test whether object is a member of named class: */ #define IS_A(pObj,className) \ SEND(pObj ,Object,isA,(className)) /* Access to the class name of an object: */ #define CLASS_NAME(pObj) (pObj->classname() #endif /* C vs. C++ */ #endif /* End of File */