📄 varmgrc.c
字号:
* FVCONST, and FVSTATIC are to be set correctly; FVARRAY &
* FVINDEXED will frequently be correct, but may be changed
* based on other flags settings; FVVALUESTORED is to
* be pathologically set to TRUE on input, while
* FVEVEREXPLICIT, and FVREDIRECT are to be set FALSE.
* mkVar - global structure containing MakeVariable inputs for oNam,
* oTyp, and a(nother) flags word.
*
* NOTE: All variables are created on even-byte boundaries. This
* guarantees, in turn, that the value fields of all variables will
* start on even byte boundaries. We ensure this primarily by the
* structure definitions in variable.h/.inc. The primary reason for
* this is that the shared runtime assumes (and requires) that all
* string descriptors be on even byte boundaries.
*
*Exit:
* return value is an error code; either zero is returned (no error),
* or the same error code as is used by MakeVariable is returned (see
* MakeVariable, below).
*
* Also sets module static vm_oVarCur to the offset into mrsCur.bdVar
* to the new entry, and vm_pVarCur to point to the entry.
*
*Exceptions:
* none.
*
*******************************************************************************/
ushort NEAR CreateVar(oPVHash, varFlags)
ushort oPVHash;
ushort varFlags;
{
var *pVar;
ushort inFlags = mkVar.flags; /* put MakeVariable callers flags
word in a register */
ushort cbValue = 0;
ushort cbOTyp;
ushort *pHash;
uchar nmsp_type;
ushort temp;
ushort entryFlags; /* [11] use this to build up
[11] the flags word for entry */
ushort oPrsRef; /* [11] 0 or oPrs for function
[11] ref */
/* if caller to MakeVariable really wanted just a search without modifying
the variable table, return Internal Error code to indicate that the
search failed */
if (mkVar.flags2 & MV_fDontCreate)
return (PRS_ER_RP | ER_IER);
/* The following assertion is made because (if for no other reason ...)
we assume that the user can still CONTinue if he asks to add a variable
but we return ER_CN and he backs out of the edit */
DbAssertIf(mkVar.flags & !(FVCOMMON | FVFNNAME | FVFUNCTION),
!(mkVar.flags2 & MV_fTrashTable))
if ((mkVar.oTyp == UNDEFINED) && !(mkVar.flags & FVASCLAUSE))
/* reference to a record prior to ...AS...*/
return (PRS_ER_RP | MSG_BadElemRef); /* [9] */
/* The following assertion is based on the fact that we're using
grs.oRsCur in the case that we CAN continue to see if there's an active
frame on the stack for the active procedure - if so, we return ER_CN */
DbAssertIf(oPVHash != UNDEFINED,
((grs.oRsCur & 0x8000) && (prsCur.oVarHash == oPVHash)))
if ((oPVHash != UNDEFINED) &&
(grs.otxCONT != UNDEFINED) &&
!(varFlags & (FVSTATIC | FVSHARED | FVCONST)))
if (FindORsFrame()) /* TRUE if this proc has an active frame */
return (0x8000 | ER_CN); /* allow the user to back out of edit */
oPrsRef = 0; /* [11] initialize */
entryFlags = varFlags & ~0x07;
if (inFlags & (FVFORCEARRAY | FVINDEXED))
if (varFlags & FVFUN)
entryFlags |= FVINDEXED;
else {
entryFlags |= (FVARRAY | FVINDEXED);
/* set the dimension count; if input of zero, assume 1 - - - will end
up giving Rude Edit later if this turns out to have been wrong */
if ((mkVar.cDimensions == 0) && !(inFlags & FVCOMMON))
cbValue = sizeof(dm);
/* NOTE: we if a dimension count wasn't specified on a COMMON
statement for an array, the execute scanner depends on
the cDims field in the variable entry being 0;
we depend on that for STATIC arrays, in StdSearch */
if ((inFlags & FVSTATIC) && (mkVar.cDimensions > 8))
return (PRS_ER_RE | MSG_SubCnt); /* 'Wrong number of subscripts' */
}
if (!(inFlags & FVIMPLICIT)) /* if pathological input was wrong */
entryFlags |= FVEVEREXPLICIT;
inFlags = entryFlags; /* now use flags as passed BY MakeVariable */
/* initialize cbValue for static variable case, to save code later on */
cbValue += (inFlags & FVARRAY) ? (sizeof(aStat) + - sizeof(oneChar) +
sizeof(dm) * mkVar.cDimensions) :
(mkVar.oTyp == ET_FS ? mkVar.fsLength :
CbTyp(mkVar.oTyp));
nmsp_type = NMSP_Variable; /* assume we're not creating a FUNCTION, or
DEF FN entry */
if (inFlags &
(FVFORMAL | FVCOMMON | FVSTATIC | FVFUNCTION | FVSHARED | FVCONST)) {
if (inFlags & (FVFORMAL | FVCOMMON | FVFUNCTION)) {
if (inFlags & FVCOMMON) {
entryFlags &= ~FVVALUESTORED; /* set that bit to FALSE */
cbValue = (inFlags & FVARRAY ? sizeof(aCom) : sizeof(comRef));
if (inFlags & FVSHARED)
nm_mask |= NM_fShared;
}
else { /* not COMMON - */
cbValue = sizeof(ushort);
if (inFlags & FVFUNCTION) {
nmsp_type = 0; /* don't set any name table
bits */
if ((oPVHash == UNDEFINED) && (mkVar.flags & FVFUNCTION))
nm_mask |= NM_fShared; /* set tNam entry flag */
if (mkVar.flags & FVLVAL) /* retval */
entryFlags &= ~FVVALUESTORED; /* set to FALSE for retval */
else {
if ((oPrsRef =
PrsRef(mkVar.oNam,
(uchar)((mkVar.flags & FVFUNCTION) ?
PT_FUNCTION : PT_DEFFN),
mkVar.oTyp)) & 0x8000) /* [16] function not found */
return (PRS_ER_RP | ER_UF); /* 'Undefined Function' */
}
}
else { /* FVFORMAL */
entryFlags &= ~FVVALUESTORED; /* set that bit to FALSE */
if (inFlags & FVARRAY)
cbValue = sizeof(aFormal);
}
} /* else - not COMMON */
} /* if FORMAL, COMMON, DEF FN, or FUNCTION */
else /* STATIC,SHARED, or CONST */
if (inFlags & FVSHARED) {
if (oPVHash == UNDEFINED) /* entry going in the tMV */
nm_mask |= NM_fShared;
else { /* entry going in tPV */
entryFlags &= ~FVVALUESTORED; /* set to FALSE */
cbValue = sizeof(ushort);
}
} /* if SHARED */
else if (inFlags & FVCONST) {
if (oPVHash == UNDEFINED) /* entry going in the tMV */
nm_mask = NM_fShared; /* Always set fShared bit
so constants are found */
}
} /* if special case flag is set */
else {
if ((grs.oPrsCur != UNDEFINED) && (prsCur.procType == PT_DEFFN))
oPVHash = UNDEFINED; /* var ref. belongs in the tMV for DEF's */
if ((oPVHash != UNDEFINED) && (!(prsCur.flags & FP_STATIC))) {
entryFlags &= ~FVVALUESTORED; /* actual value not stored in entry */
if (inFlags & FVARRAY)
cbValue = sizeof(aFrame);
else
cbValue = sizeof(ushort); /* size of a frame offset */
}
} /* no special case flag was set */
cbValue = ((++cbValue) >> 1) << 1; /* round up cbValue, to
ensure even-byte vars.
Note that this MUST be
done in case of odd-sized
user-defined types or
fixed-length strings. */
cbOTyp = ((mkVar.oTyp > ET_MAX) || (mkVar.oTyp == ET_FS)) ?
sizeof(ushort) : 0;
vm_oVarCur = mrsCur.bdVar.cbLogical + cbOTyp + VAR_STRUCT_SIZE; /* [11] */
/* [11] see if namespace ER_DD error BEFORE we try to grow the var table,
[11] so we don't ask user if he wants to continue and THEN give error */
if (nmsp_type) /* don't set anything if
creating a DEF or FUN
entry (txtmgr does it) */
if (CheckONamSpace(mkVar.oNam, nmsp_type))
return (PRS_ER_RE | ER_DD); /* duplicate definition */
temp = cbValue + cbOTyp + VAR_STRUCT_SIZE;
if (temp < cbValue) /* [12] 64k wrap occurred */
return (PRS_ER_RE | ER_OM); /* [12] out of memory */
if (temp = GrowBdVar(temp))
return (temp);
pVar = (var *)(mrsCur.bdVar.pb + vm_oVarCur); /* in case table moved */
ZeroFill((char *)pVar, cbValue);
if (cbOTyp) { /* oTyp > ET_MAX */
if (mkVar.oTyp == ET_FS) {
*((ushort *)((char *)pVar + VAR_cbFixed)) = mkVar.fsLength;
entryFlags |= mkVar.oTyp;
}
else
*((ushort *)((char *)pVar + VAR_oTyp)) = mkVar.oTyp;
}
else
entryFlags |= mkVar.oTyp;
ONamOf(pVar) = mkVar.oNam; /* [11] */
FlagsOf(pVar) = entryFlags; /* [11] set entry flags */
ValueOf(pVar, oPrs) = oPrsRef; /* [11] oPrs or zero */
if (nmsp_type) { /* don't set anything if
creating a DEF or FUN
entry (txtmgr does it) */
if (SetONamSpace(mkVar.oNam, nmsp_type))
; /* [11] CheckONamSpace will
[11] already have caught
[11] error, if any */
}
mrsCur.oPastLastVar = mrsCur.bdVar.cbLogical; /* can always trim table
back to oPastLastVar and
lose no variables */
vm_pVarCur = pVar; /* an exit value */
/* initialize the dim count if:
the entry is an array AND it's NOT (shared AND in a procedure).
(If an array is shared and in a procedure it doesn't have a cDims
field in the var table entry. The entry is a near pointer to the
array descriptor defining the array.) */
if ((FlagsOf(pVar) & FVARRAY) &&
!((FlagsOf(pVar) & FVSHARED) && (oPVHash != UNDEFINED))) //[17]
ValueOf(pVar, aryStat.cDims) = mkVar.cDimensions;
/* this actually sets
cDims for all arrays */
/* now just have to link the new entry in */
pHash = (ushort *)(mrsCur.bdVar.pb +
((oPVHash == UNDEFINED) ?
(mkVar.oNam & HASH_MV_NAMMASK) :
(oPVHash + (mkVar.oNam & HASH_PV_NAMMASK))));
if ((*pHash == 0) || (FlagsOf(pVar) & FVDECLDVAR)) {
/* link this entry into start of chain */
OHashLinkOf(pVar) = *pHash; /* old start of chain in new entry */
*pHash = vm_oVarCur; /* save offset to new entry */
}
else { /* link this entry into end of chain */
OHashLinkOf(pVar) = 0; /* 0 (or 1) indicates end of chain;
UNDEFINED doesn't do it because
we store a flag in the low bit */
pVar = (var *)(mrsCur.bdVar.pb + *pHash); /* point to start of chain */
while (OHashLinkOf(pVar) > 1) /* while not end of hash chain */
pVar = (var *)(mrsCur.bdVar.pb + (OHashLinkOf(pVar) & 0xFFFE));
OHashLinkOf(pVar) |= vm_oVarCur; /* OR this in rather than assign it
to preserve existing flag value */
DbAssert(!(vm_oVarCur & 1)) /* we depend on oVars being on even
byte boundaries for this hashlink
bit flag use, and for SD's */
}
return (vm_fVarFound = FALSE); /* var created, not found;
retval says 'no errors' */
} /* CreateVar */
/*##############################################################################
# #
# Variable Searching #
# #
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -