home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_11_07
/
1107067a
< prev
next >
Wrap
Text File
|
1993-05-18
|
10KB
|
304 lines
/******** 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