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

📄 prsutil.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;=============================================================================
; prsutil.asm - Parser's ASM Utility Functions
;
; Copyright <C> 1985, Microsoft Corporation
;
; Purpose:
;	Contains Parser Utility Functions
;
;
;=============================================================================

	include	version.inc
	PRSUTIL_ASM = ON
	includeOnce	architec
	includeOnce	context
	includeOnce	heap
	includeOnce	lister
	includeOnce	parser
	includeOnce	prstab
	includeOnce	prsirw
	includeOnce	psint
	includeOnce	qbimsgs
	includeOnce	scanner
	includeOnce	txtmgr
	includeOnce	variable
	includeOnce	ui
	includeOnce	util

	assumes	DS,DGROUP
	assumes	SS,DGROUP
	assumes	ES,NOTHING

sBegin	CP
assumes	CS,CP

subttl	pcode emitting functions

;=====================================================================
;    B d   S T A T I C   B U F F E R   R O U T I N E S
;=====================================================================



;=====================================================================
;    P C O D E    G E N E R A T I O N    F U N C T I O N S
;=====================================================================

;*********************************************************************
; BOOL NEAR CheckFreeDstBuf(cbExtra)
; Purpose:
;	Checks to see if free space exists for the parser's
;	pcode buffer ps.bdpDst. If the extra space couldn't be
;	obtained, then a parser OM error is issued.
; Entry:
;	cx = cbExtra
; Exit:
;	ax = 0 if out-of-memory error
;	Flags set on value in ax
;
;*********************************************************************
PUBLIC	CheckFreeDstBuf 		
CheckFreeDstBuf PROC NEAR
	PUSHI	ax,<dataOFFSET ps.PS_bdpDst>
	push	cx			;cbExtra
	call	BdCheckFree
	or	ax,ax
	je	CheckFreeOMError	;brif out-of-memory
CheckFreeExit:
	ret
CheckFreeDstBuf ENDP

CheckFreeOMError:
	call	ParseErrOm		;Error "Out of memory"
	sub	ax,ax
	jmp	SHORT CheckFreeExit

		
;*********************************************************************
; VOID NEAR Emit16(code16)
; Purpose:
;	Emit 16 bits of pcode to parser's pcode buffer ps.bdpDst
;
;*********************************************************************
cProc	Emit16,<PUBLIC,NEAR,NODATA>
	parmW	code16
cBegin	Emit16
	mov	ax,code16
	call	Emit16_AX
cEnd	Emit16

;**********************************************************************
; VOID NEAR Emit16_0
; Purpose:
;	Emit 16 bits of 0 to parser's pcode buffer ps.bdpDst
;
;**********************************************************************
;**********************************************************************
; VOID NEAR Emit16_AX
; Purpose:
;	Emit 16 bits (in AX) to parser's pcode buffer ps.bdpDst
;
;**********************************************************************
PUBLIC	Emit16_0
PUBLIC	Emit16_AX
Emit16_0 PROC NEAR
	sub	ax,ax			;ax = 0
Emit16_0 ENDP				;fall into Emit16_AX
Emit16_AX PROC NEAR
	DbChkPsStk			;see if this is a new high-water stack
	mov	bx,[ps.PS_bdpDst.BDP_cbLogical]
	inc	bx
	inc	bx
	cmp	bx,[ps.PS_bdpDst.BDP_cbPhysical]
	ja	Emit16Grow		;brif dest buffer needs to grow
Emit16GotRoom:
	mov	[ps.PS_bdpDst.BDP_cbLogical],bx
	mov	bx,[ps.PS_bdpDst.BDP_pbCur]
	mov	[bx],ax			;store pcode in buffer
	inc	bx
	inc	bx
	mov	[ps.PS_bdpDst.BDP_pbCur],bx
Emit16Exit:
	ret
Emit16_AX ENDP
Emit16Grow:
	push	ax			;save pcode to be emitted
	push	bx			;save new value of cbLogical
	mov	cx,2			;need 2 more bytes
	call	CheckFreeDstBuf 	;see if enough free space
	pop	bx			;restore new value of cbLogical
	pop	ax			;restore pcode to be emitted
	jne	Emit16GotRoom		;brif buffer grown successfully
	jmp	SHORT Emit16Exit

PUBLIC	Emit32
cProc	Emit32,<PUBLIC,NEAR,NODATA>
	parmW	code32HIGH
	parmW	code32LOW
cBegin	Emit32
	mov	ax,code32LOW
	call	Emit16_AX		;Emit least significant word first
	mov	ax,code32HIGH
	call	Emit16_AX		;Emit most significant word second
cEnd	Emit32

;*********************************************************************
; VOID NEAR EmitSrc(oSrcText, cbText)
;
; Purpose:
;	Copy bytes from source buffer ps.bdpSrc to pcode buffer ps.bdpDst.
;
; Entry:
;	oSrcText is an offset into the source buffer for 1st byte to copy
;	cbText = number of bytes to be copied
;
; Exit:
;	<text> is copied from the source buffer to the destination pcode buffer.
;	If cbText is odd, an extra filler byte is appended to <text> to keep
;	pcode buffer even-byte aligned.
;	If out-of-memory error, ps.errCode = ER_OM
;
;*********************************************************************
cProc	EmitSrc,<PUBLIC,NEAR,NODATA>,<si,di>
	parmW	oSrcText
	parmW	cbText
cBegin	EmitSrc
	mov	di,cbText		;round cbText (si) up to even value
	inc	di
	and	di,0FFFEH
	mov	cx,di
	call	CheckFreeDstBuf 	;make sure enough free space exits
					;in pcode buffer
	je	EmitSrcExit		;brif out-of-memory

;	set si -> where to copy chars from in bdpSrc
	mov	si,[ps.PS_bdpSrc.BDP_pb]
	add	si,[oSrcText]		


;	push arguments for call
	PUSHI	ax,<dataOFFSET ps.PS_bdpDst>
	push	si
	push	di
	;BdAppend((bd *)(&ps.bdpDst), ps.bdpSrc.pb + oSrcText, cbText)
	call	BdAppend
	DbAssertRel  ax,nz,0,CP,<EmitSrc: BdAppend returned Out of Memory>

	add	[ps.PS_bdpDst.BDP_pbCur],di  
EmitSrcExit:				
cEnd	EmitSrc

;*********************************************************************
; VOID NEAR EmitSrcCompress(oSrcText, cbText, oDstCbRem)
;
; Purpose:
;	Copy bytes from source buffer ps.bdpSrc to pcode buffer ps.bdpDst.
;	Runs of characters longer than 3 bytes will be compressed and
;	encoded as follows:
;	   Byte 1 - PS_EncodedText
;	   Byte 2 - repeat count for char
;	   Byte 3 - char
;	Chars with ASCII values equal to PS_EncodedText are represented
;	as an encoded char with byte count >= 1.
;
; Entry:
;	oSrcText is an offset into the source buffer for 1st byte to copy
;	cbText = number of bytes to be copied
;	oDstCbRem = offset to emitted cb for this REM
;
; Exit:
;	Encoded <text> is copied from the source buffer to the
;	  destination pcode buffer.
;	If cbText is odd, an extra filler byte is appended to <text> to keep
;	  pcode buffer even-byte aligned.
;	If out-of-memory error, ps.errCode = ER_OM
;
;*********************************************************************
cProc	EmitSrcCompress,<PUBLIC,NEAR>,<si,di>
	parmW	oSrcText
	parmW	cbText
	parmW	oDstCbRem
	localW	cbLeft
	localW	cbCompressed
	localW	cbRep
	localB	chPrev
cBegin	EmitSrcCompress
	push	[ps.PS_bdpDst.BDP_cbLogical] ;save current size of dest

	sub	ax,ax
	mov	[cbCompressed],ax
	mov	[chPrev],al
	inc	ax
	mov	[cbRep],ax
	mov	cx,[cbText]		;round cbText (si) up to even value
	mov	[cbLeft],cx
	inc	cx
	and	cl,0FEH
	jcxz	J1_CompressSkip 	;brif no text
	call	CheckFreeDstBuf 	;make sure pcode buffer has enough room
	jne	CompressTxt		;brif enough room
J1_CompressSkip:
DJMP	jmp	SHORT CompressSkip	;space, brif out-of-memory

CompressTxt:
	push	ds
	pop	es			;es=ds
	mov	si,[oSrcText]
	add	si,[ps.PS_bdpSrc.BDP_pb]
	mov	di,[ps.PS_bdpDst.BDP_pbCur]

;	si = pSrcBuffer 	di = pDstBuffer
;	[cbLeft] = count of bytes remaining to process in src buffer
;	[cbCompressed] = count of bytes compressed from src buffer
;	[chPrev] = last character processed
;	[cbRep] = count of repeated [chPrev] chars processed so far

CompressLoop:
	lodsb				;al = next char
	cmp	al,[chPrev]		;same as last char?
	je	SameChar		;brif so

StartNewRun:				
; Current char does not match last char.  If repeat count for last
; char is > 3 then compress repeated chars out of emitted text.
	call	CompressText		;try to compress txt of last char string
	stosb				;emit current char
	cmp	al,STR_EncodedText	;does this happen to match the
					;special Encode char?
	je	GotSpecialChar		;brif so, do special processing

NoCompress:
	mov	[cbRep],1
	jmp	short CompressNext

; We have a run of identical chars.  If char is "special char" then
; just increment emitted count of special chars.  Else increment
; count of chars seen, and emit the char

SameChar:
	cmp	al,STR_EncodedText	;is this the "special char"?
djmp	je	RunOfSpecialChars	;brif so, bump count in emit buf
	cmp	[cbRep],0FFh		; enough room for this one?
	je	StartNewRun		; brif not -- start a new run
	stosb				;emit char
	inc	[cbRep]
DbAssertRel [cbRep],be,0FFH,CP,<EmitSrcCompress: err1>

CompressNext:
	mov	[chPrev],al		;save new "Last char seen"
	dec	[cbLeft]		;dec remaining char count
	jne	CompressLoop		;brif more to process

CompressDone:
	call	CompressText		;try to compress txt of last char string
	mov	di,[oDstCbRem]		;get offset to emitted cbRem
	add	di,[ps.PS_bdpDst.BDP_pb] ;convert to ptr
	mov	ax,[cbCompressed]
	sub	[di],ax 		;adjust emitted cb for compression
	neg	ax
	add	ax,[cbText]		;adjust and pad size of original
	inc	ax			; for compression
	and	al,0FEH
	add	[ps.PS_bdpDst.BDP_pbCur],ax ;adjust for added text
	pop	[ps.PS_bdpDst.BDP_cbLogical] ;recover entry size
	add	[ps.PS_bdpDst.BDP_cbLogical],ax ;adjust by inserted size
CompressExit:
cEnd	EmitSrcCompress

CompressSkip:
	pop	ax			;clean stack
	jmp	SHORT CompressExit	;and exit quick

;=====================================================================
; We have encountered a char which matches our special flag byte.
; We will emit it as a compressed char record. Note: we have already
; emitted the char by this point.
;=====================================================================

GotSpecialChar:
	add	[cbCompressed],2	;compression record costs us 2 bytes
	js	GotSpecGrow		;brif we need to grow dest buffer

GotSpecCont:
	mov	ah,al			;mov char into high byte
	mov	al,1			;set initial count of chars
	stosw				;emit count and char
	mov	al,ah			;recover char
	jmp	SHORT CompressNext	;process next char

GotSpecGrow:
; We actually need to grow the destination buffer because we have inserted
; enough "special chars" to override the compression savings.
	sub	si,[ps.PS_bdpSrc.BDP_pb] ;conv ptr to offset in case of movement
	sub	di,[ps.PS_bdpDst.BDP_pb] ;conv ptr to offset in case of movement
	mov	cx,2			;size of compression record is 2 bytes
	call	CheckFreeDstBuf 	;ensure enough room in pcode buffer
	je	CompressSkip		;brif out-of-memory
	add	si,[ps.PS_bdpSrc.BDP_pb] ;conv offset back to ptr
	add	di,[ps.PS_bdpDst.BDP_pb] ;conv offset back to ptr
	mov	al,STR_EncodedText	;get back char
	jmp	short GotSpecCont

;=====================================================================
; We are processing a run of special chars. The first one caused us
; to emit an encoded record for the char, so just bump the count
; of these chars.
;=====================================================================

RunOfSpecialChars:
DbAssertRelB [di-3],e,STR_EncodedText,CP,<EmitSrcCompress: err2>
DbAssertRelB [di-1],e,STR_EncodedText,CP,<EmitSrcCompress: err3>

	inc	byte ptr [di-2] 	;bump count of special chars

⌨️ 快捷键说明

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