CompuServe Messages

#Code Segment Mgmt …

    19-Jul-93 16:53:29
Sb: #Code Segment Mgmt …
Fm: Joe Terry |Manhattan| 72130,2100
To: ALL
Hi y'all, The following code is used to manage code segment traffic in a large THINK C with objects application. We use the TCL and the Prepare() class libraries. I would like anyone's comments on this code. Anything appreciated. Your payment in full is the code itself. Please maintain the copyright notice. The usage is to make a call like this … void main() … InitSegmentMgr(); … ) // end main() and then else where when the mood hits … UnloadSegment( Routine_In_Segment_Name ); Thanks, // joe /* * SegmentMgr.c – routines for managing code segments * * Copyright ~ 1991 Christopher R. Wysocki. All rights reserved. * */ // #include "SegmentMgr.h" #define __DEBUG__ static long gOrigA6; /* * InitSegmentMgr * * Initialize our segment manager. * This routine should be called as the first function in main(). */ void InitSegmentMgr(void); void InitSegmentMgr(void) { asm { move.l a6,gOrigA6 ; save initial value of a6 } } /* * UnloadSegment * * Call this routine instead of the Toolbox routine _UnloadSeg to unload * a segment. This routine walks through the A6 chain to ensure that no * routine in the segment to be unloaded is in the current calling chain. * */ void UnloadSegment(void *routineAddr); void UnloadSegment(void *routineAddr) { asm { movem.l a3-a4,-(a7) ; save registers on stack movea.l routineAddr,a0 ; get pointer to jump table entry cmpi.w #0xA9F0,4(a0) ; is the segment loaded? beq @4 ; go return if not subq.w #4,a7 ; space for result pea 'CODE' ; push resource type move.w -2(a0),-(a7) ; push segment number (resource ID) _GetResource ; get the appropriate CODE resource move.l (a7)+,a0 ; pop the resource handle #ifdef __DEBUG__ cmpa.l #0,a0 ; is the handle nil? bne.s @0 ; branch if not pea @cantLoadCODERsrc ; push pointer to message _DebugStr ; drop into Macsbug bra.s @4 ; and go return @cantLoadCODERsrc: dc.b "\pUnloadSegment: can't load CODE resource!" @0 #endif move.l (a0),d0 ; get master pointer _StripAddress ; strip off high byte if in 24-bit mode movea.l d0,a3 ; save ptr to start of block in a3 _GetHandleSize ; get size of CODE resource handle movea.l a3,a4 ; keep block ptr in a4 adda.l d0,a4 ; add length to get ptr to byte after block movea.l a6,a1 ; a1 walks through the a6 calling chain @1 cmpa.l gOrigA6,a1 ; are we at the end of the calling chain? beq.s @3 ; exit loop if so move.l 4(a1),d0 ; get return address _StripAddress ; strip off high byte if in 24-bit mode cmp.l a3,d0 ; check if this address is in the segment blo.s @2 ; that we want to unload — if it is, cmp.l a4,d0 ; exit the loop without unloading the blo.s @4 ; segment @2 movea.l (a1),a1 ; the return address isn't in the segment, bra.s @1 ; so get previous contents of a6 and loop @3 move.l routineAddr,-(a7) ; push pointer to routine _UnloadSeg ; unload the segment @4 movem.l (a7)+,a3-a4 ; restore registers from stack } }