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

📄 prsid.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	call	Emit16
	test	[flags],FEM_ElemOk
	je	EvNoElem2		;brif didn't get .element
	push	[opBase]		;pass EeElements opBase
	call	EmitElements		;parse and emit .elem...
	jmp	SHORT EvExit		;return ax as result

EvNoElem2:
	clc				;return success
EvExit:
cEnd

;*********************************************************************
; STATICF(boolean) EmitElements(ax:opBase)
;	Many modifications during revision [15]
; Purpose:
;	Scan .id[.id...] and emit pcode for construct
;
; Entry:
;	parm1 = opBase = opId_Ld or opId_St or opId_Rf
;	pTokScan points to token for '.'
;	mkVar.oTyp contains the type of the variable
;
; Exit:
;	If syntax error
;	   returns Carry Set and al=PR_BadSyntax after emitting error msg
;	else
;	   returns Carry Clear
;	   pTokScan points beyond end of construct
;
;***********************************************************************
DbPub	EmitElements
cProc	EmitElements,<NEAR>,<si,di>	
	parmW	opBase
cBegin	EmitElements			
EeLoop:
	or	[psFlags],PSIF_fNoPeriod
					;so ScanTok stops at "."
					;get's reset by IdTokNoPeriod
	call	ScanTok			;skip past "." token
	call	IdTokNoPeriod		;check for id token with no period in it
	stc				;prepare to return error
DJMP	jl	EeExit			;brif PR_BadSyntax, carry set

	mov	si,[bx.TOK_id_oNam]	;si = oNam
	mov	di,[bx.TOK_id_oTyp]	;save oTyp in di
	call	ScanTok			;skip id token
	test	[psFlags],PSIF_fBindVars
	je	EeSavTyp		;brif parser not binding variables


	;ask typmgr to convert oNam to oElem
	
	push	si			
	push	di			;pass oTyp so RefElem can test the
					; explicit type if any
	cCall	RefElem 		;ax = oElem (high bit set if error)
;Fix bug where a random error message gets generated for an undefined
;element reference or element type mismatch. Fix this only in QBJ to
;be sure it has no affect on frozen QB4.5.
;Note however that this is thought to be a very safe bug fix.
	mov	si,ax			;save si = oElem
	or	si,si			
	jns	EeSavTyp		;brif no error

	;Either the variable manager hasn't seen this oNam in the variable's
	;TYPE definition or the explicit type conflicted with the actual
	;type.  Tell ParseLine() to return ReParse.
	;We call this instead of PErrMsg_AX so we can continue
	;checking for bad syntax.
	
	and	ah,7Fh			;mask off sign bit. ax = error code
	call	ParseErrTokScan
EeSavTyp:
.errnz	ET_IMP
	or	di,di			;compare di with ET_IMP
	jne	EeNoElem		;brif id is explicitly typed (i.e. id#)
	call	FElements		;check for more record elements
	jne	EeNoElem		;brif didn't get record separator
	mov	ax,opOffLd		
EeEmit:
	call	Emit16_AX		;emit opcode opOffLd
	push	si			;emit oNam/oElem
	call	Emit16
	test	[psFlags],PSIF_fBindVars
	je	EeLoop			;brif parser not binding variables
	mov	ax,[mkvar.MKVAR_oTyp]	;ax = oTyp of last element
					;     (returned by RefElem)
	cmp	ax,ET_MAX_NOFIELDS	;compare it to largest non-fielded
					; 	type
	jbe	EeIdNoPeriod		;brif if not a user defined type
	or	ax,ax			;test the top bit of the oTyp
	jns	EeLoop1 		;if not set we have a user type
EeIdNoPeriod:
	mov	ax,MSG_BadElemRef	;pass error code to ParseErrTokScan
	call	ParseErrTokScan		;As we do for bad element names
					;  we generate a ReParse and 
					;  continue parsing
EeLoop1:				
	jmp	EeLoop	
	
;done with .a.b.c loop
;if mkVar.oTyp is a USER DEFINED TYPE, we need
;to emit a opOffLd, opOffLd or opIdSt with no explicit type.
;EmitOpcode( (oTyp <= ET_MAX) ? opOffLd + opBase + oTyp :
;            (opBase == opId_St) ? opOffSt : opOffLd)
;
;di = ET_IMP or token's explicit type
EeNoElem:
	mov	ax,[opBase]
DbAssertRel	ax,ne,opId_VtRf,CP,<EmitElements: opbase = opId_VtRf>   
DbAssertRel	di,be,ET_MAX,CP,<EmitElements: oTyp is user type>
	add	ax,opOffLd		;ax = opBase + opOffLd
.errnz OPCODE_MASK - 3FFh		
	xchg	ax,di			;di = oTyp, ax = opcode to Emit
	xchg	ah,al			;ah = oTyp
	shl	ax,1			
	shl	ax,1			
	or	ax,di			;ax = opcode with oTyp in high bits
EeEmit2:
	call	Emit16_AX		;emit opOff<Ld|St><Typ>
	xchg	ax,si			;ax = oNam/oElem
	call	Emit16_AX
	clc				;return success
EeExit:
cEnd	EmitElements			

;Tables used to map from opBase to opcodes
twOpBase LABEL WORD			;opBase search table
	dw	opId_St
	dw	opId_Ld
twOpBaseEnd LABEL WORD
CB_OPBASE = twOpBaseEnd - twOpBase

twOpIdMap LABEL WORD
	dw	opIdSt			;opId_St maps to this for scalars
	dw	opVtRf			;opId_Ld maps to this for scalars
	dw	opIdLd			;opId_Rf and opId_VtRf maps to this

twOpAIdMap LABEL WORD
	dw	opAIdSt			;opId_St maps to this for arrays
	dw	opAVtRf			;opId_Ld maps to this for arrays
	dw	opAIdLd			;opId_Rf and opId_VtRf maps to this

;*********************************************************************
; MapBaseOp
; Purpose:
;	Map an opBase (opId_St etc.) to an opcode.
; Entry:
;	ax = value to search for (opId_St etc.)
;	bx = ptr to table of opcodes which cooresponds to twOpBase
; Exit:
;	ax = opcode
;
; Alters ES
;
;*********************************************************************
MapBaseOp PROC NEAR
	mov	dx,CPOFFSET twOpBase
	mov	cx,CB_OPBASE
	jmp	MapCpW			;ax = bx[find[ax,dx,cx]]
MapBaseOp ENDP

	
;*********************************************************************
; ushort NEAR SubRef(oNam)
; Purpose:
;	Map the oNam for a SUB to its oPrs.
; Entry:
;	ax = oNam of subprogram
; Exit:
;	if successful, ax = oPrs, carry clear on exit
;	else ps.errCode is set with error code, carry set on exit
;
;*********************************************************************
cProc	SubRef,<PUBLIC,NEAR>
cBegin
	push	ax			;pass oNam of sub
	PUSHI	ax,PT_SUB
	sub	ax,ax
	push	ax
	call	PrsRef			;ax = error or oPrs
	or	ax,ax
	jns	SubRefGood		;brif no error

	;Don't set PSERR_fAlert flag, wait until ScanTime to report the error
	; since user may have just deleted =B from A=B, which would make
	; A now look like both a variable and an implied call.
	mov	ah,PSERR_fRude / 100h	;set rude edit flag in result
	call	ParseErr0		;report it to ParseLine's caller
	stc				;return error result
	jmp	SHORT SubRefExit

SubRefGood:
	call	UndoLogPrs		;remember to free prs entry if
					; we turn this line into a reparse
					; ax is preserved as oPrs
	clc				;return success
SubRefExit:
cEnd

;*********************************************************************
; STATICF(PARSE_RESULT) NtConsumeExp()
;
; Purpose:
;	Parse an expression.
;	If successfully parsed, return PR_GoodSyntax.
;	If one is not found, report error and return PR_BadSyntax.
;	If expression had bad syntax, return PR_BadSyntax.
;	In other words, identical to NtExp(), but it won't take
;	   PR_NotFound for an answer.
; Exit:
;	al = PR_GoodSyntax or PR_BadSyntax, condition codes set accordingly
;
;*********************************************************************
PUBLIC	NtConsumeExp
NtConsumeExp PROC NEAR
	call	NtExp
	je	PErrExpExpr		;brif result == PR_NotFound
					; error "Expected expression"
					; al = PR_BadSyntax
	ret
NtConsumeExp ENDP

;*********************************************************************
; PARSE_RESULT NEAR PErrExpExpr()
;
; Purpose:
;	generate error "Expected expression" and return PR_BadSyntax
; Exit:
;	al = PR_BadSyntax
;
;*********************************************************************
PUBLIC	PErrExpExpr
PErrExpExpr PROC NEAR
	mov	ax,MSG_ExpExp
	jmp	PErrExpMsg_AX		;Error "Expected expression"
					; al = PR_BadSyntax
PErrExpExpr ENDP

;*********************************************************************
; NtExprOrArg()
; 
; Purpose:
;	Parse an expression or an arg based on the value in ax
; Entry:
;	ax is tested for the flag
;	    NTEL_ARGS: if set allow SEG, BYVAL and A() args
;			        otherwise only allow a normal expression
; Exit:
;	same as NtArg
;	
;*********************************************************************
NtExprOrArg PROC
	test	ax,NTEL_ARGS
	jnz	NtArg
	call	NtExp
	mov	dx,0
	ret
NtExprOrArg ENDP

;*********************************************************************
; ExpRParenLastToken
; Purpose:
;	generate the error "expected ')'" referring to the last token
;	consumed
; Exit:
;	al = PR_BadSyntax
;*********************************************************************
ExpRParenLastToken PROC NEAR
	mov	ax,[pTokLastConsumed]	
	mov	[pTokScan],ax		;reset pTokScan to point to ","
					; so it will be highlighted
	mov	ax,IRW_RPAREN		
	jmp	PErrExpRw_Ax		;generated "expected ')'"
ExpRParenLastToken ENDP

;*********************************************************************
; PARSE_RESULT NEAR NtIdCallArg()
;
; Purpose:
;	Try to parse an identifier of the form:
;	   "[BYVAL | SEG] id[([exp[,exp...]])]"
;	This can occur in the following statements:
;	   tkCALL IdSub [tkLParen IdCallArg {tkComma IdCallArg} tkRParen]
;	Tests to ensure that we haven't yet reached the maximum number
;	of args before branching into 
;
;*********************************************************************
PUBLIC	NtIdCallArg
NtIdCallArg PROC NEAR
	cmp	[cIdArgs],MAXARG
	jae	ExpRParenLastToken	;BASCOM can't handle more than 60
					; args, so we shouldn't either
; fall into NtArg
NtIdCallArg ENDP

;*********************************************************************
; STATICF(PARSE_RESULT) NtArg()
;
; Purpose:
;	Parse and generate code for:
;	   [BYVAL | SEG] expression or
;	   array reference of the form x()
;	Emit the following pcode:
;	   [opByval | opSeg] <expression's pcode>
;	   opAIdRfxx(oVar,0)
;	NOTE: BYVAL x() is illegal because it makes no sense
;	      SEG x() is illegal because we don't want to document
;	              the format of array descriptors to outside world.
; Exit:
;	Returns al = PR_NotFound, PR_GoodSyntax or PR_BadSyntax
;	If result is PR_GoodSyntax, bumps cIdArgs by 1, no matter what
;	   recursion takes place and returns
;	   dx = NTEL_ARGS if SEG, BYVAL, or array ref of form x() seen
;		0 otherwise
;
;*********************************************************************
cProc	NtArg,<NEAR,PUBLIC>,<di>
cBegin
	push	[cIdArgs]
	mov	ax,IRW_Byval
	call	TestScan_AX		;see if current token is BYVAL
					;bx points to current token
	.erre	opByval
	mov	di,opByval
	je	GotByvalSeg		;brif got BYVAL keyword
	sub	di,di			;assume no SEG
	mov	ax,IRW_Seg
	call	TestScan_AX		;see if current token is SEG
					;bx points to current token
	jne	NoByvalSeg		;brif didn't get SEG keyword
	mov	di,opSeg
	.erre	opSeg

GotByvalSeg:
	call	ScanTok			;skip BYVAL or SEG token
					;bx points to current token

;di = 0 for no SEG or BYVAL, opByval for BYVAL, opSeg for SEG
;bx points to current token
NoByvalSeg:
	or	di,di
	jne	NotAryArg		;can't have arg of form 'BYVAL A()'
					; or 'SEG A()'
	cmp	[bx.TOK_class],CL_ID
	jne	NotAryArg		;brif token isn't an id
	call	Peek1Tok		;see if its an array ref of the form x()
	mov	ax,IRW_LParen
	call	TestPeek_AX
	jne	NotAryArg		;brif not '('
	call	PeekNextTok
	mov	ax,IRW_RParen
	call	TestPeek_AX
	jne	NotAryArg		;brif not ')'

	;we did get an array reference of the form x()
	;if (!EmitVar(pTokScan, opId_VtRf, 0, FALSE)) return PR_BadSyntax
	
	push	[pTokScan]		;pass pointer to id's token
	PUSHI	ax,opId_Ld		;make opcode a Ld variant
	PUSHI	ax,0			;pass cArgs == 0
	PUSHI	ax,FEM_Ary		;let EmitVar know its an array ref
	call	EmitVar
	jc	NtArgExit		;brif unsuccessful (al = PR_BadSyntax)
	call	ScanTok			;skip id
	call	ScanTok			;skip '('
	call	ScanTok			;skip ')'
	jmp	SHORT ItsAnArg		

NotAryArg:
	or	di,di
	je	MaybeExp		;brif no tokens consumed yet
	call	NtConsumeExp		;error if can't consume an expression
	jle	NtArgExit		;brif result != PR_GoodSyntax
EmitByvalSeg:
	or	di,di
	je	NtArgGood		;brif no BYVAL or SEG parm
	push	di
	call	Emit16			;emit opByval or opSeg
ItsAnArg:
NtArgGood:
	mov	al,PR_GoodSyntax	;return PR_GoodSyntax
	jmp	SHORT NtArgExit

MaybeExp:
	call	NtExp			;consume expression, al = result
NtArgExit:
	pop	dx			;dx = caller's cIdArgs
	inc	dx
	or	al,al			;set condition codes for caller
	jle	NtArgExit1		;brif result != PR_GoodSyntax
	mov	[cIdArgs],dx		;bump cIdArgs
NtArgExit1:
cEnd

;*********************************************************************
; NtExprList
;	Completely rewritten during revision [15]
; Purpose:
;	Parse and generate code for 
;		(expr1, expr2, ..., exprN)
;	Each of these expressions can be:
;	-  An expression
;	-  A scalar or array element
;
;	Called by NtImpliedLetOrCall and EmitElements.
;
;
; Exit:
;	Returns ax = PR_NotFound, PR_GoodSyntax or PR_BadSyntax
;	condition codes set based on value in [al]
;	cx = number of args scanned. 0 if no "(" found.
;if NOT FV_QB4LANG
;	NtELFlags contains output flags
;		NTEL_ARGS is set if an arg of the form x(), or

⌨️ 快捷键说明

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