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

📄 txtload.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	push	si			;pass search start text offset
	PUSHI	ax,<CODEOFFSET tOpProcHdr>
	call	TxtFindNextOp		;ax=txt offset to next opcode from list
	xchg	di,ax			;di=txt offset

	mov	ax,si			;pass search start text offset in ax
	call	TxtSkipOp		;ax = offset to opcode after si
	cmp	ax,di
	je	SameOp			;brif this opcode is in list of
					;opcodes which could be deleted

	;some opcode not found in tOpProcHdr is on this line,
	;remember that we can't delete this line.
	
	mov	[otxLastBol],UNDEFINED
SameOp:
	mov	al,[opIndex]		;al = id of previous opcode
	cmp	al,PROCHDR_opStRem
	jae	GotRem			;brif REM or bol opcode
	;current opcode is opStDefType, op_Static, or op_Dynamic, delete it.
	push	ax			;save id of previous opcode

	push	di			;pass ptr beyond opcode to be deleted
	push	si			;pass ptr to opcode to be deleted
	call	TxtMoveDown		;delete current opcode

	pop	ax			;restore al = id of previous opcode
	mov	[fDeleted],1		;remember that something on this
					; line has been deleted
	mov	di,si			;otxCur remains unchanged for next
					; iteration of loop (because we
					; deleted the opcode)
	cmp	al,PROCHDR_op_Dynamic
	jne	NotDyn			;brif not $DYNAMIC
	mov	[fProcDyn],1
NotDyn:
	cmp	al,PROCHDR_op_Static
	jne	ChkNextOp
	mov	[fProcDyn],FALSE
	jmp	SHORT ChkNextOp

;al = PROCHDR_xxx for current opcode (we know its a REM or Begin Of Line opcode)
GotRem:
	cmp	al,PROCHDR_opBolMin
	jae	ChkNextOp		;brif opcode isnt opQuoteRem or opStRem
	lea	dx,[si+6]		;dx = otxCur + 6
	cmp	di,dx
	jbe	ChkNextOp		;brif REM has no text after it (kill it)
	;REM has significant text after it - can't delete it
	mov	[otxLastBol],UNDEFINED	;remember we can't delete this line
;Now test the opcode after this one
ChkNextOp:
	cmp	[txtFindIndex],PROCHDR_opBolMin
	jb	SqNext
	;next opcode is an opBol or opBolSp or opEot
	cmp	[otxLastBol],UNDEFINED
	je	SqNoDel			;brif we can't delete this line
	cmp	[fDeleted],FALSE
	je	SqNoDel			;brif some opcodes on this line has
					;not been deleted
	cmp	al,PROCHDR_opBolMin
	jae	SqNoDel

	;we have deleted all opcodes on this line, delete opBol as well.
	push	word ptr [TxtFindIndex] ;preserve index of last TxtFind call

	push	[otxLastBol]
	push	di
	call	TxtDelete
	mov	di,[otxLastBol]
	pop	ax
	mov	[TxtFindIndex],al	;restore TxtFindIndex for last TxtFind
					; call prior to TxtDelete
SqNoDel:
	mov	[fDeleted],FALSE	;so far, we've deleted nothing on line
	mov	[otxLastBol],di		;remember where last start of line
					; was so we can delete it later if
					; nothing significant is on the line
SqNext:
	mov	dl,[txtFindIndex]
	mov	si,di			;advance to next op (otxCur = otxNext)
	cmp	dl,PROCHDR_opEndProg
	jae	SqExit			;brif end of table
	jmp	SqLoop

SqExit:
cEnd


;*************************************************************
; boolean NEAR LoadEnterProc(otxProcDef)
; Purpose:
;	Called during ASCII Load when we encounter a SUB or FUNCTION
;	statement.  SUB/FUNCTION definition line has already been emitted.
;	Insert synthetically generated DEFxxx statements to make this
;	text table in the same state as the module's table where the
;	SUB/FUNCTION statement was seen.
;
; Entry:
;	procedure's text table is active
;	otxProcDef = where we were in module's text table when the procedure
;	   definition was seen.  We need this so we can update
;	   linked lists which thread through the module's text table.
;
; Exit:
;	modifies ps.bdpDst
;	grs.fDirect = FALSE
;	If out-of-memory,
;	    returns 0 (FALSE),
;	    text table which generated OM error is active.
;	else
;	    ax is non-zero
;	    procedure's text table is active
;	condition codes set based on value in ax
;
;*************************************************************
;.errnz ET_SD - ET_I2 - 4	 ;code assumes ET_I2...ET_SD
cProc	LoadEnterProc,<PUBLIC,NEAR>,<si,di>
	parmW	otxProcDef
	localW	oPrsProc
	localW	otxStartRem
	localW	otxStartBlank
	localW	otxPrev
	localB	prevType
	localB	fInRemBlock
cBegin
	mov	ax,[grs.GRS_oPrsCur]
	mov	[oPrsProc],ax		;remember which proc we just entered

	mov	si,[txdCur.TXD_bdlText_cbLogical]
					;si = current size of text table
					;     before synthetic code emitted
	SetStartOtx ax			;ax = start of text
	mov	bx,dataOFFSET tEtTemp
	call	OtxDefType		;fill tEtTemp with default types
					; i.e. ET_R4 for all letters


	;If we've seen a $DYNAMIC more recently than a $STATIC before
	;place where this procedure occurred in source file,
	;emit a $DYNAMIC at start of procedure's text table
	
	FLoadActive
	je	NotLoading		;brif being called for an edit, not load
	SetStartOtx ax			;ax = start of text
	mov	dh,al			;old state was $STATIC
	mov	dl,[fDynArrays]		;dl = new state ($STATIC or $DYNAMIC)
	mov	[fDynArraysMod],dl	;save so LoadExitProc can restore
	call	InsertDynDiff
	je	J1_LentEx		;return FALSE if out-of-memory error

NotLoading:
	;emit opStDefType opcodes which represent text table's initial state.
	PUSHI	ax,<dataOFFSET tEtTemp>
	PUSHI	ax,<dataOFFSET ps.PS_tEtCur>
	SetStartOtx ax			;ax = start of text
	call	InsertEtDiff
	je	J1_LentEx		;return FALSE if out-of-memory error
	neg	si
	add	si,[txdCur.TXD_bdlText_cbLogical]
					;si = txdCur.bdlText.cbLogical
					;   - cbLogical before insertion
					;   = #bytes of synthetic pcode emitted
	push	si
	mov	bx,si
	SetStartOtx si			;si = start of text
	call	TxtInsUpdate		;update line count from 0 to si for
DbAssertRel ax,ne,0,CP,<Unexpected OM error in LoadEnterProc>
	pop	si			;si = number of bytes inserted
	FloadActive			;test if we are currently loading -
					;  if not then we don't migrate rem's
	jne	InsOk			
J1_LentEx:
	jmp	LentEx			;return value in ax
InsOk:

	;Find the start of a contiguous block of Comments/Bol opcodes
	;that precedes the SUB definition.  Keep this block with the
	;procedure window, not the module window.  This allows users
	;to put comment blocks before their SUB/FUNCTION definitions
	
	;When done, we'll move the comment block, and delete the blank
	;lines preceeding the comment block.  If we didn't delete these
	;blank lines, several contiguous subs with 1 blank line between
	;would leave a huge block of blank lines.
	
	call	PrsDeactivate		;make module's txt table active
	mov	di,[otxLastProc]	;otxCur = otxLastProc
	mov	[otxStartRem],di
	mov	[otxStartBlank],di
	mov	[prevType],PROCHDR_opBol
	mov	[fInRemBlock],0
LentLoop:
	push	di			;pass otxCur to TxtFindNextOp
	PUSHI	ax,<CODEOFFSET tOpProcHdr>
	call	TxtFindNextOp
	cmp	dl,PROCHDR_opEot
	je	LentLoopEx
	mov	cx,[txdCur.TXD_bdlText_cbLogical]
	sub	cx,[cbAftMerge]		;cx = otx beyond any MERGEd text
	cmp	ax,cx
	jb	NotPastMerge		;brif not beyond MERGE's insertion point
	mov	dl,PROCHDR_opEndProg	;treat it like reaching opEndProg
	xchg	ax,cx			;use otx of merge insertion point
NotPastMerge:
	mov	dh,[prevType]		;dh = txtFindIndex for prev iteration
	mov	[prevType],dl		;dl=type of cur opcode, dh=type of prev
	push	dx

	xchg	di,ax			;update di = otxCur, ax = otxPrev
	mov	[otxPrev],ax
	call	TxtSkipOp		;ax = otx beyond opcode otxPrev

	pop	dx			;restore dl=type of cur, dh=type of prev
	cmp	ax,di
	mov	ax,di			;setup for branch to StartBlankBlock
	jne	StartBlankBlock		;brif next opcode wasn't in tOpProcHdr

	cmp	dh,PROCHDR_opBolInclude
	jae	StartBlankBlock		;brif last line came from $INCLUDE file
	cmp	dl,PROCHDR_opBolMin
	jb	InCommentBlk		;brif current op isn't a BOL, bolSp, or
					; opEndProg opcode
	cmp	dh,PROCHDR_opBolMin	;check type of previous opcode
	jb	InCommentBlk		;brif not looking at blank line

	;We now know that di points to opBol that terminates a blank line
	;If any non-blank lines have been seen since the last blank line,
	;reset the start of the blank line block.
	
	cmp	[fInRemBlock],0
	je	StartRemBlock		;brif not start of new block of blanks
	mov	ax,[otxPrev]		;ax points to start of blank line

;we saw blank line - don't include it with SUB's comment header block
; but include it in block of leading blank lines to be deleted.
; ax either points to start of blank line, or within line that is to
; remain at module level.
;
StartBlankBlock:
	mov	[fInRemBlock],0
	mov	[otxStartBlank],ax	 ;reset start of blank line block

;Found an opcode not in tOpProcHdr, or a blank line.
;di points to next opcode found which was in table (di > ax).
;
StartRemBlock:
	mov	[otxStartRem],di	;otxStartRem = otxCur
	jmp	SHORT LentNext

InCommentBlk:
	mov	[fInRemBlock],1		;causes any subsequent blank lines
					; to reset otxStartBlank
LentNext:
	cmp	[prevType],PROCHDR_opEndProg
	jb	LentLoop		;brif end of text table

;[otxStartRem] points to 1st opcode before opStSub which could be
; included with SUB.  For example, if pcode was:
;  opBol opStPrint opQuoteRem
;  opBol opRem
;  opBol opStSub
; otxStartRem would point to the opQuoteRem opcode, meaning the 2nd
; line should be included with the SUB.
; Move otxStartRem to the start of the next line.
;
LentLoopEx:
	push	[otxStartBlank]		; push otx arg.
	call	OtxBolNext0		;ax points to next opBolxxx if ax
	mov	[otxStartBlank],ax	; doesn't currently point to opBolxxx

	push	[otxStartRem]		; push otx arg.
	call	OtxBolNext0		;ax points to next opBolxxx if ax
	mov	[otxStartRem],ax	; doesn't currently point to opBolxxx
	mov	di,[otxProcDef]
	sub	di,ax			;di = cbMove (otxProcDef - otxStartRem)
	je	NoMove			;brif there is any text to be moved

; move cbMove(di) bytes from module's to proc's text table
; Start by making sure there is room for temp buffer & in proc's text table
;
	push	[oPrsProc]
	call	PrsActivateCP		;make new proc's txt table active

	push	di			;pass cbMove
	call	TxtFree			;make sure there's room in prs txt tbl
	je	JE1_LentEx		;brif out-of-memory error
	call	PrsDeactivate		;make module's txt table active

	;Move pcode from module's text table to bdlScrap	[8]
	;  CALL TxtCopyScrap(otxStartRem, StartOtx, di, TRUE)		[8]
	push	[otxStartRem]		;pass otx for start of move
	SetStartOtx ax			;[39]ax = StartOtx
	push	ax			;copy to start of scrap. 0 offset
	push	di			;pass cbMove
	push	sp			;push TRUE so text will be deleted
					;	from text table
	call	TxtCopyScrap		;move bytes from txdCur to bdlScrap
JE1_LentEx:
DJMP	je	LentEx			;return FALSE if out-of-memory

	push	[oPrsProc]
	call	PrsActivateCP		;make new proc's txt table active

	;note that we already called TxtFree to ensure we have enough memory
	;so no error is possible.
	
	call	TxtInsScrap		;insert bdlScrap in txdCur @ si

	mov	bx,di			;bx = cbMove
	add	bx,si			;bx = offset beyond pcode insertion
	call	TxtInsUpdate		;update line count for inserted lines
DbAssertRel ax,ne,0,CP,<Unexpected OM error 2 in LoadEnterProc>

	;squeeze all $DYNAMIC, $STATIC and DEFxxx statements out
	;of block copied from module.  They are redundant after
	;calling InsertEtDiff and InsertDynDiff
	
	call	SqueezeDefs		;takes parm in si
NoMove:
	call	PrsDeactivate		;make module's txt table active

;Delete redundant synthetic DEFxxx statments generated by last LoadExitProc()
;if no user-generated statements were loaded in between.
;If we didn't do this, each time SOME programs are Ascii loaded and saved
;and they contain one or more blank lines between subs, and so
;they grow by the introduction of these redundant DEFtype statements.
;
	mov	ax,[otxDefEnd]
	cmp	ax,[otxStartBlank]
	jne	NoDeadDefTypes		;brif non-synthetic lines exist
					; between end of synthetic lines and
					; start of leading blank lines
	mov	ax,[otxDefStart]
	mov	[otxStartBlank],ax	;else delete synthetic ones
NoDeadDefTypes:
	;Now delete blank lines that preceeded the comment block.
	mov	ax,[otxStartBlank]
	mov	[otxLastProc],ax
	push	[otxUpdLinks]		;pass otxUpdLinks to UpdateLinks
	push	ax			;pass otxLastProc to UpdateLinks
	;NOTE: parms to UpdateLinks are on stack
	push	ax			;pass start of block to delete
	push	[otxStartRem]		;pass end of block to delete
	call	TxtDelete		;delete blank lines from mrs text table
	call	UpdateLinks		;update linked lists which thread
					; through module's pcode up to where
					; SUB/FUNCTION line was encountered
	DbChk	TxdOps			;check for bad linked lists through
					; pcode, bad opcodes, etc.

	;save current def type state so we can bring module
	;back up to date at LoadExitProc (if any DEFxxx stmts occur
	;within the procedure being loaded)
	
	mov	ax,[otxLastProc]	;text offset for new end of module
	mov	bx,dataOFFSET tEtTemp
	call	OtxDefType		;fill tEtTemp with default types
					; at end of module

	mov	[otxUpdLinks],StartOtx	;next UpdateLinks will start at
					; start of new proc
	push	[oPrsProc]
	call	PrsActivateCP		;make new proc's txt table active

	;Tell AsciiMerge that we've changed text tables, and
	;where to insert next line in the procedure's text table
	
	mov	ax,[txdCur.TXD_bdlText_cbLogical]
	sub	ax,CB_EMPTY_TEXT - StartOtx ;ax = offset to opEndProg
	mov	[otxNewInsert],ax
	DbAssertRel ax,ne,0,CP,<LoadEnterProc: return value zero> 
LentEx:
	mov	[ps.PS_bdpDst.BDP_cbLogical],0 ;release temp buffer
	or	ax,ax			;set condition codes for caller
cEnd

;*************************************************************
; boolean NEAR LoadExitProc()
; Purpose:
;	Called during ASCII Load when we encounter an END SUB or
;	END FUNCTION statement.
;
; Entry:
;	procedure's text table is active
;
; Exit:
;	If out-of-memory
;	   returns psw.c set
;	else
;	   ax = otx where next stmt should be inserted in module's
;	        text table
;	module's text table is active
;
;*************************************************************
PUBLIC	LoadExitProc
LoadExitProc PROC NEAR
	push	si			;save caller's si
	push	[otxUpdLinks]
	push	[txdCur.TXD_bdlText_cbLogical]
	call	UpdateLinks		;update linked lists which thread
					; through procedure's pcode
	DbChk	TxdOps			;check for bad linked lists through

⌨️ 快捷键说明

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