📄 multifun.c
字号:
}
theList = (struct multifield *) DOToPointer(theValue);
/*=========================*/
/* Return the new segment. */
/*=========================*/
SetpType(returnValue,MULTIFIELD);
SetpValue(returnValue,theList);
if (GetDOBegin(theValue) > GetDOEnd(theValue))
{ SetpDOBegin(returnValue,GetDOBegin(theValue)); }
else
{ SetpDOBegin(returnValue,GetDOBegin(theValue) + 1); }
SetpDOEnd(returnValue,GetDOEnd(theValue));
}
/*************************************/
/* NthFunction: H/L access routine */
/* for the nth$ function. */
/*************************************/
globle void NthFunction(
void *theEnv,
DATA_OBJECT_PTR nth_value)
{
DATA_OBJECT value1, value2;
struct multifield *elm_ptr;
long n; /* 6.04 Bug Fix */
if (EnvArgCountCheck(theEnv,"nth$",EXACTLY,2) == -1)
{
SetpType(nth_value,SYMBOL);
SetpValue(nth_value,(void *) EnvAddSymbol(theEnv,"nil"));
return;
}
if ((EnvArgTypeCheck(theEnv,"nth$",1,INTEGER,&value1) == FALSE) ||
(EnvArgTypeCheck(theEnv,"nth$",2,MULTIFIELD,&value2) == FALSE))
{
SetpType(nth_value,SYMBOL);
SetpValue(nth_value,(void *) EnvAddSymbol(theEnv,"nil"));
return;
}
n = DOToLong(value1); /* 6.04 Bug Fix */
if ((n > GetDOLength(value2)) || (n < 1))
{
SetpType(nth_value,SYMBOL);
SetpValue(nth_value,(void *) EnvAddSymbol(theEnv,"nil"));
return;
}
elm_ptr = (struct multifield *) GetValue(value2);
SetpType(nth_value,GetMFType(elm_ptr,n + GetDOBegin(value2) - 1));
SetpValue(nth_value,GetMFValue(elm_ptr,n + GetDOBegin(value2) - 1));
}
/* ------------------------------------------------------------------
* SubsetFunction:
* This function compares two multi-field variables
* to see if the first is a subset of the second. It
* does not consider order.
*
* INPUTS: Two arguments via argument stack. First is the sublist
* multi-field variable, the second is the list to be
* compared to. Both should be of type MULTIFIELD.
*
* OUTPUTS: TRUE if the first list is a subset of the
* second, else FALSE
*
* NOTES: This function is called from H/L with the subset
* command. Repeated values in the sublist must also
* be repeated in the main list.
* ------------------------------------------------------------------
*/
globle intBool SubsetpFunction(
void *theEnv)
{
DATA_OBJECT item1, item2, tmpItem;
long i,j,k;
if (EnvArgCountCheck(theEnv,"subsetp",EXACTLY,2) == -1)
return(FALSE);
if (EnvArgTypeCheck(theEnv,"subsetp",1,MULTIFIELD,&item1) == FALSE)
return(FALSE);
if (EnvArgTypeCheck(theEnv,"subsetp",2,MULTIFIELD,&item2) == FALSE)
return(FALSE);
if (GetDOLength(item1) == 0) return(TRUE);
if (GetDOLength(item2) == 0) return(FALSE);
for (i = GetDOBegin(item1) ; i <= GetDOEnd(item1) ; i++)
{
SetType(tmpItem,GetMFType((struct multifield *) GetValue(item1),i));
SetValue(tmpItem,GetMFValue((struct multifield *) GetValue(item1),i));
if (! FindDOsInSegment(&tmpItem,1,&item2,&j,&k,NULL,0))
{ return(FALSE); }
}
return(TRUE);
}
/****************************************/
/* MemberFunction: H/L access routine */
/* for the member$ function. */
/****************************************/
globle void MemberFunction(
void *theEnv,
DATA_OBJECT_PTR result)
{
DATA_OBJECT item1, item2;
long j,k;
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
if (EnvArgCountCheck(theEnv,"member$",EXACTLY,2) == -1) return;
EnvRtnUnknown(theEnv,1,&item1);
if (EnvArgTypeCheck(theEnv,"member$",2,MULTIFIELD,&item2) == FALSE) return;
if (FindDOsInSegment(&item1,1,&item2,&j,&k,NULL,0))
{
if (j == k)
{
result->type = INTEGER;
result->value = (void *) EnvAddLong(theEnv,j);
}
else
{
result->type = MULTIFIELD;
result->value = EnvCreateMultifield(theEnv,2);
SetMFType(result->value,1,INTEGER);
SetMFValue(result->value,1,EnvAddLong(theEnv,j));
SetMFType(result->value,2,INTEGER);
SetMFValue(result->value,2,EnvAddLong(theEnv,k));
SetpDOBegin(result,1);
SetpDOEnd(result,2);
}
}
}
/***************************************/
/* FindDOsInSegment: */
/***************************************/
/* 6.05 Bug Fix */
intBool FindDOsInSegment(
DATA_OBJECT_PTR searchDOs,
int scnt,
DATA_OBJECT_PTR value,
long *si,
long *ei,
long *excludes,
int epaircnt)
{
long mul_length,slen,i,k; /* 6.04 Bug Fix */
int j;
mul_length = GetpDOLength(value);
for (i = 0 ; i < mul_length ; i++)
{
for (j = 0 ; j < scnt ; j++)
{
if (GetType(searchDOs[j]) == MULTIFIELD)
{
slen = GetDOLength(searchDOs[j]);
if (MVRangeCheck(i+1L,i+slen,excludes,epaircnt))
{
for (k = 0L ; (k < slen) && ((k + i) < mul_length) ; k++)
if ((GetMFType(GetValue(searchDOs[j]),k+GetDOBegin(searchDOs[j])) !=
GetMFType(GetpValue(value),k+i+GetpDOBegin(value))) ||
(GetMFValue(GetValue(searchDOs[j]),k+GetDOBegin(searchDOs[j])) !=
GetMFValue(GetpValue(value),k+i+GetpDOBegin(value))))
break;
if (k >= slen)
{
*si = i + 1L;
*ei = i + slen;
return(TRUE);
}
}
}
else if ((GetValue(searchDOs[j]) == GetMFValue(GetpValue(value),i + GetpDOBegin(value))) &&
(GetType(searchDOs[j]) == GetMFType(GetpValue(value),i + GetpDOBegin(value))) &&
MVRangeCheck(i+1L,i+1L,excludes,epaircnt))
{
*si = *ei = i+1L;
return(TRUE);
}
}
}
return(FALSE);
}
/******************************************************/
/* MVRangeCheck: */
/******************************************************/
static intBool MVRangeCheck(
long si,
long ei,
long *elist,
int epaircnt)
{
int i;
if (!elist || !epaircnt)
return(TRUE);
for (i = 0 ; i < epaircnt ; i++)
if (((si >= elist[i*2]) && (si <= elist[i*2+1])) ||
((ei >= elist[i*2]) && (ei <= elist[i*2+1])))
return(FALSE);
return(TRUE);
}
#if (! BLOAD_ONLY) && (! RUN_TIME)
/******************************************************/
/* MultifieldPrognParser: Parses the progn$ function. */
/******************************************************/
static struct expr *MultifieldPrognParser(
void *theEnv,
struct expr *top,
char *infile)
{
struct BindInfo *oldBindList,*newBindList,*prev;
struct token tkn;
struct expr *tmp;
SYMBOL_HN *fieldVar = NULL;
SavePPBuffer(theEnv," ");
GetToken(theEnv,infile,&tkn);
/* ================================
Simple form: progn$ <mf-exp> ...
================================ */
if (tkn.type != LPAREN)
{
top->argList = ParseAtomOrExpression(theEnv,infile,&tkn);
if (top->argList == NULL)
{
ReturnExpression(theEnv,top);
return(NULL);
}
}
else
{
GetToken(theEnv,infile,&tkn);
if (tkn.type != SF_VARIABLE)
{
if (tkn.type != SYMBOL)
goto MvPrognParseError;
top->argList = Function2Parse(theEnv,infile,ValueToString(tkn.value));
if (top->argList == NULL)
{
ReturnExpression(theEnv,top);
return(NULL);
}
}
/* =========================================
Complex form: progn$ (<var> <mf-exp>) ...
========================================= */
else
{
fieldVar = (SYMBOL_HN *) tkn.value;
SavePPBuffer(theEnv," ");
top->argList = ParseAtomOrExpression(theEnv,infile,NULL);
if (top->argList == NULL)
{
ReturnExpression(theEnv,top);
return(NULL);
}
GetToken(theEnv,infile,&tkn);
if (tkn.type != RPAREN)
goto MvPrognParseError;
PPBackup(theEnv);
/* PPBackup(theEnv); */
SavePPBuffer(theEnv,tkn.printForm);
SavePPBuffer(theEnv," ");
}
}
if (CheckArgumentAgainstRestriction(theEnv,top->argList,(int) 'm'))
goto MvPrognParseError;
oldBindList = GetParsedBindNames(theEnv);
SetParsedBindNames(theEnv,NULL);
IncrementIndentDepth(theEnv,3);
ExpressionData(theEnv)->BreakContext = TRUE;
ExpressionData(theEnv)->ReturnContext = ExpressionData(theEnv)->svContexts->rtn;
PPCRAndIndent(theEnv);
top->argList->nextArg = GroupActions(theEnv,infile,&tkn,TRUE,NULL,FALSE);
DecrementIndentDepth(theEnv,3);
PPBackup(theEnv);
PPBackup(theEnv);
SavePPBuffer(theEnv,tkn.printForm);
if (top->argList->nextArg == NULL)
{
SetParsedBindNames(theEnv,oldBindList);
ReturnExpression(theEnv,top);
return(NULL);
}
tmp = top->argList->nextArg;
top->argList->nextArg = tmp->argList;
tmp->argList = NULL;
ReturnExpression(theEnv,tmp);
newBindList = GetParsedBindNames(theEnv);
prev = NULL;
while (newBindList != NULL)
{
if ((fieldVar == NULL) ? FALSE :
(strcmp(ValueToString(newBindList->name),ValueToString(fieldVar)) == 0))
{
ClearParsedBindNames(theEnv);
SetParsedBindNames(theEnv,oldBindList);
PrintErrorID(theEnv,"MULTIFUN",2,FALSE);
EnvPrintRouter(theEnv,WERROR,"Cannot rebind field variable in function progn$.\n");
ReturnExpression(theEnv,top);
return(NULL);
}
prev = newBindList;
newBindList = newBindList->next;
}
if (prev == NULL)
SetParsedBindNames(theEnv,oldBindList);
else
prev->next = oldBindList;
if (fieldVar != NULL)
ReplaceMvPrognFieldVars(theEnv,fieldVar,top->argList->nextArg,0);
return(top);
MvPrognParseError:
SyntaxErrorMessage(theEnv,"progn$");
ReturnExpression(theEnv,top);
return(NULL);
}
/**********************************************/
/* ReplaceMvPrognFieldVars: Replaces variable */
/* references found in the progn$ function. */
/**********************************************/
static void ReplaceMvPrognFieldVars(
void *theEnv,
SYMBOL_HN *fieldVar,
struct expr *theExp,
int depth)
{
size_t flen;
flen = strlen(ValueToString(fieldVar));
while (theExp != NULL)
{
if ((theExp->type != SF_VARIABLE) ? FALSE :
(strncmp(ValueToString(theExp->value),ValueToString(fieldVar),
(STD_SIZE) flen) == 0))
{
if (ValueToString(theExp->value)[flen] == '\0')
{
theExp->type = FCALL;
theExp->value = (void *) FindFunction(theEnv,"(get-progn$-field)");
theExp->argList = GenConstant(theEnv,INTEGER,EnvAddLong(theEnv,(long) depth));
}
else if (strcmp(ValueToString(theExp->value) + flen,"-index") == 0)
{
theExp->type = FCALL;
theExp->value = (void *) FindFunction(theEnv,"(get-progn$-index)");
theExp->argList = GenConstant(theEnv,INTEGER,EnvAddLong(theEnv,(long) depth));
}
}
else if (theExp->argList != NULL)
{
if ((theExp->type == FCALL) && (theExp->value == (void *) FindFunction(theEnv,"progn$")))
ReplaceMvPrognFieldVars(theEnv,fieldVar,theExp->argList,depth+1);
else
ReplaceMvPrognFieldVars(theEnv,fieldVar,theExp->argList,depth);
}
theExp = theExp->nextArg;
}
}
#endif
/*****************************************/
/* MultifieldPrognFunction: H/L access */
/* routine for the progn$ function. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -