home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / sys / mac / programm / 14002 < prev    next >
Encoding:
Text File  |  1992-08-14  |  7.8 KB  |  293 lines

  1. Path: sparky!uunet!zephyr.ens.tek.com!shaman!pogo!jonh.wv.tek.com!user
  2. From: jonh@pogo.wv.tek.com (Jon Howell)
  3. Newsgroups: comp.sys.mac.programmer
  4. Subject: Re: Think C Debugger & Class dynamic typing... summary
  5. Message-ID: <jonh-140892100942@jonh.wv.tek.com>
  6. Date: 14 Aug 92 17:16:38 GMT
  7. References: <jonh-130892150657@jonh.wv.tek.com>
  8. Sender: nobody@pogo.wv.tek.com
  9. Followup-To: comp.sys.mac.programmer
  10. Organization: Tektronix
  11. Lines: 280
  12.  
  13. [summary]
  14. In article <jonh-130892150657@jonh.wv.tek.com>, jonh@pogo (that's me!)
  15. asked:
  16. > When you look
  17. > at a CObject in the Data window of the debugger, and dereference it to open
  18. > up a view of the object's structure, it views the object as though it were
  19. > the type it's declared as in the context. Why can't/doesn't it use the type
  20. > the object *really* is?  For example:
  21. > {
  22. >    CView *hokey;
  23. >    hokey = new CWindow;
  24. >    hokey ->IWindow(blah blah blah);
  25. > <> hokey ->Update();
  26. > }
  27. [I forgot to cast hokey above to make the method lookups work. I need a
  28.  newsreader with a built-in precompiler. :v]
  29. I also knew I could examine hokey in the debugger as a CWindow with:
  30.        *(CWindow *) hokey
  31. However, I really wish the debugger could do that on its own.
  32. Per Mildner <Per.Mildner@csd.uu.se> points out that
  33.  
  34. PM>There is a macro you can use in the debugger that tells you the class
  35. PM>name of an object as a string. I don't remember the name but it starts
  36. PM>with two (or possibly one) underscore. It's in the documentation
  37. PM>somewhere.
  38.  
  39. This would come in handy when you don't know just what hokey is at the
  40. moment, so you could look it up to do the cast.
  41.  
  42. > Another question: TC provides member() and class_name() (and another I
  43. > forget) functions for figuring out the dynamic type of an object. I'd
  44. > like to be able to see if an object I've been passed is of a certain
  45. > type. However, I don't want to do a string compare (class_name), and
  46. > member() seems to only tell me if the object is a member of class X or
  47. > one of its ancestors.  Is there a way I can get an integer which
  48. > uniquely identifies the class? (It'd be extra cool if it gave some info on
  49. > the hierarchy, but... :v)
  50. To which markw@wc.novell.COM (Mark Wittenberg) responded to in the best
  51. way -- with code! I'll include his message with a minimum of butchering
  52. here. Thanks to you two and d88-jwa@nada.kth.se for the replies.
  53.  
  54. ----- snip here -----
  55. OK, there is a way.  Here are class.h and class.c that do that and more.
  56. GetClassID does what you want, and there are several other very useful
  57. routines as well.  You can just use Think's "__class" call directly if
  58. that's really all that you want (I indicate "not a class" with an id
  59. of -1 rather than Think's 0).
  60.  
  61. Note that MapClassNameToID is code largely ripped from oops.c, and this
  62. code uses unsupported and undocumented features of v5.0.2 (translation:
  63. I carefully studied oops.h and dug through memory a lot); I've been using
  64. it a long and it's been very solid for me, but caveat emptor.
  65.  
  66. NewObjectByClassId is particularly nice because it's noticeably faster
  67. than new_by_name.
  68.  
  69. /markw
  70.  
  71. ---------------- class.h ----------------------
  72. /*
  73.  * Class.h
  74.  *      - Class ID declarations
  75.  *
  76.  * Copyright 1991 Mark Wittenberg
  77.  */
  78.  
  79. #pragma once
  80.  
  81. #include <CObject.h>
  82.  
  83. #define kNilClass       (-1)
  84.  
  85. typedef Str255  MAName;
  86. typedef int             ObjClassID;
  87.  
  88. ObjClassID      GetClassID(CObject *theObject);
  89. void            GetClassName(CObject *obj, MAName theName);
  90. void            GetClassNameFromID(ObjClassID id, MAName theName);
  91. ObjClassID      GetClassIDFromName(const MAName theName);
  92. ObjClassID      MapClassNameToID(const MAName theName);
  93. void            *NewObjectByClassId(ObjClassID currentID);
  94.  
  95. ---------------- class.c ----------------------
  96. /*
  97.  * Class.c
  98.  *      - Class ID routines
  99.  *
  100.  * Copyright 1991 Mark Wittenberg
  101.  */
  102.  
  103. #define OOPS_PRIVATE
  104. #include "Oops.h"               // change case so that <TCL Headers>
  105. doesn't mess us up
  106. #define INDIRECT
  107. #ifdef INDIRECT
  108.         #define __new __new_indirect
  109. #else
  110.         #define __new __new_direct
  111. #endif
  112.  
  113. extern void *__new(...);
  114.  
  115. #if __option(far_code) || __option(far_data)
  116.         ERROR - We assume 2-byte IDs!
  117. #endif
  118.  
  119. #include "Class.h"
  120.  
  121. /*
  122.  * GetClassID
  123.  *      - Return the class id of an object.
  124.  */
  125. ObjClassID
  126. GetClassID(CObject *obj)
  127. {
  128.         ObjClassID      id;
  129.         
  130.         id = (ObjClassID) __class(obj);
  131.         return (id == 0) ? kNilClass : id;
  132. } /* GetClassID */
  133.  
  134. /*
  135.  * GetClassName
  136.  */
  137. void
  138. GetClassName(CObject *obj, MAName theName)
  139. {
  140.         unsigned char   *name;
  141.         
  142.         theName[0] = '\0';
  143.         name = (unsigned char *) class_name(obj);
  144.         if( name )
  145.                 BlockMove( name, theName, name[0] + 1 );
  146. } /* GetClassName */
  147.  
  148. /*
  149.  * GetClassNameFromID
  150.  */
  151. void
  152. GetClassNameFromID(ObjClassID id, MAName theName)
  153. {
  154.         unsigned char   *name;
  155.                 
  156.         theName[0] = '\0';
  157.         name = (unsigned char *) __class_name(id);
  158.         if( name )
  159.                 BlockMove( name, theName, name[0] + 1 );
  160. } /* GetClassNameFromID */
  161.  
  162. /*
  163.  * GetClassIDFromName
  164.  */
  165. ObjClassID
  166. GetClassIDFromName(const MAName theName)
  167. {
  168.         ObjClassID      id;
  169.         
  170.         id = MapClassNameToID( theName );
  171.         return (id == 0) ? kNilClass : id;
  172. } /* GetClassIDFromName */
  173.  
  174. /*
  175.  * MapClassNameToID
  176.  */
  177. ObjClassID
  178. MapClassNameToID(const MAName theName)
  179. {
  180.         struct { void *min, *max; } range;
  181.         register void *p, *q;
  182.  
  183.         asm {
  184.  
  185. ;;
  186. ;
  187. ;  establish search range
  188. ;
  189. ;;
  190.  
  191. #if __option(a4_globals)
  192.                 movea.l a4,a0
  193.                 _RecoverHandle
  194.                 _GetHandleSize
  195.                 move.l  a4,range.min
  196.                 add.l   a4,d0
  197.                 move.l  d0,range.max
  198. #else
  199.                 move.l  CurStackBase,range.min
  200.                 move.l  a5,range.max
  201. #endif
  202.  
  203. ;;
  204. ;
  205. ;  search data area for matching name (this could probably be improved)
  206. ;
  207. ;;
  208.  
  209.                 movea.l range.min,p
  210.                 movea.l theName,q
  211.                 move.w  (q)+,d1                                 ;  D1.W =
  212. 1st two bytes of name
  213. @1              cmp.w   (p)+,d1
  214.                 beq.s   @2
  215.                 cmpa.l  range.max,p
  216.                 blo.s   @1
  217. ;
  218.                 moveq   #0,d0                                   ;  search
  219. failed
  220.                 return
  221. ;
  222. @2              movea.l p,a0
  223.                 movea.l q,a1
  224.                 bra.s   @4
  225. @3              cmpm.b  (a0)+,(a1)+
  226.                 bne.s   @1                                              ; 
  227. name not found - keep looking
  228. @4              tst.b   -1(a1)
  229.                 bne.s   @3
  230.  
  231. ;;
  232. ;
  233. ;  verify we've found a class info record
  234. ;
  235. ;;
  236.  
  237.                 moveq   #~1,d0
  238.                 and.w   -4(p),d0
  239.                 lea             -4(p,d0.w),a0                   ;  A0 ==>
  240. dispatch table
  241.                 cmpa.l  range.min,a0
  242.                 blo.s   @1                                              ; 
  243. out of range - try again
  244.                 cmpa.l  range.max,a0
  245.                 bhs.s   @1                                              ; 
  246. out of range - try again
  247. ;
  248.                 moveq   #1,d0
  249.                 add.w   (a0),d0
  250.                 lsl.w   #DSHIFT,d0
  251.                 lea             ClassInfo_(name[2])+2(a0,d0.w),a1
  252.                 cmpa.l  p,a1
  253.                 bne.s   @1                                              ; 
  254. sanity check failed - try again
  255.  
  256. ;;
  257. ;
  258. ; now a0 points to the dispatch table
  259. ;
  260. ;;
  261.                 move.l  a0,d0
  262.         #ifdef BASE_REG
  263.                 sub.l   BASE_REG,d0
  264.         #endif
  265.                 return
  266.         }
  267. } /* MapClassNameToID */
  268.  
  269. /*
  270.  * NewObjectByClassId
  271.  */
  272. void *
  273. NewObjectByClassId(ObjClassID id)
  274. {
  275.         void    *cptr;
  276.         
  277.         asm {
  278.                 move.w  id,d0
  279.                 ext.l   d0
  280.         #ifdef BASE_REG
  281.                 add.l   BASE_REG,d0
  282.         #endif
  283.                 move.l  d0,cptr
  284.         }
  285.         return __new( cptr );
  286. } /* NewObjectByClassId */
  287. -- 
  288.  
  289. -----------------------------------------------------------------------------
  290. jonh@pogo.wv.tek.com     Jon Howell
  291.