📄 txtmgr.asm
字号:
;
; When all pcode references to a prs have been deleted,
; and the prs has no text table, PrsFree is called to remove the entry.
;
; The management of "defining" references happens in two stages during
; an edit. When a "defining" reference is deleted, prs.otxDef is set
; to undefined by UndefPrs. At the end of the edit operation, RedefOrDelPrs
; is called to search for a new "defining" reference, or free the prs.
;
; This is done in two stages as a speed optimization for text edits.
; This will help speed up the cases where you are discarding text
; tables, or terminating ASCII load because of an out of memory error.
; This way we accumulate and process all prs defining reference changes
; at one time.
;
; Call Trees
; ==========
;
; Deleting a defining reference
; -----------------------------
; MrsDiscard PrsDiscard
; \ /
; \ /
; TxtDiscard ParseLine
; | |
; TxtDelete ParseUndo MakeProc (when renaming a sub/function)
; | | |
; ForEachPrsInPlaceCP(UpdatePrs) | |
; | | |
; +------+----+
; |
; UndefPrs
;
; End of edit - find new defining reference
; -----------------------------------------
; TxtChange LoadFile
; | |
; | |
; | |
; | MrsDiscard PrsDiscard
; | | \ / |
; | | PrsDiscard1 |
; | | |
; +-------------+------------------+
; |
; ChkAllUndefPrs
; |
; --------
; | |
; |
; ForEachCP(TryToDefPrs)
;
;--------------------------------------------------------------------
sBegin DATA
;** the static structure uPrs is defined in SetPrsDefn header
DPRS_ST STRUC
DPRS_oRs DW 1 DUP (?)
DPRS_oMrs DW 1 DUP (?)
DPRS_otx DW 1 DUP (?)
DPRS_flags DB 1 DUP (?)
DPRS_ST ENDS
dprs DB size DPRS_ST DUP (?)
;** the static structure uPrs is defined in UpdatePrs's header
UPRS_ST STRUC
UPRS_oRsEdit DW 1 DUP(?)
UPRS_otxEdit DW 1 DUP(?)
UPRS_cbDel DW 1 DUP(?)
UPRS_cbIns DW 1 DUP(?)
UPRS_oPrsDel DW 1 DUP (?)
UPRS_fPrsDelFound DW 1 DUP (?)
UPRS_fNoRefSameMod DW 1 DUP (?)
UPRS_oMrsRefDel DW 1 DUP (?)
UPRS_ST ENDS
uprs DB size UPRS_ST DUP (?)
sEnd DATA
sBegin CP
assumes cs,CP
;**************************************************************
; void SetPrsDefn
; Purpose:
; Called when a prs reference is inserted in pcode. If this is the
; "most powerful" definition we've seen so far for the current prs,
; the the prs entry is changed to remember this text offset
; as the "defining" reference.
;
; Entry:
; dprs.DPRS_oRs,oMrs,otx identify where in the pcode
; the reference lives.
; dprs.DPRS_flags = FP_DEFINED if this is for a SUB/FUNCTION/DEF FN stmt.
; = FP_DECLARED if this is for a DECLARE stmt.
; = 0 if this is for a CALL stmt.
; grs.oPrsCur identifies the prs being referenced.
;
;**************************************************************
SetPrsDefn PROC NEAR
test [dprs.DPRS_flags],FP_DEFINED
jne SpNewDef ;brif reference is SUB,FUNC,DEF FN stmt
test [prsCur.PRS_flags],FP_DEFINED
jne SpNoNewDef ;brif prs is already defined by SUB,...
test [dprs.DPRS_flags],FP_DECLARED
jne SpNewDef ;brif reference is DECLARE
test [prsCur.PRS_flags],FP_DECLARED
jne SpNoNewDef ;brif prs is already declared
SpNewDef:
;Got a SUB, FUNCTION or DEF FN OR
; a DECLARE for prs with no definition OR
; a CALL to an as yet undeclared, undefined SUB.
; This is the "most powerful" reference seen so far,
; make this text reference the new owner of the prs entry.
; We need to set prsCur.oMrs even though in most cases, it
; is redundant given prsCur.oRsDef. The case where it is
; valuable info is for DECLAREd prs's with no text tables.
; If it were not set here, there would be cases when ForEachPrsInMrs
; would not pick up this prs
mov ax,[dprs.DPRS_oRs]
mov [prsCur.PRS_oRsDef],ax
mov ax,[dprs.DPRS_otx]
mov [prsCur.PRS_otxDef],ax
mov al,[dprs.DPRS_flags]
or [prsCur.PRS_flags],al
test [txdCur.TXD_flags],FTX_mrs
je SpNoNewDef ;brif prs has text table
;If we didn't, commenting out
;a SUB stmt would move the prs to
;another module.
mov ax,[dprs.DPRS_oMrs]
mov [prsCur.PRS_oMrs],ax
cmp [prsCur.PRS_procType],PT_DEFFN
jne SpNoNewDef ;brif not a DEF FN
mov [prsCur.PRS_oRsDef],ax ;for DEF FNs, the oRsDef is the
; module's text table.
SpNoNewDef:
ret
SetPrsDefn ENDP
;**************************************************************
; boolean TryToDefPrs()
; Purpose:
; Called to see if current text table contains any references
; to prs uprs.UPRS_oPrsDel.
;
; Entry:
; uprs.UPRS_oPrsDel is the prs whose reference has been deleted
;uprs.UPRS_oMrsRefDel is the mrs from which the reference was deleted
;uprs.UPRS_fNoRefSameMod: if TRUE then TryToDefPrs must search for
; a reference to oPrsDel in text tables of module oMrsDel.
;dprs.DPRS_flags: if set to 0 then TryToDefPrs must search for any
; ref's to oPrsDel.
; Exit:
;uprs.UPRD_fNoRefSameMod is set to FALSE if it is TRUE on entry and
; the text table being searched is in module uprs.UPRS_oMrsRefDel
; and a ref to procedure uprs.UPRS_oPrsDel is found.
; uprs.UPRS_fPrsDelFound = TRUE if any other references were found
; if a "defining" reference is found (i.e. anything but a CALL),
; dprs.DPRS_oRs,otx are set to identify the text table and text
; offset for the new "defining" reference.
;dprs.DPRS_flags is set to FP_DECLARED if a DECLARE for the deleted
; Prs is found.
;FALSE is returned when no more searching is required, i.e. when
; dprs.DPRS_flags = FP_DECLARED and uprs.UPRS_fNoRefSameMod
; is FALSE.
;
;
;**************************************************************
TryToDefPrs PROC NEAR
push si ;save caller's si,di
push di
cmp [txdCur.TXD_ScanState],SS_SUBRUDE
je JE_TryDone ;
mov di,[uprs.UPRS_fNoRefSameMod]
or di,di
jz TrySearch ;brif already found another ref
; to the proc in the module with
; the deleted reference
mov di,[uprs.UPRS_oMrsRefDel] ;di = oMrs of module from which
; a reference was deleted
sub di,[grs.GRS_oMrsCur] ;di = 0 iff the text table is in
; the same module as the text tbl
; from which a ref was deleted
jz TrySearch ;brif in same module as deleted ref
test [dprs.DPRS_flags],FP_DECLARED
jnz TryDone ;exit if we don't need to search
; this text table for a declare
TrySearch:
call TxtDescanCP ;descan current txt tbl to SS_PARSE
sub ax,ax
push ax
PUSHI ax,<CODEOFFSET tOpPrsDef>
call TxtFindOp ;ax = offset to 1st opcode in cur text
; table with prs operand
;dl = [txtFindIndex]
TryLoop:
mov si,ax ;si = otxCur
cmp dl,PRSDEF_opEot
JE_TryDone:
je TryDone ;brif done with text table
add ax,4 ;advance to oPrs operand
cmp dl,PRSDEF_opStDefFn
jne TryNotDefFn ;brif ref is not a DEF FN
inc ax ;skip DEF FN's link field
inc ax
TryNotDefFn:
call GetWOtx ;ax = oPrs of reference (ax)
cmp ax,[uprs.UPRS_oPrsDel]
jne TryNext ;brif not ref to prs of interest
mov [uprs.UPRS_fNoRefSameMod],di ;set flag indicating whether
; or not another ref was found
; in module of deleted ref
test [dprs.DPRS_flags],FP_DECLARED
jnz TryExit1 ;brif not searching for defining ref
mov [uprs.UPRS_fPrsDelFound],sp
;tell caller we found a reference
;remember where new reference is in static dprs struct
mov ax,[grs.GRS_oRsCur]
mov [dprs.DPRS_oRs],ax
mov ax,[grs.GRS_oMrsCur]
mov [dprs.DPRS_oMrs],ax
mov [dprs.DPRS_otx],si ;save otxCur
cmp [txtFindIndex],PRSDEF_DefineMax
ja TryNext ;brif reference was a CALL
;Since this is only called when the current "defining"
;reference has been deleted, we know we're never going
;to find a SUB or FUNCTION pcode. A DECLARE is the
;strongest definition we can hope to find, so there's
;no need to search any further
test [mrsCur.MRS_flags2],FM2_INCLUDE ;is this an INCLUDE mrs?
jne TryNext ;force it to a "weak" owner
mov [dprs.DPRS_flags],FP_DECLARED
TryExit1:
xchg ax,di ;ax = 0 iff no longer need to search
jmp SHORT TryExit
TryNext:
;if we've just seen a CALL ref, keep searching for DECLARE
push si
PUSHI ax,<CODEOFFSET tOpPrsDef>
call TxtFindNextOp
jmp SHORT TryLoop
TryDone:
mov ax,sp ;return TRUE (non zero)
TryExit:
pop di ;restore caller's di
pop si ;restore caller's si
ret
TryToDefPrs ENDP
;**************************************************************
; FreeAllUndefinedPrs, ChkAllUndefPrs, ChkAllUndefPrsSaveRs
; Purpose:
; FreeAllUndefinedPrs has two purposes:
; (1) It is called to check all prs's to see
; if the the "defining" text reference to a prs has
; been marked as deleted. If so, it calls RedefOrDelPrs
; to search for a new "definition" if none are found, then
; the Prs is released via PrsFree.
; (2) It is called to check all prs's to see
; if the last reference to the prs has been deleted from the
; module being editted.
; ChkAllUndefPrs differs from FreeAllUndefPrs in that it
; knows that searching only needs to be performed when a
; reference is deleted.
;
; FreeAllUndefinedPrs is called to Free prs entries created
; by undefined direct mode references.
;
; The FTM_PrsDefDeleted bit of flagsTm is used to
; to determine if we need to search for a new "defining"
; reference for the prs.
;
; Entry:
; flagsTm.FTM_PrsDefDeleted set if we need to search
; for a new "defining" reference.
;
; Exit:
; Deleted prs entries with no new definitions are freed
; Deleted prs entries with new definitions have otxDef
; and oRsDef set to the new definition.
;**************************************************************
PUBLIC ChkAllUndefPrsSaveRs
ChkAllUndefPrsSaveRs PROC NEAR
push [grs.GRS_oRsCur] ;preserve current oRs
call ChkAllUndefPrs ;check all undefed prs entries
call RsActivateCP ;Reactivate current oRs
ret
ChkAllUndefPrsSaveRs ENDP
PUBLIC ChkAllUndefPrs
ChkAllUndefPrs PROC NEAR
test WORD PTR [flagsTm],FTM_PrsDefDeleted OR FTM2_PrsRefDeleted*100h
;have any definitions been deleted?
jne FreeAllUndefinedPrs ;brif so - Redef or Del all UNDEFINED
; prs entries
ret
ChkAllUndefPrs ENDP
PUBLIC FreeAllUndefinedPrs
FreeAllUndefinedPrs PROC NEAR
push si
push di
mov ax,[grs.GRS_oMrsCur]
mov [uprs.UPRS_oMrsRefDel],ax ;store mrs of deleted text
mov si,UNDEFINED
FreeAllUndef_Cont:
cCall PrsDeActivate ; ensure all proc.s are in Rs table
FreeAllUndef_Cont1:
mov di,si
FreeAllUndef_Cont2:
mov ax,di
call GetNextPrs ; PTRRS:ax points to first prs
; ax == UNDEFINED ==> no prs's
inc ax
jnz FAU_DontExit
jmp FreeAllUndef_Exit
FAU_DontExit:
dec ax
mov si,ax ; cache, so we don't end up starting
; from the beginning of the prs
; chain each time we free a prs
mov bx,ax
RS_BASE add,bx ; bx = oPrs
; assign cx = 0 if no reference to the Prs has been deleted otw non-zero
xor cx,cx
test PTRRS[bx.PRS_flags2],FP_RefDeleted ;[38]
jz NoRefDeleted ;brif no reference has been deleted
and PTRRS[bx.PRS_flags2],NOT FP_RefDeleted ;[38]clear flag
not cx ;set cx = non-0 since ref was deleted
NoRefDeleted:
mov [uprs.UPRS_fNoRefSameMod],cx ;initialize fNoRefSameMod
; to TRUE if we must search for
; a ref to the Prs in the module
; assign ax = 0 if otxDef is defined otw non-zero
mov al,1 ;assume otxDef is undefined
cmp PTRRS[bx.PRS_otxDef],UNDEFINED
je otxDefUnDefined ;brif otxDef is UnDefined
jcxz FreeAllUndef_Cont1 ;brif otxDef is Defined and
; no ref to the prs has been
; deleted -- nothing to do
xor ax,ax ;set ax = 0 since otxDef is defined
otxDefUnDefined:
push cx ;preserve condition flag
push ax ;preserve condition flag
push si ; pass to PrsActivateCP
call PrsActivateCP ;activate prs which may be freed
pop cx ;cx = 0 iff otxDef is defined
pop ax ;ax = 0 iff no ref to proc was del'd
jcxz DontSearchForDeclare ;brif otxDef of proc is defined
xor dx,dx ;assume that we will need to search
; for a new defining ref
test [flagsTm],FTM_PrsDefDeleted
jnz SearchForRef ;brif a defining ref has been del'd
or ax,ax ;ax = 0 if no ref to proc was del'd
jz ChkDeletePrs ;This branch is taken if no ref to
; this proc has been deleted and
; no defining ref has been deleted
DontSearchForDeclare:
mov dl,FP_DECLARED
SearchForRef:
mov [dprs.DPRS_flags],dl ;set dprs.flags to FP_DECLARED
; if we don't need to search for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -