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 >
Text File  |  1993-05-18  |  10KB  |  304 lines

  1. /******** OBJECTS.H  Copyright 1992 Gregory Colvin *********
  2.    This program may be distributed free with this notice.
  3. ***********************************************************/
  4. #ifndef OBJECTS_H
  5. #define OBJECTS_H
  6. #include <assert.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9.  
  10. #ifndef __cplusplus /* Not C++, assume C */
  11.  
  12. #if !defined(__MSDOS__) || defined(__STDC__)
  13.   #define near      /* near pointers are DOS extension */
  14. #endif
  15.  
  16. /* Base class for all objects: */
  17. typedef struct {
  18.   char near *name;
  19.   int initialized;
  20.   void (*destroy)(void);
  21.   int (*isA)(const char *className);
  22. } ObjectMethods;
  23. extern ObjectMethods ObjectTable;
  24. void ObjectInitClass(void);
  25. typedef struct Object {
  26.   ObjectMethods near *methods;
  27. } Object;
  28. void Object_construct(void);
  29. void Object_destruct(void);
  30.  
  31. /* Manage "this" pointer stack for methods: */
  32. extern Object * near *pThis;
  33. #define MAX_PUSH 512
  34. #if 1
  35. #define PREV_THIS() (*(pThis-1))
  36. #define PUSH_THIS(pObj) (*--pThis = (Object*)(pObj))
  37. #define GET_THIS(Class) ((Class*)*pThis)
  38. #define GET_THIS_SAFE(Class) \
  39.   (assert(IS_A(*pThis,Class)),GET_THIS(Class))
  40. #define POP_THIS() (*pThis++)
  41. #define POP_THIS_SAFE(Class) \
  42.   (assert(IS_A(*pThis,Class)),(Class*)POP_THIS())
  43. #else
  44. #define PREV_THIS() (*(Object**)_DI)
  45. #define PUSH_THIS(pObj) ((*(Object**)_DI) = pObj)
  46. #define GET_THIS(Class) (*(Class**)_DI)
  47. #define GET_THIS_SAFE(Class) \
  48.   (assert(IS_A(GET_THIS(Class),Class)),GET_THIS(Class))
  49. #define POP_THIS() (*(Object**)_DI)
  50. #define POP_THIS_SAFE(Class) GET_THIS_SAFE(Class)
  51. #endif
  52.  
  53. /* Begin class methods declaration: */
  54. #define DCL_METHODS(Class,Base,ConstructorArguments) \
  55.  typedef struct Class##DataStruct Class;             \
  56.  void Class##_construct ConstructorArguments;        \
  57.  void Class##_destruct(void);                        \
  58.  struct Class##MethodStruct {                        \
  59.   Base##Methods base;
  60.  
  61. /* Declare and redeclare methods: */
  62. #define DCL_METHOD(Name,Arguments,Return) \
  63.  Return (*Name)Arguments
  64. #define DCL_ABSTRACT(Name,Arguments,Return) \
  65.  Return (*Name)Arguments
  66. #define REDCL_METHOD(Name,Arguments,Return) \
  67.  void dummy_##Name
  68.  
  69. /* End class methods or class type declaration: */
  70. #define END_METHODS };
  71.  
  72. /* Begin class members declaration: */
  73. #define DCL_MEMBERS(Class,Base)                     \
  74.  typedef struct Class##MethodStruct Class##Methods; \
  75.  extern Class##Methods Class##Table;                \
  76.  extern void Class##InitClass(void);                \
  77.  struct Class##DataStruct {                         \
  78.   Base base;
  79.  
  80. #define END_MEMBERS };
  81.  
  82. /* Begin class type definition: */
  83. #define DEF_CLASS(Class,Base)                              \
  84.  Class##Methods Class##Table = { 0, 0 };                   \
  85.  int Class##_isA(const char *className) {                  \
  86.   int yes= !strcmp(#Class,className);                      \
  87.   if (!yes)                                                \
  88.    yes = ((ObjectMethods*)(&Base##Table))->isA(className); \
  89.   return yes;                                              \
  90.  }                                                         \
  91.  void Class##_destroy(void) {                              \
  92.   Class##_destruct();                                      \
  93.   ((ObjectMethods*)(&Base##Table))->destroy();             \
  94.  }                                                         \
  95.  void Class##InitClass(void) {                             \
  96.   ObjectMethods *objTable= (ObjectMethods*)&Class##Table;  \
  97.   Base##Methods *baseTable= (Base##Methods*)&Class##Table; \
  98.   Base##InitClass();                                       \
  99.   if (objTable->initialized)                               \
  100.    return;                                                 \
  101.   *baseTable = Base##Table;                                \
  102.   objTable->name = #Class;                                 \
  103.   REDEF_METHOD(Class,Object,isA);                          \
  104.   REDEF_METHOD(Class,Object,destroy);
  105.  
  106. /* Set and reset methods within a class definition: */
  107. #define DEF_ABSTRACT(Base,Method) \
  108.  (Base##Table.Method = 0)
  109. #define DEF_METHOD(Base,Method) \
  110.  (Base##Table.Method = Base##_##Method)
  111. #define REDEF_METHOD(Class,Base,Method)       \
  112.  (((Base##Methods *)(&Class##Table))->Method  \
  113.   = Class##_##Method)
  114.  
  115. /* End class type definition: */
  116. #define END_CLASS }
  117.  
  118. /* Initialize a class before use: */
  119. #define USE(Class) Class##InitClass()
  120.  
  121. /* Begin class method implementation: */
  122. #define METHOD(Class,Name,Arguments,Return) \
  123.  Return Class##_##Name Arguments {          \
  124.   Class *this = POP_THIS_SAFE(Class);
  125.  
  126. /* End class method implementation: */
  127. #define END_METHOD }
  128.  
  129. /* Begin class constructor implementation: */
  130. #define CONSTRUCTOR(Class,Arguments) \
  131.  void Class##_construct Arguments {  \
  132.   Class *this= GET_THIS(Class);      \
  133.   ObjectMethods *Methods=            \
  134.    (ObjectMethods *)&Class##Table;
  135.  
  136. /* Must construct Base first in class constructor: */
  137. #define CONSTRUCT(Base,Arguments)       \
  138.  Base##_construct Arguments;            \
  139.  ((Object *)this)->methods = Methods; {
  140.  
  141. /* End class constructor implementation: */
  142. #define END_CONSTRUCTOR }}
  143.  
  144. /* Begin class destructor implementation: */
  145. #define DESTRUCTOR(Class)             \
  146.  void Class##_destruct(void) {        \
  147.   Class *this = GET_THIS_SAFE(Class); \
  148.   ((Object *)this)->methods =         \
  149.    (ObjectMethods *)&Class##Table; {
  150.  
  151. /* End class destructor implementation: */
  152. #define END_DESTRUCTOR }}
  153.  
  154. /* Monomorphic access to a method of a class: */
  155. #define CALL(pObj,Class,Base,Name,Arguments)         \
  156.  ((PUSH_THIS(pObj),                                  \
  157.   (Base##Methods *)(&Class##Table))->Name Arguments  \
  158.  )
  159.  
  160. /* Polymorphic access to a method of a class: */
  161. #define SEND(pObj,Base,Name,Arguments)         \
  162.  (((Base##Methods*)                            \
  163.   (PUSH_THIS(pObj)->methods))->Name Arguments)
  164.  
  165. /* Construct a new object on the heap: */
  166. #define NEW(Class,Arguments)          \
  167.  (PUSH_THIS(malloc(sizeof(Class)))),  \
  168.   Class##_construct Arguments,        \
  169.   POP_THIS_SAFE(Class)))
  170.  
  171. /* Construct a new object on the stack: */
  172. #define PUSH(ObjName,Class,Arguments) \
  173.  Class auto_##ObjName;                \
  174.  Class *ObjName = (Class*)            \
  175.   (PUSH_THIS(&auto_##ObjName),        \
  176.    Class##_construct Arguments,       \
  177.    POP_THIS_SAFE(Class))
  178.  
  179. /* Destroy an object on the heap: */
  180. #define DELETE(pObj) \
  181.  (SEND(pObj,Object,destroy,()), free(POP_THIS())
  182.  
  183. /* Destroy an object on the stack: */
  184. #define POP(pObj) SEND(pObj,Object,destroy, ())
  185.  
  186. /* Test whether object is a member of named class: */
  187. #define IS_A(pObj,Class) \
  188.  ((((Object *)pObj)->methods)->isA(#Class))
  189.  
  190. /* Access to the class name of an object: */
  191. #define CLASS_NAME(pObj) \
  192.  (((ObjectTable*)(((Object *)(pObj))->methods))->name)
  193.  
  194. #else /* C++ */
  195.  
  196. /* Base class for all objects: */
  197. struct Object {
  198.   virtual int isA(const char *className);
  199.   virtual const char *classname();
  200. };
  201.  
  202. /* Begin class methods declaration: */
  203. #define DCL_METHODS(Class,Base,ConstructorArguments) \
  204.  struct Class : Base {                               \
  205.     Class ConstructorArguments;                      \
  206.     virtual ~Class();                                \
  207.     virtual int isA(const char *className);          \
  208.     virtual const char *classname();
  209.  
  210. /* Declare and redeclare methods: */
  211. #define DCL_METHOD(Name,Arguments,Return) \
  212.  virtual Return Name Arguments
  213. #define DCL_ABSTRACT(Name,Arguments,Return) \
  214.  virtual Return Name Arguments=0
  215. #define REDCL_METHOD(Name,Arguments,Return) \
  216.  virtual Return Name Arguments
  217.  
  218. /* End class methods declaration: */
  219. #define END_METHODS
  220.  
  221. /* Begin class members declaration: */
  222. #define DCL_MEMBERS(Class,Base)
  223.  
  224. /* End class type declaration: */
  225. #define END_MEMBERS };
  226.  
  227. /* Begin class type definition: */
  228. #define DEF_CLASS(Class,Base)                       \
  229.  const char *Class::classname() {                   \
  230.   return #Class;                                    \
  231.  }                                                  \
  232.  int Class::isA(const char *className) {            \
  233.   if (strcmp(#Class,className))                     \
  234.    return Base::isA(#Class);                        \
  235.   return 1;                                         \
  236.  }                                                  \
  237.  
  238. /* Set and reset methods within a class definition: */
  239. #define DEF_ABSTRACT(Base,Method)
  240. #define DEF_METHOD(Base,Method)
  241. #define REDEF_METHOD(Class,Base,Method)
  242.  
  243. /* End class type definition: */
  244. #define END_CLASS
  245.  
  246. /* Initialize a class before use: */
  247. #define USE(Class)
  248.  
  249. /* Begin class method implementation: */
  250. #define METHOD(Class,Name,Arguments,Return) \
  251.  Return Class::Name Arguments {
  252.  
  253. /* End class method implementation: */
  254. #define END_METHOD }
  255.  
  256. /* Begin class constructor implementation: */
  257. #define CONSTRUCTOR(Class,Arguments) Class::Class Arguments:
  258.  
  259. /* Must construct Base first in class constructor: */
  260. #define CONSTRUCT(Base,Arguments) Base Arguments {
  261.  
  262. /* End class constructor implementation: */
  263. #define END_CONSTRUCTOR }
  264.  
  265. /* Begin class desstructor implementation: */
  266. #define DESTRUCTOR(Class) Class::~Class() {
  267.  
  268. /* End class destructor implementation: */
  269. #define END_DESTRUCTOR }
  270.  
  271. /* Monomorphic access to a method of a class: */
  272. #define CALL(pObj,Class,Base,Name,Arguments) \
  273.  (pObj->Class::Name Arguments)
  274.  
  275. /* Polymorphic access to a method of a class: */
  276. #define SEND(pObj,Base,Name,Arguments) \
  277.  (pObj->Name Arguments)
  278.  
  279. /* Construct a new object on the heap: */
  280. #define CREATE(Class) new Class
  281.  
  282. /* Construct a new object on the stack: */
  283. #define PUSH(ObjName,Class,Arguments) \
  284.  Class auto##ObjName Arguments;       \
  285.  Class *ObjName= &auto##ObjName
  286.  
  287. /* Destroy an object on the heap: */
  288. #define DELETE(pObj) \
  289.  delete(pObj)
  290.  
  291. /* Destroy an object on the stack: */
  292. #define POP(pObj)
  293.  
  294. /* Test whether object is a member of named class: */
  295. #define IS_A(pObj,className) \
  296.  SEND(pObj,Object,isA,(className))
  297.  
  298. /* Access to the class name of an object: */
  299. #define CLASS_NAME(pObj) (pObj->classname())
  300.  
  301. #endif /* C vs. C++ */
  302.  
  303. #endif
  304.