📄 varmgrc.c
字号:
* error which the user will see, whereas the parser action code is an
* indication to the parser of what action it should take. The codes are
* listed below:
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
* | | | | | | | | | | | | | | | | |
* | E| P| P| P| P| P| P| P| S| S| S| S| S| S| S| S|
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
* E - Error indicator (error if set)
* P - Parser action code - bits set for different codes (includes bit 15 set):
* PRS_ER_RE - Module Rude Edit
* PRS_ER_RP - opReParse placed before statement
* S - Scanner error code - decimal number in LSB (see basicmsg.doc)
*
* If the return value is an error code, and the mkVar.flags2 MV_fTrashTable
* bit is set, then the caller MUST take action to 'throw away' mrsCur.bdVar;
* this flag set on error return indicates that the table has been modified
* somehow and cannot be used dependably.
* Note that this is a non-RELEASE flag; assertion code is used to ensure
* that a rude edit error is returned whenever this flag is TRUE.
*
* Note that ER_IER ('Internal Error') is used to signal the case where
* the caller had the mkVar.flags2 MV_fDontCreate bit set on input and a
* matching entry was not found.
*
* Note that an oVar (pVar) is not an offset (pointer) to the start (low word)
* of the appropriate variable entry, rather it's an offset (pointer) to the
* value field in the entry. Other fields are referenced from a pVar via
* negative offsets.
*
* On exit, the following input flag bits are reset to FALSE in mkVar.flags:
* FVASCLAUSE, FVFNNAME, FVFORCEARRAY, FVFUNCTION, FVIMPLICIT,
* FVINDEXED, FVLVAL, FVCONST
* On exit, the MV_fONamInOTyp and MV_fDontCreate bits are always reset in
* in mkVar.flags2.
*Exceptions:
* none.
*
*******************************************************************************/
ushort NEAR MakeVariable()
{
REG1 ushort flags;
REG2 var *pVar;
REG3 ushort retval;
REG4 ushort createMask;
REG5 ushort oHashCreate;
REG6 ushort oNamPrs;
REG7 ushort namChar;
REG8 boolean fCreate; /* used to signal that we don't
want to create input variable */
REG9 ushort inputFlags = mkVar.flags; /* save input mkVar.flags in case
we must change them locally */
ushort mkVarONam;
ushort mkVarOTyp;
uchar mkVarCDims;
boolean fTemp;
DbAssert(grs.oMrsCur != UNDEFINED)
DbChkGrs() /* sanity check on grs, mrsCur, and prsCur */
if (mkVar.flags2 & MV_fONamInOTyp) {
mkVarONam = mkVar.oNam;
mkVarOTyp = mkVar.oTyp;
mkVarCDims = mkVar.cDimensions;
/* mkVar.fsLength is really an oNam for a CONSTant. We must search local
var table for this constant (tMV too if we're at proc level) and
use it's value to set the input oTyp to the appropriate fixed length
string constant */
DbChkoNam(mkVar.fsLength)
mkVar.flags2 &= ~MV_fConstFound;
mkVar.oNam = mkVar.fsLength;
mkVar.flags = FVIMPLICIT;
mkVar.oTyp = ET_I2; /* CONSTant MUST be an I2 */
vm_fPVCur = (grs.oPrsCur != UNDEFINED);
retval = StdSearch();
if (!vm_fVarFound && !retval && !(vm_fPVCur = !vm_fPVCur))
/* if we searched tPV and didn't find it, better be in tMV */
retval = StdSearch();
/* restore input values of mkVar struct (must do this here so mkVar.flags
is correct in case of error) */
mkVar.oNam = mkVarONam;
mkVar.oTyp = mkVarOTyp;
mkVar.flags = inputFlags;
mkVar.cDimensions = mkVarCDims;
if (retval || !vm_fVarFound || !(mkVar.flags2 & MV_fConstFound) ||
(OTypOf(vm_pVarCur) != ET_I2) || (ValueOf(vm_pVarCur, I2) <= 0)) {
retval = PRS_ER_RP | MSG_InvConst;
goto RetValExit;
}
mkVar.fsLength = ValueOf(vm_pVarCur, I2);
}
mkVar.flags &= ~(FVFNNAME | FVIMPLICIT); /* Initialize the flags to FALSE */
DbAssertIf(mkVar.flags & FVCONST,
(mkVar.oTyp != ET_IMP))
if ((mkVar.oTyp == ET_IMP) ||
((mkVar.oTyp == UNDEFINED) && !(mkVar.flags & FVASCLAUSE)))
mkVar.flags |= FVIMPLICIT; /* note that an 'UNDEFINED' oTyp
could really be a fixed-length
string of maximal (32K) length.
The FVASCLAUSE bit removes this
ambiguity */
if ((namChar = GetVarNamChar(mkVar.oNam)) & 0xff00)
mkVar.flags |= FVFNNAME; /* get first logical char of name
in low byte, & fFNnam in high */
if (vm_fPVCur = (grs.oPrsCur != UNDEFINED)) {
DbAssert(prsCur.oVarHash != UNDEFINED)
DbAssert(prsCur.oVarHash < mrsCur.bdVar.cbLogical)
if (mkVar.flags & FVCOMMON) {
retval = PRS_ER_RP | MSG_InvProc;
goto RetValExit;
}
oHashCreate = prsCur.oVarHash;
/* The below is a speed optimization. oNamOfPrsCur is set by the rude
scanner to prevent searching the name table for the proc name for
each variable reference in the procedure. When we're called by the
parser, oNamOfPrsCur will be UNDEFINED and we must do it here. */
if ((oNamPrs = oNamOfPrsCur) == UNDEFINED)
oNamPrs = ONamOfOgNam(prsCur.ogNam);/* [4] */
DbAssert(oNamPrs != 0) /* [4] ONamOfOgNam CAN'T ret. OM */
}
else { /* no prs active */
if (mkVar.flags & FVSTATIC) {
retval = PRS_ER_RP | MSG_InvModLev;
goto RetValExit;
}
oHashCreate =
oNamPrs = UNDEFINED;
}
flags = mkVar.flags; /* put flags word in a register */
if ((flags & FVIMPLICIT) && (mkVar.oTyp != UNDEFINED))
mkVar.oTyp = GetDefaultType((char)namChar); /* set default type */
DbMkVarInp() /* special validation code for global inputs */
/*======================================================================
'createMask' is a mask used to pass to CreateVar - - - the code below
depends on the fact that most of the variable entry flags correspond
in position to the MakeVariable input flags ...
=======================================================================*/
createMask = FVVALUESTORED |
(flags & ~(FVREDIRECT | FVEVEREXPLICIT | FVDIM | FV_STATICSET));
nm_mask = 0; /* initialize */
vm_oVarCur = UNDEFINED; /* initialize */
mkVar.flags2 &= ~MV_fConstFound; /* initialize */
if (!(flags & (FVFORMAL | FVCOMMON | FVSTATIC | FVSHARED | FVFNNAME |
FVFUNCTION | FVCONST))) {
/*==== SEARCHING FOR VARIABLE IN THE TYPICAL CASE ====*/
if (retval = StdSearch())
goto RetValExit; /* return error code */
if (vm_fPVCur) { /* a procedure is active */
/*====================================================================
Even though a procedure is active, we must search the tMV as well
in one of three possible cases:
1. A match was not found, and the name table entry indicates that
there is a module shared variable of this oNam.
2. A match was not found, and the current prs is for a DEF FN.
3. We've found a retval in the currently active FUNCTION, but input
FVLVAL is not set, i.e., we've got a case of self-recursion,
and thus want to find the tMV FUNCTION reference rather than the
tPV retval. Note that in this case, we KNOW we'll find a match
in the tMV, as the reference is to the FUNCTION in prsCur.
====================================================================*/
if ((!vm_fVarFound &&
((FlagOfONam(mkVar.oNam) & NM_fShared) ||
(prsCur.procType == PT_DEFFN))) ||
(vm_fVarFound && !(flags & FVLVAL) &&
(FlagsOf(vm_pVarCur) & FVFUN) &&
(mkVar.oNam == oNamPrs) && (prsCur.procType == PT_FUNCTION))) {
vm_fPVCur = FALSE; /* search the tMV */
if (retval = StdSearch())
goto RetValExit; /* return error code */
vm_fPVCur = TRUE; /* reset */
if (vm_fVarFound) {
pVar = vm_pVarCur;
/* [10] set temp boolean TRUE if there exists a module-level
[10] var of this name (not necessarily the var just found! */
fTemp = FlagOfONam(mkVar.oNam) & NM_fShared; /* [10] */
if (fTemp && !(FlagsOf(pVar) & (FVFUN | FVCONST))) { /* [10] */
if (!(FlagsOf(pVar) & FVSHARED)) /* [10] */
vm_fVarFound = FALSE; /* [10] not SHARED, so not found */
} /* [10] */
else if (!fTemp && (prsCur.procType != PT_DEFFN)) /* [10] */
vm_fVarFound = FALSE; /* if not SHARED, then not found */
else if ((FlagsOf(pVar) & FVFUN) && (flags & FVLVAL))
if ((mkVar.oNam == oNamPrs) &&
(prsCur.procType == PT_FUNCTION)) {
/* not found after all - really want to create a retval */
createMask |= (FVFUN | FVDECLDVAR | FVEVEREXPLICIT);
vm_fVarFound = FALSE;
}
else goto RE_DD_Exit; /* attempt to assign to a Function
outside of the Function */
} /* if vm_fVarFound */
} /* if !vm_fVarFound && tNam entry fShared bit set */
else if (vm_fVarFound && (FlagsOf(vm_pVarCur) & FVSHARED))
vm_oVarCur = ValueOf(vm_pVarCur, oMV);
/* caller doesn't want oVar for
the SHARED entry in the tPV,
he wants the actual tMV entry */
}
else /* no procedure is active */
if ((flags & FVLVAL) && vm_fVarFound && (FlagsOf(vm_pVarCur) & FVFUN))
goto RE_DD_Exit; /* attempt to assign to a Function
outside of the Function */
if (!vm_fVarFound)
if (retval = CreateVar(oHashCreate, createMask))
goto RetValExit; /* return error code */
} /* typical case - no special flags set */
else {
/*==== SEARCHING FOR SOME SPECIAL VAR (i.e., COMMON, STATIC, etc.) =====*/
if (flags & (FVFUNCTION | FVFNNAME)) {
if (flags & FVFUNCTION) {
DbAssert(vm_fPVCur == FALSE) /* [DECLARE] FUNCTION only legal
at module level */
if (retval = FuncSearch())
goto RetValExit;
pVar = vm_pVarCur;
if ((!vm_fVarFound) || (fConvtdToFun)) {
if (!fConvtdToFun) /* function entry doesn't exist yet */
if (retval = CreateVar(UNDEFINED,
createMask | FVDECLDVAR | FVEVEREXPLICIT | FVSHARED))
goto RetValExit; /* return error code */
if ((NMSP_MASK & FlagOfONam(mkVar.oNam)) == NMSP_Variable) {
/* there exists at some non-FUNCTION variable(s) of this
oNam somewhere in mrsCur.bdVar */
/* now set up inputs for each invocation of ModSharedChk */
vm_fPVCur = TRUE;
vm_oVarTmp = vm_oVarCur;
errVal = 0;
ForEachPrsInMrs(ModSharedChk);
/* reset static variables */
vm_oVarCur = vm_oVarTmp;
vm_fPVCur = FALSE;
retval = errVal;
FlagsOf(vm_pVarCur) |= FVSHARED;
/* remember that an entry of this oNam is module shared: */
nm_mask |= NM_fShared;
if (retval)
goto RetValExit;
ResetONamMaskTmp(mkVar.oNam,NMSP_Variable);
/* txtmgr depends on us resetting
this bit in this case */
}
}
} /* if FVFUNCTION */
else { /* must be FVFNNAME */
if ((!vm_fPVCur) || (mkVar.oNam != oNamPrs))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -