📄 txtload.asm
字号:
; pcode, bad opcodes, etc.
mov ax,[otxLastProc]
mov [otxUpdLinks],ax
xchg bx,ax ;bx = otxLastProc
mov al,DT_EndProc
call TDataEntry ;add entry to table so we can
;move DATA stmts from prs to mrs
pushf ;preserve error status
call PrsDeactivate ;make module's txt table active
popf ;recover error status
je LexExit ;return PSW.C if out-of-memory
;emit DEFxxx statements to module, bringing its state up
;to the state at the end of the procedure, for BASCOM compatibility.
;In BASCOM, DEFxxx statements are globally scoped, but in QBI,
;we want to give the user the feeling that each procedure source
;window stands independently of the module's source window
mov si,[txdCur.TXD_bdlText_cbLogical]
PUSHI ax,<dataOFFSET tEtTemp>
PUSHI ax,<dataOFFSET ps.PS_tEtCur>
mov ax,[otxLastProc] ;ax = insertion point
call InsertEtDiff
je LexExit ;return PSW.C if out-of-memory
mov ax,[otxLastProc] ;ax = insertion point
mov dh,[fDynArraysMod] ;dh = old state for module level code
mov dl,[fDynArrays] ;dl = new state ($STATIC or $DYNAMIC)
call InsertDynDiff
je LexExit ;return PSW.C if out-of-memory error
neg si ;si = -(old cbLogical)
add si,[txdCur.TXD_bdlText_cbLogical]
;si = txdCur.bdlText.cbLogical-(old)
; = #bytes of synthetic pcode emitted
mov ax,[otxLastProc]
cmp [otxDefEnd],ax
je GotDeadCode
;some module level statements have been emitted since the
;last synthetically emitted DEFxxx statements, so those
;DEFxxx statements can't be deleted at the end of AsciiMerge.
;The reason we try to delete them is to keep the file from
;growing with every ASCII Save/Load by useless DEFxxx statements.
mov [otxDefStart],ax
;ax = otxLastProc
;si = #bytes of synthetic pcode generated
GotDeadCode:
xchg ax,si ;si = otx of 1st inserted DEFxxx
xchg ax,bx ;bx = cbInserted
add bx,si ;bx = otx after inserted DEFxxx
push bx ;preserve across call
call TxtInsUpdate ;update line count for inserted lines
DbAssertRel ax,ne,0,CP,<Unexpected OM error in LoadExitProc>
pop ax ;recover oTx after inserted text
;Tell AsciiMerge that we've changed text tables, and
;where to insert next line in the module's text table
mov [otxNewInsert],ax
mov [otxDefEnd],ax
stc ;not out-of-memory
LexExit:
cmc ;return psw.c set if out of memory
pop si ;restore caller's si
ret
LoadExitProc ENDP
;***************
;* ASCII Load *
;***************
;*********************************************************************
; ushort NEAR GetLineBd(bx:pbd, cx=cbAppend)
; Purpose:
; Input an arbitrarily long line into the buffer pointed to by pbd.
;
; Entry:
; pbd points to destination buffer descriptor
; cx = number of bytes already in buffer to preserve
; = 0 if append is not desired
; Exit:
; returns 0 if got a line, dx = length of line in bytes
; if out-of-memory,
; returns ax = ER_OM
; if end-of-file
; returns UNDEFINED
; If new line is longer than pbd->cbLogical,
; pbd->cbLogical = new length
; Line is 0-byte terminated
;
; Exceptions:
; Can cause runtime error (Out of memory, I/O errors)
;
;*********************************************************************
PUBLIC GetALine ;for profiling only
cProc GetALine,<NEAR>,<si,di>
parmW pBufDst ;destination buffer
parmW cbMax ;# of free bytes in dest. buffer
cBegin
;Register usage:
; SI contains b$PTRFIL, i.e., ptr to FDB for input channel
; DI contains a ptr to the destination buffer
; BX contains the offset to next unread char in buffer
; CX contains cbMax (input)
; DX contains count of chars read in so far
mov si,[b$PTRFIL]
or si,si ;is the current channel valid?
jne GlStart ;brif so, use it
call UpdChanCur ;refresh channel in case of error
mov si,[b$PTRFIL]
GlStart:
FDB_PTR es,si,si ;(ES:)[SI] = *FDB
mov bx,FileDB.FD_BUFCNT ;offset to next unread char in FDB
mov di,[pBufDst] ;di = start of dest buffer
sub dx,dx ;dx = 0 (count of chars read so far)
GlStartLoop:
mov cx,[cbMax]
GlLoop:
cmp cx,dx
jbe J1_GlEol ;brif reached end of dest. buffer
cmp bx,FileDB.FD_INBUFCNT ;any unread chars left?
jz FillBuff ; brif not
mov al,FileDB.FD_BUFFER[BX] ;fetch char from FDB
inc bx ;update offset to next unread char
GlCont1:
cmp al,ASC_DBL_QUOTE ;test for ", CR, TAB, LF, CTRL-Z
jbe GlQuoteOrLess ;brif TAB, or end-of-line
GlCont:
mov [di],al ;put char in dst buffer
inc di ;bump dst ptr
inc dx ;bump count
jmp SHORT GlLoop
J1_GlEol:
jmp short GlEol
FillBuff:
push dx ;preserve count
mov FileDB.FD_BUFCNT,bx ;update based on chars we've read so far
call B$IDISK_SINP ;al = next byte from file
FDB_PTR es ;make sure ES still in FDB segment
mov bx,FileDB.FD_BUFCNT ;restore offset to next char in FDB
pop dx
jcxz GlEof ;brif EOF (cx set by B$IDISK_SINP)
mov cx,[cbMax] ;refresh
jmp short GlCont1
GlQuote:
not [fInQuote] ;toggle "quoted string" state
jmp SHORT GlCont
GlQuoteOrLess:
je GlQuote
cmp al,ASC_EOF ;test for CR, TAB, LF, CTRL-Z
ja GlCont ;brif not TAB or end-of-line
jne GlCrOrLess ;brif Not CtrlZ
or dx,dx ;was CtrlZ at beginning of line?
je GlEof ;brif so - treat as EOF
;fall thru and loop to GlCont
GlCrOrLess:
cmp al,ASC_CR ;test for carriage return
je GlLoop ;brif carriage return - ignore
cmp al,ASC_LF ;test for line feed
je GlEol ;brif end-of-line
cmp al,ASC_TAB ;test for TAB
jne GlCont ;brif not TAB
cmp [fInQuote],0
jne GlCont ;brif within "quoted string"
;expand TABs to spaces as follows:
; emit (tabs - (col MOD tabs)) spaces
; where col is current column (0..n) and
; tabs is #columns per tab stop (from user interface)
; if buffer gets full before done expanding tabs, don't
; worry about continuing into next buffer.
or [mrsCur.MRS_flags2],FM2_EntabSource ;remember to reentab at
;ascii save time
push dx ;save current column
xchg ax,dx ;ax = current column
cwd ;DX:AX = current column
mov cx,[tabStops] ;gets value from user interface
; User interface should ensure that 0 is not a valid value
; for tabstops.
;
DbAssertRel cx,nz,0,CP,<tab stops = 0 in ascii load>
div cx ;dx = remainder = modulus
sub cx,dx ;cx = # spaces to emit
pop dx ;restore current column
mov al,' ' ;for now, map TAB to space
TabLoop:
mov [di],al
inc di ;bump dst ptr
inc dx ;bump count
cmp [cbMax],dx
jbe GlEol ;brif reached end-of-buffer
loop TabLoop
jmp GlStartLoop
;Reached end-of-file while reading a line
GlEof:
or dx,dx
jne GlEol ;brif line had valid data before EOF
dec dx ;return -1 for EOF
;Reached end-of-line while reading a line
GlEol:
mov FileDB.FD_BUFCNT,bx ;update based on chars we read
xchg ax,dx ;return byte count in ax
cEnd
CB_LINE EQU 80
cProc GetLineBd,<PUBLIC,NEAR>,<si,di>
cBegin
mov [fInQuote],0 ;toggle "quoted string" state
mov si,bx ;si points to buffer descriptor
mov di,cx ;di = cbLogical
;The following loop only executes 1 iteration for lines less than
;or equal to CB_LINE bytes in length
;
GlBdLoop:
;make sure there's room for at least CB_LINE+1 more bytes
push si ;pass pointer to buffer descriptor
lea ax,[di+CB_LINE+1] ;ax = number bytes we need
push ax
call BdCheckFree
or ax,ax
mov ax,ER_OM ;prepare for out-of-memory error
je GlBdExit ;brif out-of-memory error
mov ax,[si.BD_pb] ;ax points to start of result buffer
add ax,di ;add cbLogical
push ax ;pass ptr to destination
mov ax,[si.BD_cbPhysical] ;ax = size of buffer
sub ax,di ;ax = number of free bytes in buffer
dec ax ;leave room for 0-byte terminator
push ax ;pass maximum byte count
call GetALine ;read bytes from the file, stop at CR
cmp ax,UNDEFINED ;test for end-of-file
jne GotData ;brif not end-of-file
or di,di
jne GotData1 ;brif we've already got part of a line
jmp SHORT GlBdExit ;return end-of-file indication
; ax = UNDEFINED (eof)
GotData:
add di,ax ;di = total # bytes read so far
GotData1:
mov ax,[si.BD_cbPhysical]
dec ax
cmp ax,di
je GlBdLoop ;brif read stopped because of end-of-buf
mov bx,[si.BD_pb]
mov BYTE PTR [bx][di],0 ;zero terminate the line
mov dx,di ;return line length in dx
inc di ;include 0-byte terminator in count
cmp [si.BD_cbLogical],di
jae NotNewHigh
mov [si.BD_cbLogical],di ;cbLogical = length of longest
;line read into this bd
NotNewHigh:
sub ax,ax ;not end-of-file return code
GlBdExit:
cEnd
;Near gateway to StatusMsgFar - display msg on status line
PUBLIC StatusMsgCP, StatusMsg0CP
StatusMsg0CP PROC NEAR
mov ax,MSG_StatusEdit ; display edit window status line
StatusMsg0CP ENDP ; fall into StatusMsgCP
StatusMsgCP PROC NEAR
cCall StatusMsgFar,<ax>
ret
StatusMsgCP ENDP
;*************************************************************
; ushort NEAR AsciiMerge(ax:otxInsert)
;
; Purpose:
; Merge the contents of an ASCII source file into the current
; text table.
;
; Entry:
; ax = otxInsert = place to insert text
; grs.oMrsCur, grs.oPrsCur have their usual meaning
; Current input channel has been opened to file to be merged.
; cAsciiLoadsActive == 1 if this file is being loaded/merged,
; > 1 if this file is being $INCLUDEd
;
; Exit:
; grs.fDirect = FALSE
; al = 0 if no error, else Standard BASIC error code (i.e. ER_xxx)
; ps.bdpSrc is used
;
; Exceptions:
; Can cause runtime error (Out of memory, I/O errors)
;
;*************************************************************
DbPub AsciiMerge
cProc AsciiMerge,<NEAR>,<si,di>
cBegin
DbChk Otx,ax
mov si,ax ;ax = si = otxInsert
sub di,di ;initial line count = 0
inc [cAsciiLoadsActive]
cmp [cAsciiLoadsActive],1
jne AmLoop
;this isn't a recursive $INCLUDE call, init static variables
mov [otxUpdLinks],ax
mov [otxDefEnd],ax
mov [otxDefStart],ax
mov [otxLastProc],ax
sub ax,ax
mov [fDynArrays],al ;default to $STATIC
mov [fMergeInSub],al
dec ax ;ax = UNDEFINED
mov [otxNewInsert],ax
test [txdCur.TXD_flags],FTX_mrs
jne NotMergingInSub
mov [fMergeInSub],al ;set fMergInSub non-zero
NotMergingInSub:
test [mrsCur.MRS_flags2],FM2_NoPcode
jne NoStatusMsg ;dont display "precompiling" if document
mov ax,-MSG_Loading ;display Loading msg in intense video
call StatusMsgCP ; to tell user we're loading
NoStatusMsg:
;init default ps.tEtCur[] (default type array)
mov ax,si ;ax = text offset
call OtxDefTypeCur
;Get source lines and append them until EOF
AmLoop:
mov bx,dataOFFSET ps.PS_bdpSrc
sub cx,cx ;don't append, just fill buffer
call GetLineBd
inc ax ;test for UNDEFINED
je AmLoopExit ;brif got End-of-file (with ax=0)
dec ax ;ax = error code
jne AmLoopExit ;brif out-of-memory error
test di,1Fh ;update status line every 32 lines
jne NotYet ; just to tell user we're not hung
cCall UpdStatusLn,<di>
NotYet:
inc di ;bump line count
push [txdCur.TXD_bdlText_cbLogical]
;save current size of text table
test [mrsCur.MRS_flags2],FM2_NoPcode ; Document file?
je @F ;brif not, insert into text table
push WORD PTR [mrsCur.MRS_pDocumentBuf] ; ptr to buffer info
PUSHI ax,<dataOFFSET ps.PS_bdpSrc.BD_pb> ; ptr to ptr to text
call AppendLineBuf ;Append line to document buffer
and ax, ER_OM ; convert 0, -1 to 0, ER_OM
jmp short InsertDone
@@:
push si ;insert the line in the text table
push si
sub ax,ax ;clear fNoInsert flag
push ax ;We have text to insert
call TxtChange ;al = error code
InsertDone:
pop cx ;cx = old size of text table
cmp al,ER_OM
je AmLoopExit ;brif out-of-memory (only fatal error)
mov ax,[txdCur.TXD_bdlText_cbLogical]
sub ax,cx ;ax = size of inserted line
add si,ax ;update insertion point
cmp [otxNewInsert],UNDEFINED
je AmLoop ;brif we're still in same text table
;We just got a SUB, FUNCTION, END SUB, or END FUNCTION statement
;and as a result, have switched text tables
mov si,[otxNewInsert] ;si = new insertion point
mov [otxNewInsert],UNDEFINED
jmp SHORT AmLoop
;We are done loading this file.
;[al] = 0 if we've reached end-of-file.
;[al] = error code if fatal error occurred while loading.
; Fatal errors (like out-of-memory) cause mrs to be discarded
; unless they occurred within an INCLUDE file.
;
AmLoopExit:
dec [cAsciiLoadsActive]
jne StillLoading ;brif we're still in nested INCLUDE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -