📄 txtthr.asm
字号:
TITLE txtthr.asm - Text Table Linked List Maintenance Functions
;==========================================================================
;
;Module: txtthr.asm - Text Table Linked List Maintenance Functions
;System: Quick BASIC Interpreter
;
;=========================================================================*/
include version.inc
TXTTHR_ASM = ON
IncludeOnce architec
IncludeOnce context
IncludeOnce opcodes
IncludeOnce opaftqb4
IncludeOnce qbimsgs
includeOnce txtint
includeOnce txtmgr
includeOnce types
includeOnce variable
assumes DS,DATA
assumes SS,DATA
assumes ES,NOTHING
sBegin CODE
;These opcodes are of special interest whenever they are inserted:
;
PUBLIC tOpUpdl
tOpUpdl LABEL WORD
opTabStart UPDL
opTabEntry UPDL,opLab
opTabEntry UPDL,opLabSp
opTabEntry UPDL,opBolLab
opTabEntry UPDL,opBolLabSp
UPDL_labMax EQU UPDL_opBolLabSp
; Put in opBol to keep terminate most searches in update links
; before encountering opEot. This significantly speeds up generic
; edits which don't have any threads past the point of the edit.
opTabEntry UPDL,opBol
UPDL_SkipMax EQU UPDL_opBol
opTabEntry UPDL,opReParse
opTabEntry UPDL,opStDefType
opTabEntry UPDL,opStType
opTabEntry UPDL,opStEndType
opTabEntry UPDL,opStDefFn
opTabEntry UPDL,opStEndDef
opTabEntry UPDL,opEndSingleDef
opTabEntry UPDL,opEot
;Opcodes which are valid within TYPE/END TYPE blocks
;
tOpTypes LABEL WORD
opTabStart TYPES
opTabEntry TYPES,opElemRef
opTabEntry TYPES,opAsType
opTabEntry TYPES,opAsTypeExp
opTabEntry TYPES,opAsTypeFixed
opTabEntry TYPES,opStEndType
TYPES_DispatchMax EQU TYPES_opStEndType
; the following opcodes are allowed but no processing is required
; by ScanBlock
opTabEntry TYPES,opBol
opTabEntry TYPES,opBos
opTabEntry TYPES,opBolSp
opTabEntry TYPES,opBolInclude
opTabEntry TYPES,opBolIncludeSp
opTabEntry TYPES,opStRem
opTabEntry TYPES,opQuoteRem
opTabEntry TYPES,op_Static
opTabEntry TYPES,op_Dynamic
opTabEntry TYPES,op_Include
opTabEntry TYPES,opEot
sEnd CODE
sBegin CP
assumes cs,CP
;Threaded pcode descriptor
THR_DSC STRUC
THR_otxPrev DW 0 ;points to previous thread
THR_fInDS DW 0 ;non-zero if THR_otxPrev is a DS offset
THR_DSC ENDS
;*************************************************************************
; TxtDeThread(ax:pHead, di:otxDelFirst, cx:cbDel)
;
; Purpose:
; Called when a block of text is deleted.
; Traverse a linked list through the current text table,
; removing any nodes which are being deleted, and updating
; next-node-offsets for those nodes beyond the deleted range.
; This function is called BEFORE the text has been deleted.
;
; Entry:
; ax = pointer to ushort which heads linked list
; for example, &txdCur.otxLabLink
; di = text offset to 1st byte being deleted
; cx = number of bytes being deleted
;
; Preserves:
; cx (callers depend on this)
;
;*************************************************************************
cProc TxtDeThread,<PUBLIC,NEAR>,<si>
localW segTxtTab ;text table's segment
cBegin
xchg si,ax ;si points to head of list
DbChk TxdCur ;perform sanity check on txdCur
GetSegTxtTblCur ;es = seg adr of cur txt tbl
;preserves cx
mov [segTxtTab],es ;save text table's segment
mov dx,ds ;dx -> prev link node's segment (DGROUP)
mov bx,[si] ;bx -> 1st node in linked list (in ES)
mov ax,di
add ax,cx ;ax -> last byte deleted
DbChk Otx,ax
DeThrLoop:
cmp bx,UNDEFINED
je DeThrExit ;branch if done with linked list
DbChk Otx,bx
cmp bx,di
jb DeThrUnaffected ;brif node is unaffected by delete
; (i.e. node < 1st byte deleted)
cmp bx,ax
jb DeThrDeleted ;brif node is in deleted range
; (i.e. node < last byte deleted)
;else node is beyond deleted range
mov es,dx ;es = segment of predecessor node
;may be DGROUP:pHead or es:<node>
mov es:[si],bx ;update predecessor node
sub es:[si],cx
mov es,[segTxtTab] ;es = text table's segment
DeThrUnaffected:
mov si,bx ;save offset of prev node ptr in si
mov dx,es ;save seg of prev node ptr in dx
DeThrDeleted:
mov bx,es:[bx] ;bx points to next node in list
jmp SHORT DeThrLoop
DeThrExit:
mov es,dx ;es = segment of predecessor node
;may be DGROUP:pHead or es:<node>
mov es:[si],bx ;update predecessor node
cEnd
;**********************************************************************
; TxtDelThread
; Purpose:
; Called BEFORE pcode is deleted from current text table.
; Traverses all linked lists through the text table,
; updating the linked lists for the delete.
; Entry:
; parm1 = offset to start of delete
; parm2 = cbDel
;
;**********************************************************************
; TxtDeThread(&txdCur.otxLabLink, otxDelFirst, cbDel)
; TxtDeThread(&txdCur.otxReParseLink, otxDelFirst, cbDel)
; TxtDeThread(&txdCur.otxDefTypeLink, otxDelFirst, cbDel)
; TxtDeThread(&txdCur.otxTypeLink, otxDelFirst, cbDel)
;
; NOTE: TxtDeThread takes ax,cx,di as parms and preserves cx
;
cProc TxtDelThread,<PUBLIC,NEAR>,<si,di>
parmW otxStart
parmW cbDel
cBegin
mov di,[otxStart]
mov cx,[cbDel]
mov si,CPOFFSET TxtDeThread ;si = adr of function to call
mov ax,dataOFFSET txdCur.TXD_otxTypeLink
call si ;fixup otxTypeLink list
mov ax,dataOFFSET txdCur.TXD_otxDefTypeLink
call si ;fixup otxDefTypeLink list
mov ax,dataOFFSET txdCur.TXD_otxReParseLink
call si ;fixup otxReParseLink list
mov ax,dataOFFSET txdCur.TXD_otxLabLink
call si ;fixup otxLabLink list
test [txdCur.TXD_flags],FTX_mrs
je DelNotMod ;brif not module text table
; The linked list of opcodes headed by mrsCur.MRS_data_otxFirst
; only needs to be maintained while in SS_EXECUTE state, so
; we don't need to fix it up here
mov ax,dataOFFSET mrsCur.MRS_otxDefFnLink
call si
DelNotMod:
cEnd
;*************************************************************************
; TxtInsThread(pHead, pThrDsc, otxInsFirst, cbIns)
;
; Purpose:
; Called when a block of text is inserted. Traverse a linked
; list through the current text table, updating next-node-offsets
; for those nodes beyond the inserted range.
; This function is called AFTER the text has been inserted.
;
; Entry:
; parm1: pointer to ushort which heads linked list
; for example, &txdCur.otxLabLink
; parm2: pointer to thread descriptor which on exit contains fields:
; THR_otxPrev: offset to head or node which precedes the node
; being inserted in the list
; THR_fInDS: non-zero if THR_otxPrev is an offset into DS
; zero if THR_otxPrev is an offset into text table
; parm3: text offset to 1st byte inserted
; parm4: number of bytes being deleted
;
; Exit:
; *pThrDsc is updated so it refers to the last link which
; precedes otxInsFirst.
;
;*************************************************************************
cProc TxtInsThread,<PUBLIC,NEAR>,<si,di>
parmW pHead
parmW pThrDsc
parmW otxInsFirst
parmW cbIns
cBegin
DbChk TxdCur ;perform sanity check on txdCur
mov si,[pHead] ;si -> head of linked list (in DGROUP)
mov di,[pThrDsc]
mov [di.THR_otxPrev],si ;default THR_otxPrev to head of list
mov [di.THR_fInDS],1 ;set flag indicating THR_otxPrev is
; offset in DS
GetSegTxtTblCur ;es = seg adr of cur txt tbl
mov ax,es ;ax = seg adr of cur txt tbl
;NOTE: ax=es for remainder of function
mov dx,ds ;dx -> prev link node's segment (DGROUP)
mov bx,[si] ;bx -> 1st node in linked list (in ES)
mov cx,[cbIns] ;cx = #bytes inserted
InsThrLoop:
cmp bx,[otxInsFirst] ;compare with adr of 1st byte inserted
jb InsThrUnaffected ;brif node is unaffected by insert
; (i.e. node < 1st byte inserted)
cmp bx,UNDEFINED
je InsThrExit ;branch if done with linked list
mov es,dx ;es = segment of predecessor node
;may be DGROUP:pHead or es:<node>
add bx,cx ;bx points to where node is after insert
mov es:[si],bx ;update predecessor node
mov es,ax ;es = text table's segment
jmp SHORT NextLink
InsThrUnaffected:
mov [di.THR_otxPrev],bx ;THR_otxPrev points to last link before
; inserted block of text
mov [di.THR_fInDS],0 ;reset flag to 0, indicating THR_otxPrev
; is relative to the text segment
NextLink:
mov si,bx ;save offset of prev node ptr in si
mov dx,es ;save seg of prev node ptr in dx
mov bx,es:[si] ;bx points to next node in list
jmp SHORT InsThrLoop
InsThrExit:
cEnd
;*************************************************************************
; TxtAddThread(pThrDsc, otxNewLink)
;
; Purpose:
; Called AFTER a block of text has been inserted which contains
; an opcode having an operand that should be added to a linked
; list through the text table. This function inserts this opcode
; in the list.
;
; Entry:
; parm1: pointer to thread descriptor which contains following fields:
; THR_otxPrev: offset to head or node which precedes the node
; being inserted in the list
; THR_fInDS: non-zero if THR_otxPrev is an offset into DS
; zero if THR_otxPrev is an offset into text table
; parm2: pointer to new link field to add to linked list
;
;*************************************************************************
cProc TxtAddThread,<PUBLIC,NEAR>,<si,di>
parmW pThrDsc
parmW otxNewLink
cBegin
DbChk TxdCur ;perform sanity check on txdCur
GetSegTxtTblCur ;es = seg adr of cur txt tbl
mov ax,es ;ax = seg adr of cur txt tbl
mov si,[pThrDsc] ;si -> thread descriptor
mov bx,[si.THR_otxPrev] ;bx -> prev node / head of list
cmp [si.THR_fInDS],0
je prevInTxt ;brif bx is offset within text table
mov [si.THR_fInDS],0 ;reset THR_fInDS to 0
push ds
pop es ;es -> DGROUP
prevInTxt:
mov dx,es:[bx] ;dx -> next node
mov di,[otxNewLink] ;di -> new node
DbChk Otx,di
mov es:[bx],di ;prev node -> new node
mov es,ax ;es -> text table
mov es:[di],dx ;new node -> next node
mov [si.THR_otxPrev],di ;save adr of new node in thread dsc
cEnd
;**************************************************************
; void NEAR UpdateLinks(otxInsStart, otxInsEnd)
; void NEAR NoWalkUpdateLinks(otxInsStart, otxInsEnd)
;
; Purpose:
; Called after some text has been inserted into the current text table.
; During ASCII Load, it is not called for every line, but every
; time we switch text tables (speed optimization for LOAD).
; For each inserted opcode which has a link-field operand, it
; is inserted into its appropriate linked list. The NoWalkUpdateLinks
; entrypoint allows the binary translator to adjust links for pcode
; growth without looking at the inserted pcode. This is necessary as
; the pcode is not valid until after all translation has been performed.
;
; Entry:
; grs.oMrsCur, grs.oPrsCur have their usual meaning
; txdCur.bdlText describes the current text table.
; ps.bdpSrc contains source line to be inserted
; parm1: ushort otxInsStart - text table offset to opBol
; opcode for 1st line inserted.
; parm2: ushort otxInsEnd - text table offset to opBol
; opcode beyond last line inserted.
; (parm2 - parm1) should equal the number of bytes inserted.
; If this (parm2 - parm1), this function is effectively a nop.
;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -