⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 txtload.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	TITLE	txtload.asm - ASCII Load Functions

;==========================================================================
;
;Module:  txtload.asm - ASCII Load Functions
;System:  Quick BASIC Interpreter
;
;=========================================================================*/

	include		version.inc
	TXTLOAD_ASM = ON
	includeOnce	architec
	includeOnce	context
	includeOnce	conint		
	includeOnce	fdb
	includeOnce	heap
	includeOnce	names		
	includeOnce	opid
	includeOnce	opmin
	includeOnce	opstmt
	includeOnce	opaftqb4
	includeOnce	parser
	includeOnce	pcode
	includeOnce	qbimsgs
	includeOnce	rtinterp
	includeOnce	rtps
	includeOnce	rttemp
	includeOnce	sb
	includeOnce	scanner
	includeOnce	txtmgr
	includeOnce	txtint
	includeOnce	ui
	includeOnce	util
	includeOnce	stack2		

	includeOnce	edit		


	ASC_TAB		EQU 09h
	ASC_LF		EQU 0Ah
	ASC_CR		EQU 0Dh
	ASC_EOF 	EQU 1AH
	ASC_DBL_QUOTE	EQU 22h
	ASC_QUOTE	EQU 27h

	assumes	DS,DATA
	assumes	SS,DATA
	assumes ES,NOTHING


	externFP	B$ISTALCTMPSUB	
	externFP	B$ISTDALCTMP	


sBegin	DATA
	extrn	b$PTRFIL:WORD	;Read only for QBI - channel Ptr

	extrn	szUntitled:BYTE 	


fInQuote DB 0
PUBLIC	fMergeInSub
fMergeInSub DB 0		;non-zero if MERGING a file into a SUB
				; in this case, LoadEnterProc & LoadExitProc
				; will never be called.

;temp buffers for filename before and after Normalization [7]
PUBLIC NormFname
NormFname 	DB	FILNAML DUP (?)	;buffer for temp storage of filename 

	EVEN				; SD must be word-aligned!
PUBLIC sdNormFname
sdNormFname	SD	<0,dataOFFSET NormFname> ;string descriptor 

	externB	b$BAS_EXT		;".bas" constant
	externW	b$PN_NAME		

	globalB	fLoadInclude,0		; Nonzero when loading include file

	externB fInitialized		; non-zero if we've completed
					; initialization of QB

sEnd	DATA

	EXTRN	B$FREF:FAR
	EXTRN	B$OPEN:FAR
	EXTRN	B$IDISK_SINP:FAR
	EXTRN	B$CLOS:FAR
	EXTRN	B$SEEKSTART:FAR
	EXTRN	B$IDISK_BAKC:FAR
	EXTRN	B$IValidatePath:FAR	
	EXTRN	B$CHAN:FAR


sBegin	CODE

;Table of opcodes which make up '$STATIC, '$DYNAMIC and DEFINT
;and INCLUDE statements.
;The order of entries in this table is VERY important
;
tOpProcHdr LABEL WORD
	opTabStart PROCHDR
	opTabEntry PROCHDR,opStDefType
	opTabEntry PROCHDR,op_Dynamic
	opTabEntry PROCHDR,op_Static
	opTabEntry PROCHDR,opStRem
	opTabEntry PROCHDR,opQuoteRem
	opTabEntry PROCHDR,opBol
		PROCHDR_opBolMin equ PROCHDR_opBol
	opTabEntry PROCHDR,opBolSp
	opTabEntry PROCHDR,opBolInclude
	opTabEntry PROCHDR,opBolIncludeSp
	opTabEntry PROCHDR,opBolLab		
	opTabEntry PROCHDR,opBolLabSp		
	opTabEntry PROCHDR,opEndProg
		;must be 2nd to last entry in table
	opTabEntry PROCHDR,opEot
		;must be last entry in table


sEnd	CODE

sBegin	DATA

;-------------------------------------------------------------------
; During ASCII Load/Merge, we don't update threaded linked lists
; through the pcode for each line, because it is very slow.
; Much faster to update them all at once when we're done.
; This must be done at the following points:
;
;	  1 - when we enter a procedure, since we are moving into
;	      a new text table.
;	  2 - when we exit a procedure, since we are returning to
;	      the module's text table.
;	  3 - When the Load reaches end-of-file
;
; otxUpdLinks represents an offset into the current text table to the
; 1st byte of pcode which UpdateLinks() has not been called for yet.
;
;-------------------------------------------------------------------

	EXTRN	tabStops:WORD	;defined in edit manager

PUBLIC	otxUpdLinks
otxUpdLinks	DW 0

;fDynArrays is initialized to FALSE by AsciiMerge, set TRUE when $DYNAMIC is
;seen by TxtChange, set FALSE when $STATIC is seen by TxtChange
;
PUBLIC	fDynArrays
fDynArrays	DB 0

;fDynArraysMod is set to the value of fDynArrays when we enter a procedure
; (LoadEnterProc), so we can restore the $DYNAMIC/$STATIC state when we
; return back to module level (LoadExitProc).
;
fDynArraysMod	DB 0

;fProcDyn is TRUE if a $DYNAMIC deleted later than a $STATIC,
;i.e. the state at the end of the deleted range was $DYNAMIC
;and not $STATIC.
;
PUBLIC	fProcDyn
fProcDyn	DB 0

;otxLastProc = text offset in module's text table where we were
;when we entered the most recent SUB/FUNCTION.  One way to think
;of it is, when were in a procedure, its the module's text offset
;where the 1st line after the END SUB/FUNCTION will be inserted
;into the module's text table.
;
otxLastProc	DW 0

;otxNewInsert is initialized to UNDEFINED by AsciiMerge,
;and set by LoadEnterProc and LoadExitProc to tell AsciiMerge
;that we switched text tables
;
otxNewInsert	DW 0

;cbAftMerge is initialized to 0 by LoadFile,
;if we're doing anything except a MERGE.  If we're doing a MERGE,
;it marks the insertion point in the main module.
;
cbAftMerge DW 0

;otxDefStart and otxDefEnd represent the range of text in the module's
;text table for DEFtype statements synthetically emitted by LoadExitProc.
;If, when the Load completes, this range is at the end of the module,
;it is discarded.  If we didn't do this, the module would grow with
;every subsequent LOAD/SAVE
;
otxDefStart	DW 0
otxDefEnd	DW 0

;used to keep procedure DEFtype stmts independent of module's DEFtype statements
;
PUBLIC	tEtTemp
tEtTemp		DB 26 DUP(0)

PUBLIC	chanCur
chanCur		DW 0	;current channel # used by Load/Save
PUBLIC	cChansOpen	;only referenced by FLoadActive macro
cChansOpen	DB 0	;number of recursive calls to LoadFile active, bumped
			; every time file is opened, decremented when closed.
cAsciiLoadsActive DB 0	;number of recursive calls to LoadFile active for
			; ASCII files

sEnd	DATA


		;---------------------------------------
		; SUB/FUNCTION Window Support Functions 
		;---------------------------------------

externFP FindFile		

sBegin	CP
assumes	cs,CP

;*************************************************************
; boolean NEAR InsertEtDiff(ax:otxInsert, ptEtBase, ptEtNew)
; Purpose:
;	Emit opBol and opStDefType statements necessary to move from
;	one set of default-types to another.
;	The new pcode is emitted at otxInsert in the current module.
;
; NOTE: This routine doesn't update the line count for any inserted BOLs.
;	The caller is responsible for updating the line count if it is
;	needed.
;
; Entry:
;	ax:otxInsert = offset into current module's text table where
;	   synthetic pcode is to be emitted.
;	ptEtBase and ptEtNew point to an arrays of 26 bytes, one ET_xx for each
;	   letter from A to Z.
;
; Exit:
;	If ptEtBase is identical to ptEtNew, no pcode is emitted.
;	else the pcode emitted is the most efficient way to get from
;	   ptEtBase to ptEtNew.
;	If out-of-memory, returns ax = 0 (and psw.z set)
;	else returns ax non-zero
;
;*************************************************************
DEFLN	STRUC
DEFLN_bolOpcode		DW	0
DEFLN_defOpcode		DW	0
DEFLN_defLinkField	DW	0
DEFLN_defOperandLO	DW	0
DEFLN_defOperandHI	DW	0
DEFLN	ENDS

cProc	InsertEtDiff,<PUBLIC,NEAR>,<si,di>
	parmW	ptEtBase
	parmW	ptEtNew
	localV	deflnNew,<SIZE DEFLN>
cBegin
	xchg	di,ax			;di = insertion point (otxInsert)
	mov	[deflnNew.DEFLN_bolOpcode],opBol
	mov	[deflnNew.DEFLN_defOpcode],opStDefType
	mov	si,CBASETYPEMAX		;init etCur
InsEtLoop:
	dec	si			;decrement etCur
	js	InsEtEnd		;brif we've done all primitive types

	push	[ptEtBase]
	push	[ptEtNew]
	push	si			;pass etCur
	call	EtDiff			;[dx:ax] = bit mask representing
					; difference between base and new type
					; with respect to si (etCur)
	mov	[deflnNew.DEFLN_defOperandLO],ax
	mov	[deflnNew.DEFLN_defOperandHI],dx
	or	ax,dx
	je	InsEtLoop		;brif no difference between base & new

	push	di			;pass otxInsert
	PUSHI	ax,<SIZE DEFLN>
	call	TxtMoveUp		;make room for pcode to be inserted
	je	InsEtExit		;return FALSE if out-of-memory

	;insert new pcode in current text table
	PUSHI	ax,<dataOFFSET txdCur.TXD_bdlText>
	push	di			;pass otxInsert
	lea	ax,[deflnNew]
	push	ax
	PUSHI	ax,<SIZE DEFLN>
	call	BdlCopyTo
	jmp	SHORT InsEtLoop

InsEtEnd:
	mov	ax,sp			;return TRUE (non-zero)
InsEtExit:
	or	ax,ax			;set condition codes for caller
cEnd

;*************************************************************
; boolean InsertDynDiff(ax:otxInsert, dh:fDynBase, dl:fDynNew)
; Purpose:
;	Emit pcode for REM $STATIC or REM $DYNAMIC if fDynBase <> fDynNew.
;	The new pcode is emitted at otxInsert in the current module.
;
; NOTE: This routine doesn't update the line count for any inserted BOLs.
;	The caller is responsible for updating the line count if it is
;	needed.
;
; Entry:
;	ax = otxInsert = offset into current module's text table where
;	   synthetic pcode is to be emitted.
;	dh = fDynBase = 1 if we were already in $DYNAMIC mode.
;	dl = fDynNew = TRUE if we want to move into $DYNAMIC mode.
; Exit:
;	ax = 0 if out-of-memory error (psw.z set as well)
;
;*************************************************************
PUBLIC	InsertDynDiff
InsertDynDiff PROC NEAR
	push	si			;save caller's si,di
	push	di
	xchg	di,ax			;di = text offset where pcode is to go
	cmp	dh,dl
	je	InsDynGoodExit		;brif we're already in mode we want

	mov	si,op_Static
	or	dl,dl
	je	ItsStatic		;brif new state is $STATIC
	mov	si,op_Dynamic
ItsStatic:
	;insert the pcode into text table in reverse order
	push	di			;push source of move to TxtMoveUp
	PUSHI	ax,10d			;push number of bytes to insert
	call	TxtMoveUp
	or	ax,ax
	je	InsDynExit		;return FALSE if out-of-memory

	GetSegTxtTblCur es		;es = seg adr of heap entry for txt tb
	mov	ax,opBol
	stosw				;insert beginning-of-line opcode
	mov	ax,opStRem
	stosw				;insert REM opcode
	sub	ax,ax
	stosw				;insert rem's cb operand
	mov	ax,si			;ax = op_Static or op_Dynamic
	stosw
	sub	ax,ax
	stosw				;insert op_Dynamic/op_Static's operand
InsDynGoodExit:
	mov	ax,sp			;return TRUE (non-zero)
InsDynExit:
	pop	di			;restore caller's si,di
	pop	si
	or	ax,ax			;set condition codes for caller
	ret
InsertDynDiff ENDP

;*************************************************************
; void SqueezeDefs(si:otxCur)
; Purpose:
;	Squeeze out all opStDefType, op_Dynamic and op_Static opcodes
;	from otxCur to the end of the current text table.
;	We squeeze them out and synthetically generate new ones
;	to eliminate redundant statements which could be introduced
;	as a result of moving SUBs and FUNCTIONs to their own text tables
;	during ASCII load.
; Entry:
;	si = text offset where we are to start deleting opcodes
; Exit:
;	The static variable [fProcDyn] is TRUE if a $DYNAMIC deleted
;	later than a $STATIC, i.e. the state at the end of the deleted
;	range was $DYNAMIC and not $STATIC.
;
;*************************************************************
cProc	SqueezeDefs,<PUBLIC,NEAR>,<si,di>
	localW	otxLastBol
	localB	fDeleted
	localB	opIndex
cBegin
	sub	ax,ax
	mov	[fProcDyn],al		;default state is $STATIC
	mov	[fDeleted],al		;so far we've deleted nothing
	dec	ax			;ax = UNDEFINED
	mov	[otxLastBol],ax

	push	si			;pass otxCur
	PUSHI	ax,<CODEOFFSET tOpProcHdr>
	call	TxtFindOp		;ax = text offset to 1st found opcode
					;dl = [txtFindIndex]
	cmp	dl,PROCHDR_opEot
	jb	NotEot
	jmp	SqExit			;brif end of table

NotEot:
	xchg	si,ax			;update si = otxCur
	cmp	dl,PROCHDR_opBolMin
	jb	SqLoop			;brif not opBol or opBolSp
	mov	[otxLastBol],si		;save offset to last start of line

;NOTE that TxtFindNextOp(x, p) sets txtFindIndex but
;TxtSkipOp() does not
;dl = txtFindIndex from last call to TxtFind[Next]Op
;
SqLoop:
	mov	[opIndex],dl		;save opcode's id (PROCHDR_xxx)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -