📄 prsutil.asm
字号:
;=============================================================================
; 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 + -