📄 varmgrc.c
字号:
##############################################################################*/
/***
*ReDirect() - unlink entry @ vm_oVarCur, set FVREDIRECT, put vm_oVarTmp in value
*Purpose:
* 'ReDirect' a variable entry, i.e., unlink it from its hash chain, set
* the FVREDIRECT flag in the entry, and put the offset to the 'real'
* entry (in vm_oVarTmp) into the value field.
*
* Redirection is performed whenever an existing entry is made invalid
* by some new instance of a matching variable, for example, what looked
* like an array at first encounter might be found to be a FUNCTION at
* a later encounter - - - all such array entries (in tMV and all tPV's)
* are redirected to this newly created FUNCTION entry. The scanner
* can then go through and fix up the pcode for each redirected entry,
* since we'll put the oVar for the new entry in the redirected entry.
*Entry:
* vm_fPVCur - module static flag, TRUE if hash table is in tPV, FALSE if tMV.
* mrsCur.bdVar assumed set up, and if vm_fPVCur is TRUE, prsCur is assumed
* to be set up, and the oVarHash field to contain an offset into
* mrsCur.bdVar to the tPV hash table.
* vm_oVarCur is an offset into mrsCur.bdVar to the entry to be redirected.
* vm_oVarTmp is an offset into mrsCur.bdVar to the entry it is to be
* redirected to.
*Exit:
* none.
*Exceptions:
* none.
*******************************************************************************/
VOID NEAR ReDirect()
{
REG1 var *pVar;
REG2 char *pVarBase = mrsCur.bdVar.pb;
REG3 ushort *pHash;
REG4 var *pVarPrev;
REG5 ushort oHashTmp;
/*--------------------------------------------------------------------------
| calculate pointer into hash table to offset to the first entry in the |
| chain; this is just: |
| (base of physical table) + (offset to start of hash table) + |
| (offset into hash table) |
--------------------------------------------------------------------------*/
DbAssertIf(vm_fPVCur, prsCur.oVarHash != UNDEFINED)
pHash = (ushort *)(mrsCur.bdVar.pb +
(vm_fPVCur ?
(prsCur.oVarHash + (mkVar.oNam & HASH_PV_NAMMASK)) :
(0 + (mkVar.oNam & HASH_MV_NAMMASK))));
pVar = (var *)(pVarBase + *pHash); /* point to first entry */
if (*pHash == vm_oVarCur) /* entry is @ start of chain */
*pHash = OHashLinkOf(pVar) & 0xFFFE; /* unlink first entry */
else {
while ((oHashTmp = OHashLinkOf(pVar) & 0xFFFE) != vm_oVarCur) {
DbAssert(oHashTmp != 0) /* better not be end of chain */
pVar = (var *)(pVarBase + oHashTmp);
}
pVarPrev = pVar; /* point to entry prior to one
we wish to unlink */
pVar = (var *)(pVarBase + oHashTmp);
OHashLinkOf(pVarPrev) = OHashLinkOf(pVar);/* unlink the entry */
}
/* at this point, pVar points to the entry being redirected */
FlagsOf(pVar) |= FVREDIRECT;
ValueOf(pVar, oMV) = vm_oVarTmp;
} /* ReDirect */
/***
*FuncSearch() - search the appropriate hash table for FUNCTION case
*Purpose:
* Search the appropriate table (tPV or tMV) in the case where we've
* encountered [DECLARE] FUNCTION.
*Entry:
* vm_fPVCur - module static flag, TRUE if we're to search tPV, FALSE if tMV.
* mrsCur.bdVar assumed set up, and if vm_fPVCur is TRUE, prsCur is assumed
* to be set up, and the oVarHash field is either UNDEFINED (in which
* case we just return), or contains an offset into mrsCur.bdVar to the
* tPV hash table.
*
* mkVar set up as per MakeVariable (below).
*Exit:
* FALSE = no error
* otherwise, the same error code is returned as described for MakeVariable,
* below.
* If no error is returned, then the static vm_fVarFound indicates success or
* failure.
* If vm_fVarFound == TRUE, vm_oVarCur is set to the offset into mrsCur.bdVar to
* the found variable entry, and vm_pVarCur points to the entry.
* If an existing entry has been converted to a FUNCTION entry by the search,
* the static flag fConvtdToFun will be set TRUE.
*Exceptions:
* none.
*******************************************************************************/
ushort NEAR FuncSearch()
{
REG1 var *pVar;
REG2 char *pVarBase = mrsCur.bdVar.pb;
/*--------------------------------------------------------------------------
| calculate offset into mrsCur.bdVar to first entry in appropriate hash |
| chain; this is the contents of: |
| (base of physical table) + (offset to start of hash table) + |
| (offset into hash table) |
--------------------------------------------------------------------------*/
REG3 ushort oVar = *(ushort *)(mrsCur.bdVar.pb +
(vm_fPVCur ?
(prsCur.oVarHash + (mkVar.oNam & HASH_PV_NAMMASK)) :
(0 + (mkVar.oNam & HASH_MV_NAMMASK))));
fConvtdToFun = vm_fVarFound = FALSE; /* initialize */
if ((oVar == 0) || (vm_fPVCur && (prsCur.oVarHash == UNDEFINED)))
return(FALSE); /* empty hash chain - not found */
for (pVar = (var *)(pVarBase + oVar); /* loop init. */
pVar != (var *)pVarBase; /* oVar = 0 ==> end of chain */
pVar = (var *)(pVarBase + (OHashLinkOf(pVar) & 0xFFFE))) {
/* loop re-init */
if (mkVar.oNam != ONamOf(pVar))
continue;
if (!(FlagsOf(pVar) & FVFUN)) {
if (FlagsOf(pVar) & (FVFORMAL | FVCOMMON | FVSTATIC | FVCONST |
FVSHARED | FVDECLDVAR))
return (PRS_ER_RE | ER_DD);
if (OTypOf(pVar) != mkVar.oTyp)
if (FlagsOf(pVar) & FVEVEREXPLICIT)
return (PRS_ER_RE | ER_DD);
else {
DbAssert(mkVar.oTyp <= ET_MAX)
FlagsOf(pVar) = (FlagsOf(pVar) & ~ 0x07 | mkVar.oTyp);
}
fConvtdToFun = TRUE; /* set flag if converting to FUN */
ValueOf(pVar, oPrs) = PrsRef(mkVar.oNam, PT_FUNCTION, mkVar.oTyp);
/* set value field */
DbAssert(ValueOf(pVar, oPrs) != UNDEFINED)
/* error if prs not found */
FlagsOf(pVar) |= (FVFUN | FVDECLDVAR | FVEVEREXPLICIT);
FlagsOf(pVar) &= ~FVARRAY;
} /* if entry flag FVFUN is FALSE */
if (vm_fVarFound) /* is this a second match in the */
return(PRS_ER_RE | ER_DD); /* same chain? If so error */
/* now, note that we've found a match and save this oVar, but keep
looking, in case there's another matching name, which would trigger
the above error ... */
vm_fVarFound = TRUE;
vm_oVarCur = (char *)pVar - mrsCur.bdVar.pb;
vm_pVarCur = pVar;
} /* while not at end of hash chain */
return (FALSE); /* no errors */
} /* FuncSearch */
/***
*ModSharedChk() - check tPV for matches to a new module SHARED variable
*Purpose:
* Check the tPV (of prsCur) for a match to a given (new) module SHARED
* variable. If a match is found, redirect it, i.e., unlink the tPV entry
* from its hash chain, set the FVREDIRECT flag in it, and place
* the offset to the new module SHARED variable in its value field.
*
* Note: This is now optimized based on the knowledge that it's ONLY used
* used for FUNCTION declarations or definitions.
*
*Entry:
* vm_oVarTmp = offset into mrsCur.bdVar to a new module SHARED variable.
* vm_fPVCur assumed to be TRUE
* other inputs set up as for FuncSearch (above)
*Exit:
* TRUE - no error.
* FALSE - some error from FuncSearch, assumed to be a rude edit case
* (so we can count on mrsCur.bdVar being tossed out).
* In this event, the static variable 'errVal' will be contain the
* error return, and (non-RELEASE only) the mkVar.flags2 bit
* MV_fTrashTable will be set.
*Exceptions:
* none.
*******************************************************************************/
boolean ModSharedChk()
{
if (errVal = FuncSearch()) {
return(FALSE); /* some error found - quit looking */
}
if (vm_fVarFound)
ReDirect();
return (TRUE);
} /* ModSharedChk */
/***
*GetDefaultType - given the logical 1st char of a var name, get default oTyp
*Purpose:
* Given the logical first char of a name, return the default oTyp of that name.
* Note that 'logical first char' implies the third char of a name which starts
* with 'FN' and the first char of any other name.
*Entry:
* namChar
*Exit:
* oTyp
*Exceptions:
* none.
*
*******************************************************************************/
ushort NEAR GetDefaultType(namChar)
char namChar;
{
namChar &= 0xDF; /* convert to upper case */
DbAssert ((namChar == ('.' & 0xDF)) ||
((namChar >= 'A') && (namChar <= 'Z')));
return(namChar == ('.' & 0xDF)) ? ET_R4 : (ushort)ps.tEtCur[(namChar) - 'A'];
} /* GetDefaultType */
/***
*MakeVariable - Search for var, create if req'd, return offset to it
*Purpose:
* Given a variable encountered by the parser or scanner, search for the
* variable; if not found (and no error conditions detected), create the
* variable in the tMV or the appropriate tPV and return an offset into
* mrsCur.bdVar ('oVar') to the value field in the variable entry; this offset
* goes in the pcode stream.
*
*Entry:
* mrsCur set up; it is assumed that bdVar is a heap owner.
* prsCur either set up, or grs.oPrsCur is UNDEFINED if no procedure is
* currently active
* mkVar.oNam - global name table offset for the name of the input variable
* mkVar.oTyp - global type table offset for the (perhaps assumed) type of the
* input variable. In the case of an implicitly typed variable,
* ET_IMP should be passed; in this instance, MakeVariable will
* determine the appropriate default type, based on the oNam.
* In the case of a reference to a record element, the oTyp of the
* record variable cannot be set by the caller; in this special
* case, mkVar.oTyp must be set to UNDEFINED by the caller.
* mkVar.flags - global 2-bytes of bit flags used to describe the variable
* encountered. One byte contains flags which are set in
* atypical situations, the other contains flags to be tested
* in common situations.
* Note that the FVIMPLICIT and FVFNNAME flags are not inputs,
* however - - - these can be set or reset on input: MakeVariable
* (now) sets these based on the oTyp and oNam fields (respectively)
* mkVar.cDimensions - number of dimensions in an array variable; required
* for correctly allocating the array descriptor, and setting
* the dimension count for array variables. Only meaningful
* when FVINDEXED is set, and FVFUNCTION is not (and the variable
* name does not start with 'FN') (Note that FVINDEXED is
* considered to be set whenever FVFORCEARRAY is set).
* mkVar.flags2 & MV_fONamInOTyp - set when the oType field is either ET_FS or
* ET_FT and the fsLength field is the oNam of a CONSTant
* which gives the length of the fixed length string/text.
* mkVar.flags2 & MV_fDontCreate - set when MakeVariable is called JUST to
* search for an existing variable. Does not create a new variable
* if one is not found with this flag set. Non-RELEASE code checks
* that no other modification of the variable table takes place
* when this is TRUE.
*
*Exit:
* The return value is an oVar if the high bit (bit 15) is clear, and
* it's an error code if the high bit is set.
*
* If the high bit is not set (and retval is an oVar), if the input mkVar.oTyp
* was incorrectly assumed by the caller (i.e., implicitly typed), mkVar.oTyp
* will contain the correct oTyp on exit.
*
* If the high bit is not set, if a CONSTant var entry was found, mkVar.flags2
* will have the MV_fConstFound bit set (always reset on exit otherwise).
*
* If the high bit is set, the LSB is a scanner error code and the MSB
* minus bit 15 is a parser action code. The scanner error code is an
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -