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

📄 txtutil.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 4 页
字号:
	TITLE	TXTUTIL - Text Table Management Routines

;============================================================================
;
; Module: TxtUtil.asm - Text Table Management Routines
; System: Quick BASIC Interpreter
;
;	--------- --- ---- -- ---------- ----
;	COPYRIGHT (C) 1985 BY MICROSOFT, INC.
;	--------- --- ---- -- ---------- ----
;
;
;============================================================================

	.xlist
	include version.inc
	TXTUTIL_ASM = ON
	includeOnce architec
	includeOnce context
	includeOnce executor
	includeOnce heap
	includeOnce lister
	includeOnce msgshort
	includeOnce names
	includeOnce optables
	includeOnce opcontrl
	includeOnce opid
	includeOnce opmin
	includeOnce opstmt
	includeOnce opaftqb4
	includeOnce parser
	includeOnce pcode
	includeOnce qbimsgs
	includeOnce rtinterp	;just needed for CbStrucErrRet
	includeOnce rtps
	includeOnce scanner
	includeOnce txtint
	includeOnce txtmgr
	includeOnce ui
	includeOnce variable

	.list

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

externFP B$GetCompSwitches	; runtime routine for QuickLIB switch info


;-------------------------------------------------------------------------
;		DATA Segment Declarations
;-------------------------------------------------------------------------

sBegin	DATA

PUBLIC	fViewInclude
fViewInclude	DB 0	;non-zero if included source lines are visible
PUBLIC	fLnNotIncl
fLnNotIncl	DB 0	;static return value of LnOfOtx, OtxOfLn, OtxBolOfOtx
			;zero if given line was an INCLUDEd line
PUBLIC	cInclNest
cInclNest	DB 0	;$INCLUDE nesting depth.  Non-zero if currently loading
			;an $INCLUDE file

;used to pass info to DoDescan()
descanTo	DB 0

PUBLIC	compSwitches
compSwitches	DB 0	;Set by SetCompSwitches()
fPreScanAsChg	DB 0	;non-zero when PreScanAsChg is active

;statics needed by ChkLastAs()
oNamAs		DW 0
oRsAs		DW 0
otxAsDelStart	DW 0
otxAsDelEnd	DW 0

externB fLoadInclude	



sEnd	DATA


;-------------------------------------------------------------------------
;		CODE (execution-time) Segment Functions
;-------------------------------------------------------------------------

sBegin CODE
assumes CS,CODE

;Table of all the opcodes that are searched for by PreScanAsChg
;
tOpAs	LABEL WORD
	opTabStartAll	AS
	opTabEntry	AS,opOffLd
	opTabEntry	AS,opOffSt
	opTabEntry	AS,opNoType	;assumed to be 2nd to last
	opTabEntry	AS,opEot

;Table of all opcodes which represent  AS <usertype>
tOpAsType LABEL WORD
	opTabStart	ASTYPE
	opTabEntry	ASTYPE,opAsType
	opTabEntry	ASTYPE,opStDefFn    ;must preceed Declare,Sub,Function
	opTabEntry	ASTYPE,opStDeclare
	opTabEntry	ASTYPE,opStSub
	opTabEntry	ASTYPE,opStFunction
	opTabEntry	ASTYPE,opEot

;Table of all the opcodes that are op_Include (or opStInclude [03])
;
tOpReInclude LABEL WORD
	opTabStart	RI
	opTabEntry	RI,op_Include
	opTabEntry	RI,opEot

;Table of all the opcodes which affect the setting of Compiler switches
;Can't use opTab... macros because we need opEot as 1st entry in table.
;
tOpCompSw LABEL WORD
	opTabStart	CSW
	opTabEntry	CSW,opStOnError
	opTabEntry	CSW,opEvGosub
	opTabEntry	CSW,opEvOff
	opTabEntry	CSW,opEvOn
	opTabEntry	CSW,opEvStop
			CSW_EventMax EQU CSW_opEvStop
	opTabEntry	CSW,opStResume
	opTabEntry	CSW,opStResume0
	opTabEntry	CSW,opStResumeNext
	opTabEntry	CSW,opEot

;These functions are included in the CODE segment, because they
; are called by runtime code, and we wouldn't want to swap in
; the entire CP segment just to do these functions.

;*************************************************************************
; DescanOpcode(opcode)
;
; Purpose:
;	Given the address of an executor for an opcode, return the opcode's
;	id.  For example, give, ExStStop, it would return opStStop.
;
; Entry:
;	parm1: ushort - opcode's executor offset into CODE segment
;
; Exit:
;	AX = opcode id
;
;*************************************************************************
cProc	DescanOpcode,<PUBLIC,FAR,ATOMIC>	
	parmW	opcode
cBegin
	mov	bx,[opcode]
	mov	ax,cs:[bx-2]
cEnd

sEnd	CODE

;-------------------------------------------------------------------------
;		CP (compile) Segment Functions
;-------------------------------------------------------------------------


					; the current text table

sBegin	CP
assumes CS,CP

;*************************************************************************
; TxtTblSegCurCP(), TxtSegCurCP()
;
; Purpose:
;	Return the segment address for the start of the current text table.
;
; NOTE: TxtTblSegCurCP never returns the adr of the direct mode buffer.
;	TxtSegCurCP return the adr of the direct mode buffer if
;	  grs.fDirect is TRUE.
;
; Entry:
;	The structure txdCur identifies the current text table.
;	For TxtSegCurCP, if grs.fDirect is TRUE, the direct mode
;	   text table (grs.bdlDirect) is used instead.
;
; Exit:
;   TxtTblSegCurCP:  ES = segment address,
;	             cx preserved (callers depend on this)
;   TxtSegCurCP:     ES = segment address
;	             All other registers preserved (including flags)
;		     (callers depend on all being preserved)
;
;*************************************************************************
PUBLIC	TxtTblSegCurCP
TxtTblSegCurCP PROC NEAR
	DbChk	ConStatStructs		;ensure static structures
	GETSEG	es,[txdCur.TXD_bdlText_seg],,<SPEED,LOAD> ;[2]
	ret
TxtTblSegCurCP ENDP

PUBLIC	TxtSegCurCP
TxtSegCurCP PROC NEAR
	pushf
	push	bx
	DbChk	TxdCur			;perform sanity check on txdCur
	DbChk	ConStatStructs		;ensure static structures
	mov	bx,dataOFFSET txdCur.TXD_bdlText
	cmp	[grs.GRS_fDirect],FALSE
	je	NotDirectMode		;branch if not in direct mode
	mov	bx,dataOFFSET grs.GRS_bdlDirect
NotDirectMode:
	GETSEG	es,[bx.BDL_seg],bx,<SPEED,LOAD> ;[2] es = seg adr of text table
	pop	bx
	popf
	ret
TxtSegCurCP ENDP

sEnd	CP				

sBegin	SCAN				
assumes CS,SCAN 			

;***
; TxtSegCurSCAN
;
; Purpose:
;	Return the segment address for the start of the current text table.
;	Added as revision [20].
;
;	TxtSegCurSCAN returns the adr of the direct mode buffer if
;	  grs.fDirect is TRUE.
;
; Entry:
;	The structure txdCur identifies the current text table.
;	if grs.fDirect is TRUE, the direct mode
;	   text table (grs.bdlDirect) is used instead.
;
; Exit:
;   TxtSegCurSCAN:   ES = segment address
;	             All other registers preserved (including flags)
;		     (callers depend on all being preserved)
;
;*************************************************************************
PUBLIC	TxtSegCurSCAN
TxtSegCurSCAN PROC NEAR
	assumes ds,NOTHING		
	pushf
	push	bx
	DbChk	TxdCur			;perform sanity check on txdCur
	DbChk	ConStatStructs		;ensure static structures
	mov	bx,dataOFFSET txdCur.TXD_bdlText
	cmp	[grs.GRS_fDirect],FALSE
	je	@F			;branch if not in direct mode

	mov	bx,dataOFFSET grs.GRS_bdlDirect
@@:
	GETSEG	es,ss:[bx.BDL_seg],bx,<SPEED,LOAD> ;[2] es = seg adr of text table
	pop	bx
	popf
	ret
	assumes DS,DATA 		
TxtSegCurSCAN ENDP

sEnd	SCAN				


sBegin	CP				
assumes CS,CP				

;**************************************************************
; void DoDescan()
; Purpose:
;	Called indirectly by SystemDescan and ModuleRudeEdit.
;	See comments in those functions.
;
; Entry:
;	descanTo = SS_PARSE or SS_RUDE
; Exit:
;	grs.fDirect = FALSE
;	returns ax = non-zero (so ForEach... continues)
;
;**************************************************************
DoDescan PROC NEAR
	DbAssertRelB [descanTo],ne,SS_EXECUTE,CP,<DoDescan - bad descanTo>
	SetfDirect al,FALSE		;turn off direct mode if on
	and	[grs.GRS_flags],NOT FG_allSsExecute
	cmp	[txdCur.TXD_scanState],SS_RUDE
	jae	DdExit			; brif text table is already SS_RUDE
					; or lower (we never descan lower
					; than SS_RUDE)
	cmp	[txdCur.TXD_scanState],SS_EXECUTE
	jne	NotExec			;we always descan at least to SS_PARSE
	call	SsDescan		;descan from SS_EXECUTE to SS_PARSE
	DbChk	TxdOps			;see if rude scanner inserted bad opcode
	;Only call TxtMoved if we descanned the text table, if we call
	; it every time we call DoDescan, Txt Edits slow down because we
	; have lost the cache unnecessarily.
	call	TxtMoved		;can't depend on cached text offsets
					;reset History and Watch info too
NotExec:
	cmp	[descanTo],SS_RUDE
	jne	DdExit			;brif only descanning to SS_PARSE
	push	WORD PTR ([descanTo])	;pass SS_RUDE to SsRudeScan
	call	SsRudeScan
	DbChk	TxdOps			;see if rude scanner inserted bad opcode

DdExit:
	mov	ax,sp			;return non-zero result for ForEachCP
	ret
DoDescan ENDP

;**************************************************************
; SystemDescan()
; Purpose:
;	This is called to descan all module and procedure text table's
;	to SS_PARSER or lower.  It occurs after some edits like
;	the definition of a function, to force the scanner to re-check
;	all references to the function for type compatability.  It
;	is also called just before a Binary SAVE is executed, so we
;	write opcodes to the file instead of executor addresses.
; SystemDescanRude() is identical, but all text tables are descanned
;	to SS_RUDE instead of SS_PARSE.
;
; This function never results in an error (not even out-of-memory)
;
; Exit:
;	grs.fDirect = FALSE
;
;**************************************************************
PUBLIC	SystemDescanCP
SystemDescanCP PROC NEAR
	test	[flagsTm],FTM_NoSsExecute ;speed opt - skip if all
	jnz	SystemDescanCPX 	;txt tables are already SS_PARSE
					;or lower
	mov	al,SS_PARSE
	mov	[descanTo],al

	;descan each prs in a module before descanning the module itself
	mov	al,FE_PcodeMrs+FE_CallMrsAfter+FE_PcodePrs+FE_SaveRs
	mov	bx,CPOFFSET DoDescan
	call	ForEachCP		;DoDescan returns no error codes
	or	[flagsTm],FTM_NoSsExecute ;all txt tables at least in
SystemDescanCPX:			;SS_PARSE scan state
	SetfDirect al,FALSE		;turn off Direct mode
	ret
SystemDescanCP ENDP

cProc	SystemDescanRudeCP,<PUBLIC,NEAR>
cBegin
;	If a def fn is active, we need to deactivate it.  ForEachCP
;	saves/restores oPrsCur.  ModuleRudeEdit frees all def fn's.
;	The combination of these two would cause ForEachCP to attempt
;	to activate a freed prs if oPrsCur is for a def fn.

	mov	ax,[grs.GRS_oPrsCur]	
	inc	ax			; have an active procedure?
	jz	NotDefFn		; brif not
	dec	ax			
	cCall	FieldsOfPrs,<ax>	; returns dl = proctype
	cmp	dl,PT_DEFFN		; is it a def fn?
	jne	NotDefFn		; brif not
	call	PrsDeactivate		; deactivate active def fn
NotDefFn:				

	mov	al,FE_PcodeMrs+FE_CallMrs+FE_SaveRs
	mov	bx,CPOFFSET ModuleRudeEdit
	call	ForEachCP		;ModuleRudeEdit returns no error codes
cEnd

cProc	SystemDescanRude,<PUBLIC,FAR>
cBegin
	call	SystemDescanRudeCP
cEnd


;**************************************************************
; ModuleRudeEdit()
; Purpose:
;	This is called after some edit has occurred which could have
;	made existing variable tables and/or pcode inconsistent.
;	For example, after a DEFINT statement is inserted in a text
;	table.  It descans to SS_RUDE all text tables in this module.
;	It then eliminates the module's variable table (which
;	holds all procedure variables for this module as well).
;
;	Resets the NM_fShared name table bit and for each name table
;	entry, maps NMSP_Variable to NMSP_UNDEFINED
;
; Exit:
;	This function never results in an error (not even out-of-memory)
;	ax = non-zero (so it can be called by ForEachCP
;	grs.fDirect = FALSE
;
;**************************************************************
cProc	ModuleRudeEdit,<PUBLIC,NEAR>
cBegin

	test	[mrsCur.MRS_flags2],FM2_NoPcode OR FM2_Include
	DJMP	jne  NoVarTbl		;brif this mrs has no variable tables

	test	[mrsCur.MRS_flags],FM_AllSsRude ;speed opt - skip if all module
	jnz	FreeVarTbl		;text tables are already in SS_RUDE

	test	[txdCur.TXD_flags],FTX_mrs
	je	GotSubOrFunc		;brif a SUB or FUNC txt tbl is active
	call	PrsDeactivate		;deactivate DEF FN or DECLARE (if any)
					; since DEF FNs are discarded.  This
					; lets us call ForEachCP with FE_SaveRs
					; without crashing when we try to
					; restore a discarded DEF FN.
GotSubOrFunc:
	call	VarDealloc		;must free all owners in module var
					;  table BEFORE rude descan, because
					;  rude descan resets the oVarHash field
					;  in each prs to UNDEFINED
	mov	[descanTo],SS_RUDE

	;descan each prs in a module before descanning the module itself
	mov	al,FE_CallMrsAfter+FE_PcodePrs+FE_SaveRs
	mov	bx,CPOFFSET DoDescan
	call	ForEachCP		;DoDescan can return no error codes

;start of revision [39]
	;Note that the below scheme depends on the fact that NextPrsInMrs
	;finds the first prs in the table if grs.GRS_oPrsCur is UNDEFINED, and
	;then subsequent prs's based on grs.GRS_oPrsCur.  It is not safe to
	;call ForEachCP to do this, because that scheme depends on walking
	;the prs chain, and PrsFree causes PrsCur to be Unlinked.  The next
	;call ForEach pass uses the unlinked entry, and thinks that it must
	;be looking at prsCur.

⌨️ 快捷键说明

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