📄 txtdata.asm
字号:
TITLE txtdata.asm - Ascii Load DATA Stmt movement Functions
;==========================================================================
;
;Module: txtdata.asm
;System: Quick BASIC Interpreter
;
;This entire module could disappear if previous versions of BASCOM
;either did not allow DATA statements within a SUB, or localized
;access to DATA and RESTORE statements to the context they are in.
;For compatibility, the functions in this module move DATA statements
;and labels for RESTORE statements from SUB/FUNCTIONs to main level code.
;
;
;===========================================================================
include version.inc
TXTDATA_ASM = ON
includeOnce architec
includeOnce context
includeOnce heap
includeOnce msgshort
includeOnce names
includeOnce opmin
includeOnce parser
includeOnce scanner
includeOnce txtmgr
includeOnce txtint
assumes DS,DATA
assumes SS,DATA
assumes ES,NOTHING
sBegin DATA
;-----------------------------------------------------------------------------
; Description of Table bdData
;
; This table contains 1 entry for every statement in the module significant
; to migration of DATA statements from SUB/FUNCTION to main program.
; The first byte of each entry is a type, which determines what info
; is contained in the rest of the entry as follows:
;
; DT_Data - entry describes a DATA opcode which needs to be moved from an
; SUB/FUNCTION's text table to the module's text table.
; It is followed by 2 byte oPrs and a 2 byte text offset to
; the opStData opcode within the prs. This entry is created
; by TDataEntry when text mgr sees opStData during ASCII Load.
;
; DT_Restore - entry describes a RESTORE opcode which may or may not refer to
; a label within a SUB/FUNCTION's text table.
; It is followed by 2 byte oPrs and a 2 byte text offset to
; the opStRestore1 opcode. This entry is created
; by TDataEntry when text mgr sees opStRestore1 during ASCII Load.
;
; DT_EndProc - entry is created when we see the end of a SUB/FUNCTION during
; ASCII Load. It is followed by 2 byte oPrs and a 2 byte text offset
; into the module's text table, where the SUB/FUNCTION was encountered
; during the Load.
;
; DT_Label - entry describes a new label to be generated in the main program.
; This is needed because the label in the prs which was refered to
; by a RESTORE, may also be refered to by GOTO or GOSUB.
; This entry is created by TDataEnd after the Load has completed.
;
; DT_End - marks the end of the table.
;
;-----------------------------------------------------------------------------
bdData bd <0,0,0>
fIgnoreTDataEntry DB TRUE
CB_TDATA EQU 5 ;5 bytes per entry
PUBLIC fDataMoved
;set to TRUE every time a DATA statement is moved from a SUB to module level
fDataMoved DB 0
sEnd DATA
sBegin CP
assumes cs,CP
;*****************************************************************************
; TDataStart
; Purpose:
; Called at the start of ASCII Load to initialize things for movement
; of DATA statements from prs to module.
; Exit:
; returns al=ER_OM if out-of-memory
; al=0 if no error
; (with condition codes set accordingly)
;
;*****************************************************************************
PUBLIC TDataStart
TDataStart PROC NEAR
; Don't allow nested calls to TDataStart
DbAssertRelB [fIgnoreTDataEntry],ne,0,CP,<TDataStart: nested call>
sub ax,ax
mov [fIgnoreTDataEntry],al
mov [bdData.BD_cbLogical],ax
PUSHI ax,<dataOFFSET bdData>
PUSHI ax,CB_TDATA ;initial size of node buffer
PUSHI ax,<IT_NO_OWNERS> ;heap type
call BdAlloc
or ax,ax ;set condition codes for caller
mov al,ER_OM
je TDStartExit ;brif out-of-memory error
GotBd:
mov bx,[bdData.BD_pb]
mov BYTE PTR [bx],DT_End ;make table look empty
;condition codes still based on ax
sub ax,ax ;no error
TDStartExit:
or ax,ax ;set condition codes for caller
ret
TDataStart ENDP
;*****************************************************************************
; TDataEntry
; Purpose:
; Called during ASCII Load every time a DATA statement
; or a RESTORE statement is inserted into any text table.
; It adds info about the statement to a buffer so TDataEnd
; can move the DATA statements from prs to module at end of load.
; Always keeps room for a new entry at end of buffer
; Entry:
; al = DT_Data for DATA stmt,
; = DT_Restore for RESTORE stmt,
; = DT_EndProc for END SUB/FUNCTION stmt
; bx = otx
; grs.oPrsCur identifies the text table within the module
; Exit:
; returns ax=0 (with condition codes set accordingly) if out-of-memory
;
;*****************************************************************************
PUBLIC TDataEntry
TDataEntry PROC NEAR
DbAssertRelB [txdCur.TXD_scanState],ne,SS_EXECUTE,CP,<TDataEntry: bad scanstate>
DbAssertRelB al,ne,0,CP,<TDataEntry: called with al=0>
;function assumes we can return al=non-zero if we don't alter ax
FLoadActive
je TdExit ;brif not LOADing a file
cmp [fIgnoreTDataEntry],FALSE
jne TdExit ;brif TDataEnd is active. TDataEnd
; calls TxtInsUpdate, which can call
; TDataEntry
cmp al,DT_Data
jne NotData
test [txdCur.TXD_flags],FTX_mrs
jne TdExit ;brif DATA stmt within main program
NotData:
push di ;save caller's di
mov di,[bdData.BD_pb]
DbAssertRel di,ne,NULL,CP,<TDataEntry: no buffer>
add di,[bdData.BD_cbLogical]
sub di,CB_TDATA
push ds
pop es ;es = DGROUP
;NOTE: al must still = TDataEntry parm
;**********************************
;NOTE: al still equals entry value
;**********************************
stosb ;store node type
mov ax,[grs.GRS_oPrsCur]
stosw ;store current prs
xchg ax,bx ;ax = otx
stosw
;make room for next entry
PUSHI ax,<DATAOFFSET bdData>
PUSHI ax,CB_TDATA
call BdGrow
mov bx,[bdData.BD_pb]
add bx,[bdData.BD_cbLogical]
mov BYTE PTR [bx - CB_TDATA],DT_End ;make table look empty
pop di ;restore caller's di
TdExit:
or ax,ax ;set condition codes for caller
ret
TDataEntry ENDP
;*****************************************************************************
; TDataEnd
; Purpose:
; Called at the end of an ASCII Load
; Step1: For each RESTORE in bdData, find the label definition.
; If the label definition is in a prs,
; Generate a new unique oNam
; Store the new oNam in the restore opcode's operand
; Insert DT_Label into bdData with
; otx field to the label definition's otx,
; oPrs field to the label definition's oPrs
; else
; ignore the entry
; Step2: For each DT_Data move the DATA opcode from the prs to
; the mrs. For each DT_Label entry in bdData, generate
; an opBolLab opcode in the mrs.
;
; Exit:
; returns al=ER_OM if out-of-memory
; al=0 if no error
; (with condition codes set accordingly)
;
;*****************************************************************************
cProc TDataEnd,<PUBLIC,NEAR,NODATA>,<si,di>
localW lnCur
localW oPrsRestore
localW oNamNew
cBegin
cmp [fIgnoreTDataEntry],0
je @F ; Redundant tDataEnd
J1_TDEndExitOk:
jmp TDEndExitOk ; Redundant tDataEnd
@@:
mov [lnCur],100d
mov [fIgnoreTDataEntry],NOT FALSE
mov si,[bdData.BD_pb]
or si,si ; is bdData even allocated?
jz J1_TDEndExitOK ; brif not, nothing to do
Step1Loop:
lodsb ;al = node type
.errnz DT_End
or al,al ;test for DT_End
je Step1Done ;brif done with step1's pass over list
cmp al,DT_Restore
jne Step1Next ;brif not a RESTORE node
lodsw ;ax = oPrs field (may be UNDEFINED)
mov [oPrsRestore],ax
push ax
call PrsActivateCP ;activate opRestore's prs
;Generate a label which has not been used in this module
UniqueLabelLoop:
inc [lnCur]
mov ax,[lnCur] ;pass line# to ONamOfLn in ax
call ONamOfLn ;ax = oNam for line number lnCur
je JE1_TdEndOmErr ;brif out-of-memory error
mov [oNamNew],ax ;preserve proposed oNam
test dl,NM_fLineNumLabel ;dl = flags byte returned by ONamOfLn
jne UniqueLabelLoop ;brif name is already used as label
lodsw ;ax = otx field of opStRestore
inc ax ;advance to oNam operand
inc ax
mov di,ax ;di = otx to opStRestore's oNam
call GetWOtx ;ax = label's oNam (from opStRestore)
call FindLabelDef ;bx = oPrs, ax = otx of label def
;current prs is preserved
inc ax
je Step1Loop ;brif label not found
inc bx ;test prs for UNDEFINED
je Step1Loop ;brif label defn is in mrs (no need
; to change RESTORE's operand, we're
; not moving DATA stmts already in mrs)
dec ax ;restore ax = otx
dec bx ;restore bx = oPrs where label's defined
mov cx,[oNamNew]
call InsertLabInTbl ;insert DT_Label entry in bdData
; si updated if new entry inserted
; before current si
inc ax ;test for UNDEFINED
je Step1Loop ;brif label defn is in prs with no DATA
; stmts (we could handle this case,
; but it is not worth the code it would
; take)
dec ax ;test for 0
je JE1_TdEndOmErr ;brif out-of-memory error
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -