home *** CD-ROM | disk | FTP | other *** search
- ******************************************************************************
- *
- * lclptr.checker
- *
- * Copyright (C) 1989 by Apple Computer.
- * Written by Eric Soldan.
- *
- * Converted to APW 6-May-90 DAL
- *
- ******************************************************************************
-
- case on
-
- rtlStkDepth gequ 50 ;You may need to make this bigger.
-
- ******************************************************************************
- *
- * These functions are to help detect usage of C pointers and handles that are
- * not initialized. In main(), call initPtrCheck(). Do NOT call other
- * functions in main.
- *
- * In other functions, call zapLocals() as the first thing in the function.
- * checkForHit() will automatically be called whenever you exit a function.
- * You can call checkForHit() at any point you want, also. If you have an idea
- * of which function has a pointer problem, but you are not sure where in
- * the function the problem is, you can add some calls to checkForHit().
- * The functions initPtrCheck(), closePtrCheck(), zapLocals(), and
- * checkForHit() can be conditionally set active or inactive with #define
- * statements. This way they can be active when developing, and turned off
- * when making a production version. The calls can be defined to nothing,
- * thus making any reference to them drop out of the object code.
- *
- * So, a C program would use the functions as below:
- *
- * main()
- * {
- * initPtrCheck(_ownerid);
- * /* Your code goes here */
- * closePtrCheck();
- * exit(0);
- * }
- *
- * void someFnCalledByMain(parm1, parm2)
- * unsigned int parm1, parm2;
- * {
- * unsigned int i, j, k;
- * unsigned long theID;
- *
- * zapLocals();
- * /* Your code goes here */
- * checkForHit();
- * }
- *
- * Note that zapLocals() needs to be the first code in a function. Also,
- * you can't call zapLocals before you call initPtrCheck(). Given this
- * dependency, you can't call zapLocals in main(). To fix this problem,
- * you may wish to have a nearly empty main(). You may want it to just
- * do the initPtrCheck() and closePtrCheck(), and the code in between
- * simply calls something like main0(), which can have a zapLocals().
- *
- ******************
-
- * The return address to exit zapLocals is used to point to the code used to
- * create the stack frame. The stack frame code should look like the below.
- * The values in front are the negative offsets from the return address.
- * (This is why zapLocals() must be the first code in a function.)
-
- * E PHD
- * D TSC
- * C SEC
- * BA9 SBC #$fb
- * 8 TCD
- * 765 ADC #$f0
- * 4 TCS
- *
- * 321.0 JSL >zapLocals
-
- ******************************************************************************
-
- mcopy 2/ainclude/m16.memory
- mcopy 2/ainclude/m16.misctool
- mcopy 2/ainclude/m16.util2
-
-
- initPtrCheck start
-
- DefineStack
-
- hndl long ;Must be at 1,s.
- ptr long
-
- dpage word
- retaddr block 3
-
- userid word
-
- phd
-
- pha ;Make space for locals.
- pha
- pha
- pha
- tsc
- tcd
-
- pea 1 ;Get the bank-sized handle.
- lda #0
- sta >rtlStkPtr ;Nothing on "stack" yet.
- pha
- pei userid
- pea $C010
- pha
- pha
- _NewHandle
- bcc gothndl
-
- lda #0
- sta >ptrCheckHndl ;Flag as no handle.
- sta >ptrCheckHndl+2
- sta >zapval ;"Pattern" is 0.
- sta >$0 ;Point 0-2 to the screen.
- lda #$E100 ;If there is any bad stuff
- sta >$1 ;going on, then it will show
- bra exit1 ;on the super-hi-res screen.
- * ;This is true only for handles.
- * ;Simple pointers will still
- * ;store into zpage. Storing
- * ;into zpage will, most likely,
- * ;cause the system to die.
- * ;The best test is when the
- * ;system has enough memory to
- * ;create the 64k hit-test handle.
-
- gothndl lda hndl ;Keep the handle, and initialize it.
- sta >ptrCheckHndl
- lda hndl+2
- sta >ptrCheckHndl+2
-
- ldy #2 ;Dereference the handle to get to
- lda [hndl],y ;the bank of memory.
- sta ptr+2
- lda [hndl]
- sta ptr
- lda ptr+2 ;Move byte 2 of bank address into
- xba ;byte 3 also.
- ora ptr+2
- sta >zapval
-
- ldy #0 ;Fill the handle with the bank value,
- loop sta [ptr],y ;so pointers within the handle end
- iny ;up pointing back into the handle.
- iny
- bne loop
-
- sta >$0
- sta >$2
-
- exit1 pla
- pla
- pla
- pla
-
- pld
- rtl
-
- ptrCheckHndl entry
- dc i4'0'
- zapval entry
- dc i2'0'
- rtlStkPtr entry
- dc i2'0'
- rtlStk entry
- ds rtlStkDepth*3
-
- end
-
- ******************
-
- zapLocals start
-
- DefineStack
-
- ptr long
-
- dpage word
- retaddr block 3
-
- phd
-
- pha ;Make space for locals.
- pha
- tsc
- tcd
-
- lda retaddr+1 ;Use return address as pointer.
- sta ptr+1
- lda retaddr
- sec
- sbc #$0A
- sta ptr
- lda [ptr] ;sbc value
- tax
- ldy #4
- lda [ptr],y ;adc value
-
- sta ptr
- txa
- sec
- sbc ptr
- beq exit2 ;No stack frame at all.
- tax ;Save this to fetch RTL address.
- tay ;Number of bytes to zap.
- dey
- beq exit2 ;Just in case.
-
- tsc
- clc
- adc #retaddr+2 ;Point to beginning of stack
- sta ptr ;frame to clobber.
- stz ptr+2
-
- shortm
- lda >zapval ;Pattern to clobber with.
- loop2 sta [ptr],y
- dey
- bne loop2
- longm
-
- inx ;Save the return address on rtlStk.
- inx
- txy ;yreg is offset to return address.
- lda >rtlStkPtr
- cmp #rtlStkDepth*3 ;Make sure we aren't overflowing rtlStk.
- bcc stackOK
- brk $AA
-
- stackOK tax
- lda [ptr],y
- sta >rtlStk,x
- iny
- inx
- lda [ptr],y
- sta >rtlStk,x ;Return address now on rtlStk.
- inx
- inx
- txa
- sta >rtlStkPtr ;Save new index into rtlStk.
-
- lda #rtlCheck|-8 ;Put return address of checking
- sta [ptr],y ;routine in place of regular
- dey ;return address.
- lda #rtlCheck-1
- sta [ptr],y
-
- exit2 pla
- pla
-
- pld
- rtl
-
- rtlCheck anop ;This is where we end up when a c
- * ;function exits with an rtl.
- jsl saveRegs ;Keep registers for return value for c.
-
- lda >rtlStkPtr ;Get the real return address onto the stack.
- tax
- dex
- dex
- lda >rtlStk,x
- pha ;We pushed middle and hi byte here.
- phb
- pla ;We just pulled the middle byte.
- dex
- lda >rtlStk,x
- pha ;We pushed low and middle byte here, so
- * ;we have a full rtl address on stack.
- txa
- sta >rtlStkPtr
- jml checkForHitz
-
- saveRegs entry
- sta >keepa ;Keep everything.
- txa
- sta >keepx
- tya
- sta >keepy
- php
- php
- pla
- sta >keepp
- rtl
-
- getRegs entry
- lda >keepp
- pha
- lda >keepx
- tax
- lda >keepy
- tay
- lda >keepa
- plp
- plp
- rtl
-
- keepa dc i2'0'
- keepx dc i2'0'
- keepy dc i2'0'
- keepp dc i2'0'
-
- end
-
- ******************
-
- checkForHit start
-
- jsl saveRegs
-
- checkForHitz entry
- lda >zapval
- beq exit3 ;When using zpage as hit
- * ;detector, there is nothing
- * ;we can check. We just have
- * ;to wait until the system
- * ;dies a horrible death. This
- * ;horrible death should happen
- * ;faster when clobbering zpage.
- tax
- and #$FFFE ;So we can go by words.
- tay
- txa
-
- phb
- pha
- plb
- plb
-
- loop3 cmp |$0,y
- bne oops1
- iny
- iny
- bne loop3
-
- plb ;Put data bank back.
- exit3 jml getRegs
-
- oops1 plb
-
- brk $AB ;Bank is indicated by acc.
- * ;Offset into bank that was hit is
- * ;in the yreg.
- * ;The program can be resumed, but unless
- * ;the hit is repaired, the program will
- * ;break again.
-
- jml getRegs ;Allow option of continuing from debugger.
-
- end
-
- ******************
-
- closePtrCheck start
- jsl checkForHit ;Let's make sure there were no hits.
-
- lda >zapval
- beq exit ;No handle to dispose of.
-
- lda >ptrCheckHndl+2
- pha
- lda >ptrCheckHndl
- pha
- _DisposeHandle ;We got rid of what we created.
-
- lda #0
- sta >zapval
-
- exit rtl
-
- end
-