📄 prsnt1.asm
字号:
;=============================================================================
; prsnt1.asm - Parser's Non-Terminal Functions (continued)
;
; Copyright <C> 1985, Microsoft Corporation
;
; Purpose:
; In an ideal world, these functions would reside in prsnt.asm.
; They live here to reduce the number of include files needed
; by prsnt.asm, so MASM won't run out of memory when assembling it.
; See general comments at top of prsnt.asm for non-terminal function
; conventions.
;
;
;=============================================================================
include version.inc
PRSNT1_ASM = ON
includeOnce architec
includeOnce names
includeOnce opstmt
includeOnce opid
includeOnce parser
includeOnce prstab
includeOnce psint
includeOnce qbimsgs
includeOnce types
includeOnce util
assumes CS,CP
assumes DS,DGROUP
assumes SS,DGROUP
assumes ES,DGROUP
sBegin DATA
szB DB "B",0
szBF DB "BF",0
szF DB "F",0
sEnd DATA
sBegin CP
subttl misc parser nonterminal recognizers
;**********************************************************************
; PARSE_RESULT NEAR NtRwB()
;
; Purpose:
; Parse the identifier B
; Exit:
; Returns PR_GoodSyntax (and consumes token) or PR_NotFound
;
;******************************************************************
PUBLIC NtRwB
NtRwB PROC NEAR
mov ax,dataOFFSET szB
jmp SHORT CheckRw1
NtRwB ENDP
;**********************************************************************
; PARSE_RESULT NEAR NtRwBF()
;
; Purpose:
; Parse the identifier BF
; Exit:
; Returns PR_GoodSyntax (and consumes token) or PR_NotFound
;
;******************************************************************
PUBLIC NtRwBF
NtRwBF PROC NEAR
mov ax,dataOFFSET szBF
mov cx,8002h ;highbit says don't change case
; of existing namtbl id, incase
; user has variable 'bF'
jmp SHORT CheckRw
NtRwBF ENDP
;**********************************************************************
; PARSE_RESULT NEAR NtRwF()
;
; Purpose:
; Parse the identifier F (as found in the statement LINE ...,B F
; Exit:
; Returns PR_GoodSyntax (and consumes token) or PR_NotFound
;
;******************************************************************
PUBLIC NtRwF
NtRwF PROC NEAR
mov ax,dataOFFSET szF
CheckRw1:
mov cx,8001h ;highbit says don't change case
; of existing namtbl id, incase
; user has variable 'f'
NtRwF ENDP
; Fall into CheckRw
;*******************************************************************************
; PARSE_RESULT NEAR CheckRw(ax=pbRw,cx=cbRw)
;
; Purpose:
; Checks for the reserved word and eats it if found.
;
; Entry:
; ax=pbRw - Pointer to string containing the reserved word to check for.
; cx=cbRw - Length of the reserved word string.
;
; Exit:
; PR_GoodSyntax or PR_NotFound based on finding the pseudo reserved word.
;
;***************************************************************************
CheckRw PROC NEAR
mov bx,[pTokScan] ;bx points to current token
cmp [bx.TOK_class],CL_id
jne CheckNotFound ;branch if token isn't an identifier
push bx ;save pointer to token
;ax = pbRw, cx = cbRw
call ONamOfPbCb ;ax = oNam (or 0 if out-of-memory)
; no-need to check for out-of-memory
; since comparison will fail, and we'll
; get another out-of-memory when we
; try to insert the text in a txttbl.
pop bx ;restore pointer to token
cmp [bx.TOK_id_oNam],ax
jne CheckNotFound
call ScanTok ;skip identifier
mov al,PR_GoodSyntax
ret
CheckNotFound:
sub al,al ;return(PR_NotFound)
ret
CheckRw ENDP
sEnd CP
sBegin DATA
str255Include DB 7,'INCLUDE'
str255Static DB 6,'STATIC'
str255Dynamic DB 7,'DYNAMIC'
IMETA_INCLUDE EQU 0
IMETA_STATIC EQU 1
IMETA_DYNAMIC EQU 2
NMETA EQU 3
EVEN
tstr255Meta DW OFFSET DGROUP:str255Include
DW OFFSET DGROUP:str255Static
DW OFFSET DGROUP:str255Dynamic
EVEN
topMeta DW op_Include
DW op_Static
DW op_Dynamic
sEnd DATA
sBegin CP
;**********************************************************************
; STATICF(PARSE_RESULT) NtEmitRem(opcode)
;
; Purpose:
; Emit opcode which encapsulates text argument for REM, DATA, _, or '.
; Meta command syntax is:
; $DYNAMIC
; $STATIC
; $INCLUDE <spaces>:<spaces>'<filename>'
;
; Entry:
; opcode is: opStRem for REM, opQuoteRem for ', opStData for DATA
;
; Exit:
; opcode = opcode to be generated
; An end-of-line terminates all of the above.
; Sequential runs of a single char > 6 will be specified by opRemRepeat.
; An additional terminator for a DATA statement is : outside of quotes.
; Condition codes set based on value in al
;
;******************************************************************
cProc NtEmitRem <PUBLIC,NODATA,NEAR>,<si,di>
parmW opcode
localW oSrcRemArg
localW fCompress
localW oDstCbRem
localW oDstTerm
localW cbMeta
localW iMeta
localB fMetaOk
;fMetaOk is intended to allow meta commands only if the 1st
; non-white-space char on the line is '$'
cBegin NtEmitRem
mov [fCompress],sp ;we start by assuming that we want
; to compress text
mov [fMetaOk],1 ;$meta commands are valid
mov bx,[pTokScan] ;bx points to current token
mov si,[bx.TOK_oSrc] ;si = offset in source line to token
mov ax,[opcode] ;ax = opcode to be emitted
;skip past reserved word in source buffer based on opcode
inc si ;assume its a single-quote rem
cmp ax,opQuoteRem
je KeywordSkipped ;branch if we're doing '
inc si ;'REM' is 3 bytes long
inc si
cmp ax,opStRem
je KeywordSkipped ;branch if we're doing REM
inc si ;else it must be 'DATA' (4 bytes long)
mov [fCompress],0 ;don't compress DATA text
KeywordSkipped:
;si = offset in current source line to 1st byte of remark's data
; i.e. to 1st byte beyond "REM", "DATA", "'", "$STATIC" etc.
;
RemLoop:
mov [oSrcRemArg],si ;save offset to start of REM/DATA text
add si,[ps.PS_bdpSrc.BDP_pb] ;convert offset to ptr
; si points to start of source buffer
mov [iMeta],UNDEFINED ;assume we'll see no $<meta>
sub dl,dl ;remember we're not inside a quote
;search for end of remark/DATA
; si points to next byte of remark's data
; dl = non-zero if we're in a DATA statement and within double quotes
; (so we know to not treat : as end-of-stmt)
;
LoopTillEos:
lodsb ;al = next byte of source
or al,al
je J1_EmitRem ;branch if end-of-line
cmp [opcode],opStData
je GotData ;branch if we're scanning a DATA stmt
cmp [fMetaOk],0
je LoopTillEos ;brif $meta commands not legal
cmp al,"$" ;else we're in some form of REM stmt
je CheckMeta ;branch if '$' inside a REM
cmp al," "
je LoopTillEos ;brif haven't seen anything but space
and [fMetaOk],NOT 1 ;$meta commands are no longer valid
; unless we've already parsed one
jmp SHORT LoopTillEos ;test for end-of-line (end-of-REM)
GotData:
cmp al,34 ;compare with '"' (double quote)
jne NotDoubleQuote
not dl ;toggle in-quote state
jmp SHORT LoopTillEos
NotDoubleQuote:
cmp al,":"
jne LoopTillEos ;branch if not ':'
or dl,dl
jne LoopTillEos ;branch if we're inside a "xxx"
J1_EmitRem:
jmp SHORT EmitRem ;else, the DATA stmt is terminated
BadMeta:
mov ax,ER_ADF ; Map all $INCLUDE errors to AFE
call PErrMsg_AX ;al = PR_BadSyntax
jmp NtRemExit
;At this point, we've seen a dollar sign in a REMARK which could
;be the start of a $META directive.
;
CheckMeta:
or [fMetaOk],2 ;$meta commands are now valid until
; the end of this remark
mov di,NMETA ;number of meta commands to search for
MetaLoop:
dec di
js LoopTillEos ;branch if didn't find a $<meta>
mov bx,di ;bx = iMeta
shl bx,1 ;bx = 2*iMeta
mov bx,WORD PTR tstr255Meta[bx]
;bx points to str255 struct for string
mov al,[bx] ;al = length of meta command
inc bx ;bx points to 1st letter of meta
cbw ;ax = cbMeta
mov [cbMeta],ax ;save it for later
xchg cx,ax ;pass byte count in cx
call CmpStrIns ;do a case insensitive string compare
; of strings *bx and *si
jne MetaLoop ;branch if they don't match
;We found a $META command in the REM
;si points past '$' byte of $META directive
mov [iMeta],di ;save meta command's id
or di,di ;test for IMETA_INCLUDE
jne EmitRem ;branch if not $INCLUDE
; got $INCLUDE <spaces>:<spaces>'<filename>'
mov di,si ;di points beyond "$"
add di,[cbMeta] ;di points beyond "$<meta>"
push ds
pop es ;es = DGROUP for repne scasb
jmp short BadMeta ; Always give AFE error
;Copy bytes from source buffer ps.bdpSrc to pcode buffer ps.bdpDst
; oSrcRemArg = offset to first byte to emit
; si points beyond text's terminator
;
EmitRem:
mov di,[opcode] ;di = REM/DATA/<meta> opcode
cmp di,opStData
je ItsData ;brif DATA (leave room for 0-terminator)
dec si ;si points to text's terminator
ItsData:
sub si,[ps.PS_bdpSrc.BDP_pb] ;si = offset beyond last byte to emit
push di ;pass opcode
call Emit16 ;emit opcode
mov cx,[oSrcRemArg] ;cx = offset to first byte to emit
mov ax,si ;ax = offset beyond last byte to emit
sub ax,cx ;ax = size of opcode's argument
push cx ;pass offset to EmitSrc (below)
push ax ;pass cb to EmitSrc (below)
mov cx,[ps.PS_bdpDst.BDP_cbLogical] ;get offset to where cb will be
mov [oDstCbRem],cx ;emitted
cmp di,opStData
je LinkedOpcode ;branch if this opcode has link field
cmp di,opQuoteRem
jne UnlinkedOpcode ;branch if opcode has no column field
LinkedOpcode:
inc ax ;add size of link field to size
inc ax
mov dx,[ps.PS_bdpDst.BDP_pbCur]
sub dx,[ps.PS_bdpDst.BDP_pb] ;dx = #bytes in output buffer
inc dx ;add 2 bytes for cb field
;subtract 1 for 0-terminator
add dx,ax ;dx = offset to 0-terminate DATA stmt
mov [oDstTerm],dx ;save offset to 0-terminate DATA stmt
call Emit16_AX ;emit the size field
mov bx,[pTokScan] ;bx points to current token
mov ax,[bx.TOK_oSrc] ;ax = source column token started in
;for opSQuote, we are emitting the
; column so we can accurately list it.
; For all other opcodes, we are making
; room for a link field
UnLinkedOpcode:
call Emit16_AX ;emit the size field/link field
cmp [fCompress],0 ;should we compress chars in string?
jne CompressText ;brif so
call EmitSrc ;parms were pushed (above)
jmp short ChkOpData
CompressText:
push [oDstCbRem] ;pass offset of cbRem in case
; we compress the text
call EmitSrcCompress ;other parms were pushed (above)
ChkOpData:
cmp di,opStData
jne NotData
mov bx,[ps.PS_bdpDst.BDP_pb]
add bx,[oDstTerm] ;bx points 1 byte beyond dst DATA
mov BYTE PTR [bx],0 ;0-terminate DATA stmt
dec si ;rescan terminator
NotData:
mov bx,[iMeta]
shl bx,1 ;bx = 2 * iMeta
jc GotLastRem ;branch if no more $<meta> commands on
; this line
;generate another opcode for the $META directive
mov ax,topMeta[bx] ;ax = meta directive's opcode
mov [opcode],ax
add si,[cbMeta]
inc si
mov [fCompress],0 ;don't compress $<meta> command text
jmp RemLoop
;si points beyond REM/DATA stmt
GotLastRem:
add si,[ps.PS_bdpSrc.BDP_pb]
mov [ps.PS_bdpSrc.BDP_pbCur],si
call ScanTok ;pTokScan points to end-of-stmt or
; end-of-line token
mov al,PR_GoodSyntax
NtRemExit:
or al,al ;set condition codes for caller
cEnd NtEmitRem
sEnd CP
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -