📄 txtsave.asm
字号:
TITLE txtsave.asm - ASCII Save Functions
;==========================================================================
;
;Module: txtsave.asm - ASCII Save Functions
;System: Quick BASIC Interpreter
;
;=========================================================================*/
include version.inc
TXTSAVE_ASM = ON
includeOnce architec
includeOnce context
includeOnce heap
includeOnce lister
includeOnce names
includeOnce opcontrl
includeOnce opid
includeOnce opmin
includeOnce opstmt
includeOnce parser
includeOnce pcode
includeOnce qbimsgs
includeOnce rtinterp
includeOnce rtps
includeOnce rttemp
includeOnce scanner
includeOnce txtmgr
includeOnce txtint
includeOnce util
includeOnce ui
includeOnce variable
includeOnce edit
assumes DS,DATA
assumes SS,DATA
assumes ES,NOTHING
ASC_CRLF EQU 0A0Dh ;ASCII Carriage return/Line Feed
ASC_TAB EQU 9 ;ASCII Tab
sBegin DATA
EXTRN tabStops:WORD ;defined in edit manager
EXTRN b$PTRFIL:WORD ;defined by runtime - current channel ptr
CrLf DW ASC_CRLF ;for file line termination
oMrsSaveDecl DW 0 ;used by SaveDeclares
sEnd DATA
sBegin CODE
;Table of opcodes used to search for DECLARE or CALL statements
;
tOpDecl LABEL WORD
opTabStart DECL
opTabEntry DECL,opStDeclare
opTabEntry DECL,opStCall
opTabEntry DECL,opStCalls
opTabEntry DECL,opStCallLess
opTabEntry DECL,opEot
sEnd CODE
EXTRN B$BUFO:FAR
EXTRN B$KILL:FAR
sBegin CP
assumes cs,CP
;*************************************************************
; ushort SaveTxdCur(ax:otxStart)
; Purpose:
; ASCII save the contents of the current text table
; Entry:
; ax = text offset to start saving text
; Exit:
; ax = size of last line output (=2 if trailing blank line)
; ps.bdpSrc is used
; Exceptions:
; Can cause runtime error (Out of memory, I/O errors)
;
;*************************************************************
SaveTxdCur PROC NEAR
DbChk Otx,ax
push si
push di
sub di,di ;Init cbLastLine = 0
mov [otxListNext],ax ;ListLine() updates [otxListNext]
test [mrsCur.MRS_flags2],FM2_NoPcode ; document file?
je GetOtxEndProg ; file is measured in Otxs, not lines
DbAssertRel [otxListNext],e,0,CP,<SaveTxdCur:Not starting at the begining of file>
push [mrsCur.MRS_pDocumentBuf]
call S_LinesInBuf ; get # lines in document buffer
jmp short SetMaximumSave
GetOtxEndProg:
call OtxEndProg ;ax = otx to Watch pcode
SetMaximumSave:
xchg si,ax ;si = otx to Watch pcode
StLoop:
mov ax,[otxListNext] ;ax=offset for next line to list
cmp ax,si
DJMP jae SlDone ;brif done with this text table
test [mrsCur.MRS_flags2],FM2_NoPcode ; document file?
je ListPcodeLine ; brif not, let lister get line
push [mrsCur.MRS_pDocumentBuf] ; document table to list from
push ax ; line to list
push ps.PS_bdpSrc.BDP_cbLogical ; length of buffer
push ps.PS_bdpSrc.BDP_pb ;pass ptr to dest buf
call S_cbGetLineBuf ; AX = cBytes in line
inc [otxListNext] ; bump pointer to next line
mov [cLeadingSpaces],0 ; start with no leading spaces
mov bx,[ps.PS_bdpSrc.BDP_pb]; BX = ptr to 0 terminated string
CheckNextChar:
cmp byte ptr [bx],' ' ; Is it a space
jne GotLine ; brif not, say that we got line
inc [cLeadingSpaces] ; indicate another space
inc bx ; point to next character
jmp CheckNextChar ; check it for a space
ListPCodeLine:
push ax ;pass offset to ListLine
PUSHI ax,<DATAOFFSET ps.PS_bdpSrc> ;pass dst buf ptr to listline
call ListLine ;ax=char count
inc ax ;test for UNDEFINED
jne NotOmErr ;brif out-of-memory
jmp OmErrCP
NotOmErr:
dec ax ;restore ax = byte count
GotLine:
cmp [fLsIncluded],0
jne StLoop ;brif line was part of $INCLUDE file
test mrsCur.MRS_flags2,FM2_EntabSource ;do we need to entab leading
;blanks?
jz NoEntab ;brif not
mov cl,[cLeadingSpaces] ;cl = count of leading spaces
or cl,cl ;any leading spaces?
jnz EntabLeadingSpaces ;brif so, replace with tabs
NoEntab:
mov bx,[ps.PS_bdpSrc.BDP_pb]
EntabCont:
; There is currently no need to call UpdChanCur here, because
; there is no chance of having nested open files during ascii save.
DbAssertRel b$PTRFIL,ne,0,CP,<SaveTxdCur:Invalid channel>
; Call OutLine as we can not guarentee that the buffer
; pointed to by BX contains at least two more bytes.
; This is slower, but will not trash the heaps.
mov di,ax ; DI = new "cbLastLine"
inc di ; account for CRLF
inc di
call OutLine ; Print line and CRLF
DJMP jmp SHORT StLoop
SlDone:
xchg ax,di ;ax = cb last line emitted
pop di
pop si
ret
SaveTxdCur ENDP
; We have a line with leading spaces which needs to be entabbed.
; We will convert spaces to tabs in the buffer, and return the
; new buffer char count, and a ptr to the start of the buffer.
;
; Entry:
; ax = count of chars in line buffer
; cl = count of leading spaces
; Exit:
; ax = adjusted count of chars in line buffer
; bx = ptr to first char in buffer
; Uses:
; bx,cx,dx
EntabLeadingSpaces:
push ax ;preserve buffer char count
xchg ax,cx
sub ah,ah ;ax = cLeadingSpaces
mov dx,ax ;remember cLeadingSpaces
mov cx,[tabStops] ;get user defined tabstop settings
; User interface guarantees tabStops will not be set to 0
DbAssertRel cx,nz,0,CP,<tabStops=0 detected in Ascii save>
div cl ;al=tab count, ah=space count
mov bx,[ps.PS_bdpSrc.BDP_pb] ;bx=ptr to line buffer
add bx,dx ;bx=ptr to first non-leading space
sub dl,al
sub dl,ah ;dx=excess space in buffer
sub bl,ah ;backup over remaining spaces
sbb bh,0
xchg ax,cx
sub ch,ch ;cx=tab count
jcxz NoTabs ;brif none to replace
mov al,ASC_TAB
TabLoop:
dec bx ;back up a char
mov [bx],al ;replace space with tab
loop TabLoop
NoTabs:
pop ax ;recover buffer char count
sub ax,dx ;adust for removed spaces
jmp EntabCont
;*************************************************************
; OutLine, OutCrLf
; Purpose:
; OutLine - Output line and CR-LF to current file
; OutCrLf - Output CR-LF to current file
; Entry:
; bx points to 1st byte to output
; ax = byte count
;
;*************************************************************
OutLine PROC NEAR
; There is currently no need to call UpdChanCur here, because
; there is no chance of having nested open files during ascii save.
DbAssertRel b$PTRFIL,ne,0,CP,<OutLine:Invalid channel>
push ds ;pass segment of buffer
push bx ;pass offset of buffer
push ax ;pass length of buffer
call B$BUFO ;output line via runtime
;fall into OutCrLf
OutLine ENDP
OutCrLf PROC
; There is currently no need to call UpdChanCur here, because
; there is no chance of having nested open files during ascii save.
DbAssertRel b$PTRFIL,ne,0,CP,<OutCrLf:Invalid channel>
push ds
PUSHI ax,<dataOFFSET CrLf>
PUSHI ax,2
call B$BUFO ;output CR/LF via runtime
ret
OutCrLf ENDP
;*************************************************************
; RelShBuf
; Purpose:
; Release temporary text table used by SaveProcHdr.
; Called when we're done saving, or when an error occurs.
;
;*************************************************************
RelShBuf PROC NEAR
mov [txdCur.TXD_bdlText_cbLogical],0
;so TxtDiscard won't examine deleted txt
call TxtDiscard ;discard temporary text table
call TxtActivate ;make module's text table cur again
mov [ps.PS_bdpDst.BDP_cbLogical],0 ;release space held by temp bd
ret
RelShBuf ENDP
;*************************************************************
; ushort SaveProcHdr(ax:otxProcDef)
; Purpose:
; ASCII save the current procedure's header.
;
; Entry:
; ax = otxProcDef = offset into procedure's text table to opBol for line
; containing SUB/FUNCTION statement. 0 if this table has no
; SUB/FUNCTION statement yet.
;
; Exit:
; ps.bdpSrc is used
; grs.fDirect = FALSE
; ax = 0 if no error, else Standard BASIC error code (i.e. ER_xxx)
;
; Exceptions:
; Can cause runtime error (Out of memory, I/O errors)
;
;*************************************************************
SaveProcHdr PROC NEAR
push si ;save caller's si,di
push di
mov di,ax ;di = otxProcDef
push [grs.GRS_oPrsCur] ;pass current oPrs to PrsActivate below
;fill tEtTemp[] with DEFTYP's from start of proc table to SUB line
mov ax,di ;ax = otxProcDef
mov bx,dataOFFSET tEtTemp ;bx -> type table
call OtxDefType
;move everything up to proc def from procedure's to temp text table
PUSHI ax,<dataOFFSET ps.PS_bdpDst>
push di ;pass otxProcDef
call BdRealloc
or ax,ax
je JE1_ShOmErr ;brif out-of-memory error
PUSHI ax,<dataOFFSET txdCur.TXD_bdlText>
SetStartOtx ax
push ax
push [ps.PS_bdpDst.BDP_pb]
push di ;pass otxProcDef
call BdlCopyFrom
;Now we create a temporary text table for saving the synthetically
;generated procedure header. We must go through the following steps
; to do this:
; PrsDeactivate() --- causes module's text table to be made active
; TxtDeactivate() --- causes no text table to be made active
; TxtCurInit() --- make temp text table active
; put synthetically generated pcode into txdCur
; ASCII save this pcode buffer to the file
; TxtDiscard() --- discard temporary text table
; TxtActivate() --- make module's text table current again
; PrsActivate(oPrsSave)
;[flagsTM.FTM_SaveProcHdr] is non-zero while in critical state
; within function SaveProcHdr. Tells SaveFile's error cleanup
; to take special action.
or [flagsTM],FTM_SaveProcHdr ;if err, remember to clean up
call PrsDeactivate ;make module's text table active
call TxtDeactivate ;causes no text table to be made active
call TxtCurInit ;make temp text table active
je ShOmErr ;brif out-of-memory error
;emit synthetic DEFxxx statements as transition from end of last
;text table to procedure definition line
PUSHI ax,<dataOFFSET ps.PS_tEtCur>
PUSHI ax,<dataOFFSET tEtTemp>
SetStartOtx ax ;insert at start of text
call InsertEtDiff
JE1_ShOmErr:
je ShOmErr ;brif out-of-memory error
call OtxEndProg ;ax = otx to Watch pcode
xchg si,ax ; = offset beyond synthetic DEFxxx stmts
;Append everything up to SUB line to temp table
push si ;pass otx to Watch pcode
push di ;pass otxProcDef
call TxtMoveUp
je ShOmErr ;brif out-of-memory error
PUSHI ax,<dataOFFSET txdCur.TXD_bdlText>
push si ;pass otx to Watch pcode
push [ps.PS_bdpDst.BDP_pb]
push di ;pass otxProcDef
call BdlCopyTo
call SqueezeDefs ;takes parm in si
;if setting of $STATIC/$DYNAMIC differs between procedure's header
;and where procedure will be listed in source file,
;insert pcode to change the state for the procedure,
;Note: fLsDynArrays's value will be changed by ListLine() when it
; lists the line emitted by InsertDynDiff (if any)
SetStartOtx ax ;insert at start of text
mov dh,[fLsDynArrays] ;dh = old $STATIC/$DYNAMIC state
mov dl,[fProcDyn] ;dl = new $STATIC/$DYNAMIC state
call InsertDynDiff
je ShOmErr ;brif out of memory error
SetStartOtx ax ;start saving at start of text
call SaveTxdCur ;save procedure's header to file
call RelShBuf ;release temp text tbl
and [flagsTM],NOT FTM_SaveProcHdr ;reset critical section flag
;oPrs parm was pushed on entry to this function
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -