📄 txtload.asm
字号:
cProc LoadFile,<PUBLIC,FAR>,<si,di>
parmW psdFilename
parmW otxInsert
localW oRsSave
localW otxCurSave
cBegin
DbAssertRel [b$CurFrame],a,bp,CP,<LoadFile: b$CurFrame .GE. bp>
;otherwise, runtime error recovery fails
push WORD PTR ([grs.GRS_fDirect]) ;save caller's fDirect
push [chanCur] ;save caller's current chan
; (for recursive calls)
call RtPushHandler ;save caller's runtime error handler
; (NOTE: alters stack pointer)
mov ax,CPOFFSET LfDone ;if any runtime errors occur,
call RtSetTrap ; branch to LfDone with sp,di =
; current values
;Runtime ensures we never enter the user interface with less
;than STACK_CHECK bytes free. Make sure that STACK_CHECK is big enough
;to satisfy parser's requirements.
DbAssertRel <STKCHK_ToLoadFile+STKCHK_LoadFile>,b,STACK_CHECK,CP,<LoadFile stk>
mov ax,[b$pend]
add ax,STKCHK_LoadFile
cmp sp,ax
jbe J1_RtErrOmStack ;brif almost out of stack space
mov ax,[grs.GRS_oRsCur]
mov [oRsSave],ax
mov ax,[grs.GRS_otxCur]
mov [otxCurSave],ax
sub ax,ax
mov [chanCur],ax ;in case we don't get file opened
; before we branch to LfDone (error)
SetfDirect al ;we're dealing with text tables
; not direct stmt buffer
dec ax ;ax = UNDEFINED
FLoadActive
jne Not1stLoad ;brif we're being called for
; recursive load ($INCLUDE or
; from LoadMakFile)
mov [oRsDupErr],ax ;so we can tell if any Duplicate
; Prs or Mrs errors occur during
; load
mov [cbAftMerge],0
test [txdCur.TXD_flags],FTX_mrs
je LfNotMerge ;brif we're in a SUB or FUNCTION
mov ax,[otxInsert]
cmp ax,LF_NewDoc
jae LfNotMerge ;brif we're not MERGEing a file
sub ax,[txdCur.TXD_bdlText_cbLogical]
neg ax ;ax = #bytes beyond insertion point
mov [cbAftMerge],ax
LfNotMerge:
Not1stLoad:
mov bx,[psdFilename] ;bx points to source filename sd
push ss
pop es ; assure es==dgroup
cmp [fLoadInclude],NULL ; loading include file?
jz SkipSearch ; no, go process as usual
mov al,ER_ADF ; "advanced feature unavailable"
jmp short J1_LfDone ; exit
SkipSearch:
mov di,dataOFFSET NormFname
mov si,dataOFFSET sdNormFname
call NormFilename ;normalize path of filename and
; append .bas to sd pointed to by si
jne J1_LfDone ;brif bad filename
Lf_Cont:
cmp [fInitialized],FALSE
je InInit ;if we're initializing we want to
;create the mrs for the module even
;if the file isn't found.
;Before we toss the current text table (via NewStmt), make sure
;file exists, so we can report an error. Note: this doesn't cover
;case where one of the modules in a multi-module load was not found.
;It is VERY expensive to handle the multi-module case, and
;handling the single module case lets the user test any error
;trapping code the same way as it would work in the compiler,
;since in the compiler, even a multi-module program consists of
;a single EXE file. Handling multi-modules would be of little
;value if we didn't handle missing $INCLUDE files, which
;would be more than prohibitive.
;
cCall FileExists,<di> ;see if file [di] found
or ax,ax
mov al,ER_FNF
jne InInit
J1_LfDone:
jmp LfDone ;brif couldn't find filename
InInit:
;Any errors encountered after this point are untrappable.
call CantCont ;loading/re-including a file prevents
; CONTinue (because we can't back out
; of it after the n'th line)
; NOTE: CantCont closes all files
; if CONT was possible, so this
; must be called before OpenChan.
; It also calls _BRUNINI which
; shows and clears the user screen.
mov ax,[otxInsert]
.errnz LF_NewDoc - 0FFFCh
cmp ax,LF_NewDoc
jb LoadFile_Cont ;brif doing a MERGE or $INCLUDE
.errnz LF_NewProg - 0FFFFH
DbAssertRelB [cChansOpen],e,0,CP,<NewStmt called for recursive LoadFile()>
call NewStmt ;erase content of this module
call StatusMsg0CP ;NewStmt erases function key line (25)
; which is same as status line
mov [otxCurSave],2 ;so we will position cursor @
; top of new window if ExStRunFile
; calls RtErrorCODE
mov [oRsSave],UNDEFINED ;remember that we can't restore
; the caller's oRs for error
; recovery. NewStmt also sets
; grs.otxCont to UNDEFINED,
; for runtime error recovery.
NoNewStmt:
cCall OgNamOfPsd,<si> ; get ogNam of given filename
or ax,ax ; OM error return?
jnz GotOgNam ; brif not
mov al,ER_OM
jmp SHORT J1_LfDone
GotOgNam:
push ax ; parm to MrsMake
mov cx,FM_TEMPORARY + (100h * FM2_File)
;set TEMP in case LOAD fails somewhere
;so we'll know to discard the mrs
mov ax,[otxInsert]
cmp ax,LF_ViewIncl
jne NotIncl
or ch,FM2_Include ;so we'll know to do a ReInclude
;if/when this file gets saved.
NotIncl:
cmp ax,LF_NewDoc
jne NotDoc ;brif not loading a Document file
or ch,FM2_NoPcode
NotDoc:
push cx ;pass flags
call MrsMake ;create new mrs for this file
or ax,ax
jne J1_LfDone ;brif error, al = error code
or [mrsCur.MRS_flags3], FM3_NotFound
call ModuleRudeEdit
LoadFile_Cont:
push [rsNew] ;DoDrawDebugScr resets rsNew,
; which was set by MrsMake.
; We need to preserve this so correct
; rs is active after MakeExe, or
; MakeLib.
call DoDrawDebugScrFar ;so screen isn't blank with just
; title bar for too long during a
; binary load. (It was cleared by
; CantCont above, and title may
; have changed by MrsMake above)
pop [rsNew]
;If we could assume DOS 3.0 or greater, (we can't yet) we could set
;dx to (ACCESS_READ OR LOCK_WRITE) SHL 8 OR MD_SQI
fLoadActive
jne @F
call TDataStart ;init for movement of DATA stmts
; from prs(s) to mrs
jne LfDone ;[37] brif no error occurred
@@:
mov dx,MD_SQI
call OpenChan ;Sets [chanCur] which tells LfDone to
; close the file. Tells AsciiLoad/Binary
; Load to use this channel
jne LfDone ;brif error
and [mrsCur.MRS_flags3],NOT FM3_NotFound
call B$IDISK_SINP ;al = 1st byte from file
; errors trapped @ LfDone
jcxz Empty_File ;brif trying to load an empty file
push ax ;save 1st char
call B$IDISK_BAKC ;put the char back in the buffer
pop ax ;restore al = 1st char of file
cmp al,BINSAV_1stByte
jne DoAsciiLoad ;brif not binsav flag
call fEditorActive ; is this the Editor?
jnz DoAsciiLoad ; brif so, no binary files
mov al,ER_BFM ; otherwise, it is an error
jmp LfDone
Empty_File:
xchg ax,cx ;ax = 0 == no error
jmp SHORT LfDone
DoAsciiLoad:
mov ax,[otxInsert] ;ax = line where text is to be inserted
cmp ax,LF_NewDoc
jb DoMerge ;brif doing a MERGE or $INCLUDE
or [mrsCur.MRS_flags2],FM2_AsciiLoaded
SetStartOtx ax ;start load at offset 0
DoMerge:
DbAssertRelB [txdCur.TXD_scanState],ne,SS_EXECUTE,CP,<LoadFile: bad scan state>
call AsciiMerge ;merge file at offset [ax]
;Note: AsciiLoad can make recursive
; calls to LoadFile()
; some errors trapped @ LfDone
;al = error code (0 if no error)
LfDone:
mov [txtErr.TXER_oRs],UNDEFINED
;don't try to position cursor to
; offending stmt for errors caused
; by LoadFile. Values of txtErr.otx
; and txtErr.oSrc are unimportant
; if txtErr.oRs = UNDEFINED
cmp al,ER_FNF ;test for FileNotFound
jne NotInInit ;brif not
cmp [fInitialized],FALSE
jne NotInInit
FLoadActive
jne NotInInit
cmp [cInclNest],0 ;test for INCLUDE file not found
jne NotInInit ; brif include file not found
test [cmdSwitches],CMD_SW_RUN ;Want to Run program, or just load it?
jne NotInInit ;brif /RUN <filename>
and [mrsCur.MRS_flags3],NOT FM3_NotFound
sub ax,ax ;qb <filename> when filename not
; found should just create file
;al = error code (0 if no error)
NotInInit:
sub ah,ah ;ax = result
xchg si,ax ;si = result
call CloseChan ;close [chanCur]
; don't care about int 24 errors
; here, since we were reading
FLoadActive
jne LfExit1 ;brif not done with multi-module load
; or recursive $INCLUDE
call TDataEnd ;move DATA stmts from prs(s) to mrs
je NoDataMoveErr
mov si,ER_OM ;return out-of-memory error
NoDataMoveErr:
call LfDupRs ;if duplicate mrs or prs encountered
; during load, set si=errcode
; if dup mrs, (sets txtErr.oRs),
; it will be reset to UNDEFINED if mrs
; is discarded.
or si,si ;test result
je MakeMods_Perm ; brif no error
or [flagsTm],FTM_PrsDefDeleted
;make sure discarded PRSs are freed
call MrsDeactivate ; required so NextMrsFile starts
; at the beginning
TempMrs_Discard_Loop:
call far ptr NextMrsFile ; activate next file mrs
inc ax ; no more file mrs's?
jz @F ; brif so - exit loop
test [mrsCur.MRS_flags],FM_TEMPORARY
je TempMrs_Discard_Loop
mov ax,[txtErr.TXER_oRs]
cmp ax,[grs.GRS_oMrsCur]
je DmNotErr
mov [txtErr.TXER_oRs],UNDEFINED
;don't try to position cursor to
; offending stmt for error.
DmNotErr:
call MrsDiscard
jmp TempMrs_Discard_Loop
MakeMods_Perm:
mov al,FE_PcodeMrs+FE_CallMrs+FE_SaveRs+FE_TextMrs
mov bx,OFFSET CP:ModulePermanent ;reset 'fTemporary' in each mrs
call ForEachCP
@@:
; We call ChkAllUndefPrsSaveRs here to make sure that FTM_PrsDefDeleted
; flag is reset. If this flag didn't get reset, then the next PRS
; that is created would accidentally be freed in TxtChange. The case
; where this flag doesn't get reset is when we don't find any Temp mrs's.
call ChkAllUndefPrsSaveRs ;search for new defining
;references for Prs entries
;which had their "defining"
;reference deleted.
LfExit1:
mov ax,[oRsSave]
inc ax
je LfExit2 ;brif entry mrs has been discarded
dec ax ;ax = oRs to restore
push ax
call RsActivateCP ;activate it (for ExStRun)
LfExit2:
mov ax,[grs.GRS_oRsCur]
inc ax ;test for UNDEFINED
jne LfExit3 ;brif not - we need an oMrsCur
DbAssertRel [grs.GRS_oMrsMain],ne,UNDEFINED,CP,<LoadFile: no oMrsMain>
mov ax,[grs.GRS_oMrsMain]
mov [rsNew],ax ;if UserInterface has not yet been
; called, we need rsNew non-zero
; to cause windows to be initialized
push ax
call RsActivateCP ;activate oRsMain
LfExit3:
mov ax,[otxCurSave]
mov [grs.GRS_otxCur],ax ;restore caller's grs.otxCur (or
; set it to 2 if NewStmt was done)
; This is done for ExStRunFile.
call RtPopHandler ;restore caller's runtime error handler
; (saved on stack by RtPushHandler)
pop [chanCur]
cmp [chanCur],0 ;do we need to update channel for
jz NoChanUpd ;recursive opens?
call UpdChanCur ;Update channel
NoChanUpd:
; The user interface needs the source and scratch buffers to be the
; same size. If the scratch is smaller, then horizontal scrolling
; (like CTRL-PGDN) could cause garbage characters to be displayed.
; This does not cause any data or code corruption, but is visually
; disconcerting. Since this is only a visual bug, special out-of-
; memory handling is not necessary.
PUSHI ax,<dataOFFSET bdEMScratch>;pass Scratch buffer
mov ax,[ps.PS_bdpSrc.BDP_cbLogical] ; get current size
push ax
call TxtGrowPsSrcEmScratch ;grow bdEmScratch
;can ignore OM errors here since cbLogical will have been
;trimmed to the same value for both buffers.
PopfDirect ax ;restore direct mode status
call fEditorActive ; Did we start with /EDITOR
jz @F ; no, ok to exit
test [mrsCur.MRS_flags2],FM2_NoPcode ; is it a document table?
jnz @F ; brif so, it is ok
; We must insure that we are using a document table, so create
; a new one
mov ax,DATAOFFSET szUntitled; psz of title
push ax ; first parm to OgNamofPsd
push ax ; parm to CbSz
call CbSz ; get the length
push ax ; second parm to OgNamofPsd
call OgNamofPbCb ; convert to OgNam
xchg bx,ax ; save OgNam in BX
or bx,bx ; did we make the OgNam?
mov ax,ER_OM ; assume not, prepare OM error
jz NoOgName ; no, give OM Error
push bx ; ogNam
PUSHI ax,<(FM2_File + FM2_NoPCode) * 100h> ; flags
call MrsMake ; create the MRS
NoOgname:
or ax,ax ; is there an error
jz @F ; brif not, all ok
or si,si ; is there already an error?
jz SaveError ; brif not, use the new error
@@:
xchg ax,si ;ax = result
or ax,ax ;set condition codes for caller
je LfExit ;brif no error occurred
SaveError:
mov [txtErr.TXER_errCode],ax
LfExit:
cEnd
;*********************************************************************
; SetPsErrMsg
; Purpose:
; Set the parser's error message buffer to the name of a
; register set (module or procedure).
; Entry:
; ax = oRs (condition codes set based on value in ax)
; Exit:
; ps.bdErr contains ASCII name of module/procedure.
; ax = 0 if out-of-memory (condition codes set based on value in ax)
;
;*********************************************************************
cProc SetPsErrMsg,<PUBLIC,NEAR>
cBegin
push ax ;preserve the oRs
cCall RsActivateCP,<ax> ;activate the oRs
pop ax ;ax = oRs
mov bx,[prsCur.PRS_ogNam]
or ax,ax ;test the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -