📄 insquery.c
字号:
{
for (i = 0 , j = (unsigned) (result->end + 2) ; i < rcnt ; i++ , j++)
{
SetMFType(result->value,j,INSTANCE_NAME);
SetMFValue(result->value,j,GetFullInstanceName(theEnv,InstanceQueryData(theEnv)->QueryCore->soln_set->soln[i]));
}
result->end = (long) j-2;
PopQuerySoln(theEnv);
}
rm(theEnv,(void *) InstanceQueryData(theEnv)->QueryCore->solns,(sizeof(INSTANCE_TYPE *) * rcnt));
rtn_struct(theEnv,query_core,InstanceQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryClasses(theEnv,qclasses);
}
/******************************************************************************
NAME : QueryDoForInstance
DESCRIPTION : Finds the first set of instances which satisfy the query and
executes a user-action with that set
INPUTS : None
RETURNS : Caller's result buffer
SIDE EFFECTS : The query class-expressions are evaluated once,
and the query boolean-expression is evaluated
zero or more times (depending on instance restrictions
and how early the expression evaulates to TRUE - if at all).
Also the action expression is executed zero or once.
Caller's result buffer holds result of user-action
NOTES : H/L Syntax : See ParseQueryAction()
******************************************************************************/
globle void QueryDoForInstance(
void *theEnv,
DATA_OBJECT *result)
{
QUERY_CLASS *qclasses;
unsigned rcnt;
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg->nextArg,
"do-for-instance",&rcnt);
if (qclasses == NULL)
return;
PushQueryCore(theEnv);
InstanceQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
InstanceQueryData(theEnv)->QueryCore->solns = (INSTANCE_TYPE **) gm2(theEnv,(sizeof(INSTANCE_TYPE *) * rcnt));
InstanceQueryData(theEnv)->QueryCore->query = GetFirstArgument();
InstanceQueryData(theEnv)->QueryCore->action = GetFirstArgument()->nextArg;
if (TestForFirstInChain(theEnv,qclasses,0) == TRUE)
EvaluateExpression(theEnv,InstanceQueryData(theEnv)->QueryCore->action,result);
InstanceQueryData(theEnv)->AbortQuery = FALSE;
ProcedureFunctionData(theEnv)->BreakFlag = FALSE;
rm(theEnv,(void *) InstanceQueryData(theEnv)->QueryCore->solns,(sizeof(INSTANCE_TYPE *) * rcnt));
rtn_struct(theEnv,query_core,InstanceQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryClasses(theEnv,qclasses);
}
/******************************************************************************
NAME : QueryDoForAllInstances
DESCRIPTION : Finds all sets of instances which satisfy the query and
executes a user-function for each set as it is found
INPUTS : Caller's result buffer
RETURNS : Nothing useful
SIDE EFFECTS : The query class-expressions are evaluated once,
and the query boolean-expression is evaluated
once for every instance set. Also, the action is
executed for every instance set.
Caller's result buffer holds result of last action executed.
NOTES : H/L Syntax : See ParseQueryAction()
******************************************************************************/
globle void QueryDoForAllInstances(
void *theEnv,
DATA_OBJECT *result)
{
QUERY_CLASS *qclasses;
unsigned rcnt;
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg->nextArg,
"do-for-all-instances",&rcnt);
if (qclasses == NULL)
return;
PushQueryCore(theEnv);
InstanceQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
InstanceQueryData(theEnv)->QueryCore->solns = (INSTANCE_TYPE **) gm2(theEnv,(sizeof(INSTANCE_TYPE *) * rcnt));
InstanceQueryData(theEnv)->QueryCore->query = GetFirstArgument();
InstanceQueryData(theEnv)->QueryCore->action = GetFirstArgument()->nextArg;
InstanceQueryData(theEnv)->QueryCore->result = result;
ValueInstall(theEnv,InstanceQueryData(theEnv)->QueryCore->result);
TestEntireChain(theEnv,qclasses,0);
ValueDeinstall(theEnv,InstanceQueryData(theEnv)->QueryCore->result);
PropagateReturnValue(theEnv,InstanceQueryData(theEnv)->QueryCore->result);
InstanceQueryData(theEnv)->AbortQuery = FALSE;
ProcedureFunctionData(theEnv)->BreakFlag = FALSE;
rm(theEnv,(void *) InstanceQueryData(theEnv)->QueryCore->solns,(sizeof(INSTANCE_TYPE *) * rcnt));
rtn_struct(theEnv,query_core,InstanceQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryClasses(theEnv,qclasses);
}
/******************************************************************************
NAME : DelayedQueryDoForAllInstances
DESCRIPTION : Finds all sets of instances which satisfy the query and
and exceutes a user-action for each set
This function differs from QueryDoForAllInstances() in
that it forms the complete list of query satisfactions
BEFORE executing any actions.
INPUTS : Caller's result buffer
RETURNS : Nothing useful
SIDE EFFECTS : The query class-expressions are evaluated once,
and the query boolean-expression is evaluated
once for every instance set. The action is executed
for evry query satisfaction.
Caller's result buffer holds result of last action executed.
NOTES : H/L Syntax : See ParseQueryNoAction()
******************************************************************************/
globle void DelayedQueryDoForAllInstances(
void *theEnv,
DATA_OBJECT *result)
{
QUERY_CLASS *qclasses;
unsigned rcnt;
register unsigned i;
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg->nextArg,
"delayed-do-for-all-instances",&rcnt);
if (qclasses == NULL)
return;
PushQueryCore(theEnv);
InstanceQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
InstanceQueryData(theEnv)->QueryCore->solns = (INSTANCE_TYPE **) gm2(theEnv,(sizeof(INSTANCE_TYPE *) * rcnt));
InstanceQueryData(theEnv)->QueryCore->query = GetFirstArgument();
InstanceQueryData(theEnv)->QueryCore->action = NULL;
InstanceQueryData(theEnv)->QueryCore->soln_set = NULL;
InstanceQueryData(theEnv)->QueryCore->soln_size = rcnt;
InstanceQueryData(theEnv)->QueryCore->soln_cnt = 0;
TestEntireChain(theEnv,qclasses,0);
InstanceQueryData(theEnv)->AbortQuery = FALSE;
InstanceQueryData(theEnv)->QueryCore->action = GetFirstArgument()->nextArg;
while (InstanceQueryData(theEnv)->QueryCore->soln_set != NULL)
{
for (i = 0 ; i < rcnt ; i++)
InstanceQueryData(theEnv)->QueryCore->solns[i] = InstanceQueryData(theEnv)->QueryCore->soln_set->soln[i];
PopQuerySoln(theEnv);
EvaluationData(theEnv)->CurrentEvaluationDepth++;
EvaluateExpression(theEnv,InstanceQueryData(theEnv)->QueryCore->action,result);
EvaluationData(theEnv)->CurrentEvaluationDepth--;
if (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE)
{ PropagateReturnValue(theEnv,result); }
PeriodicCleanup(theEnv,FALSE,TRUE);
if (EvaluationData(theEnv)->HaltExecution || ProcedureFunctionData(theEnv)->BreakFlag || ProcedureFunctionData(theEnv)->ReturnFlag)
{
while (InstanceQueryData(theEnv)->QueryCore->soln_set != NULL)
PopQuerySoln(theEnv);
break;
}
}
ProcedureFunctionData(theEnv)->BreakFlag = FALSE;
rm(theEnv,(void *) InstanceQueryData(theEnv)->QueryCore->solns,(sizeof(INSTANCE_TYPE *) * rcnt));
rtn_struct(theEnv,query_core,InstanceQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryClasses(theEnv,qclasses);
}
/* =========================================
*****************************************
INTERNALLY VISIBLE FUNCTIONS
=========================================
***************************************** */
/*******************************************************
NAME : PushQueryCore
DESCRIPTION : Pushes the current QueryCore onto stack
INPUTS : None
RETURNS : Nothing useful
SIDE EFFECTS : Allocates new stack node and changes
QueryCoreStack
NOTES : None
*******************************************************/
static void PushQueryCore(
void *theEnv)
{
QUERY_STACK *qptr;
qptr = get_struct(theEnv,query_stack);
qptr->core = InstanceQueryData(theEnv)->QueryCore;
qptr->nxt = InstanceQueryData(theEnv)->QueryCoreStack;
InstanceQueryData(theEnv)->QueryCoreStack = qptr;
}
/******************************************************
NAME : PopQueryCore
DESCRIPTION : Pops top of QueryCore stack and
restores QueryCore to this core
INPUTS : None
RETURNS : Nothing useful
SIDE EFFECTS : Stack node deallocated, QueryCoreStack
changed and QueryCore reset
NOTES : Assumes stack is not empty
******************************************************/
static void PopQueryCore(
void *theEnv)
{
QUERY_STACK *qptr;
InstanceQueryData(theEnv)->QueryCore = InstanceQueryData(theEnv)->QueryCoreStack->core;
qptr = InstanceQueryData(theEnv)->QueryCoreStack;
InstanceQueryData(theEnv)->QueryCoreStack = InstanceQueryData(theEnv)->QueryCoreStack->nxt;
rtn_struct(theEnv,query_stack,qptr);
}
/***************************************************
NAME : FindQueryCore
DESCRIPTION : Looks up a QueryCore Stack Frame
Depth 0 is current frame
1 is next deepest, etc.
INPUTS : Depth
RETURNS : Address of query core stack frame
SIDE EFFECTS : None
NOTES : None
***************************************************/
static QUERY_CORE *FindQueryCore(
void *theEnv,
int depth)
{
QUERY_STACK *qptr;
if (depth == 0)
return(InstanceQueryData(theEnv)->QueryCore);
qptr = InstanceQueryData(theEnv)->QueryCoreStack;
while (depth > 1)
{
qptr = qptr->nxt;
depth--;
}
return(qptr->core);
}
/**********************************************************
NAME : DetermineQueryClasses
DESCRIPTION : Builds a list of classes to be used in
instance queries - uses parse form.
INPUTS : 1) The parse class expression chain
2) The name of the function being executed
3) Caller's buffer for restriction count
(# of separate lists)
RETURNS : The query list, or NULL on errors
SIDE EFFECTS : Memory allocated for list
Busy count incremented for all classes
NOTES : Each restriction is linked by nxt pointer,
multiple classes in a restriction are
linked by the chain pointer.
Rcnt caller's buffer is set to reflect the
total number of chains
Assumes classExp is not NULL and that each
restriction chain is terminated with
the QUERY_DELIMITER_SYMBOL "(QDS)"
**********************************************************/
static QUERY_CLASS *DetermineQueryClasses(
void *theEnv,
EXPRESSION *classExp,
char *func,
unsigned *rcnt)
{
QUERY_CLASS *clist = NULL,*cnxt = NULL,*cchain = NULL,*tmp;
int new_list = FALSE;
DATA_OBJECT temp;
*rcnt = 0;
while (classExp != NULL)
{
if (EvaluateExpression(theEnv,classExp,&temp))
{
DeleteQueryClasses(theEnv,clist);
return(NULL);
}
if ((temp.type == SYMBOL) && (temp.value == (void *) InstanceQueryData(theEnv)->QUERY_DELIMETER_SYMBOL))
{
new_list = TRUE;
(*rcnt)++;
}
else if ((tmp = FormChain(theEnv,func,&temp)) != NULL)
{
if (clist == NULL)
clist = cnxt = cchain = tmp;
else if (new_list == TRUE)
{
new_list = FALSE;
cnxt->nxt = tmp;
cnxt = cchain = tmp;
}
else
cchain->chain = tmp;
while (cchain->chain != NULL)
cchain = cchain->chain;
}
else
{
SyntaxErrorMessage(theEnv,"instance-set query class restrictions");
DeleteQueryClasses(theEnv,clist);
SetEvaluationError(theEnv,TRUE);
return(NULL);
}
classExp = classExp->nextArg;
}
return(clist);
}
/*************************************************************
NAME : FormChain
DESCRIPTION : Builds a list of classes to be used in
instance queries - uses parse form.
INPUTS : 1) Name of calling function for error msgs
2) Data object - must be a symbol or a
multifield value containing all symbols
The symbols must be names of existing classes
RETURNS : The query chain, or NULL on errors
SIDE EFFECTS : Memory allocated for chain
Busy count incremented for all classes
NOTES : None
*************************************************************/
static QUERY_CLASS *FormChain(
void *theEnv,
char *func,
DATA_OBJECT *val)
{
DEFCLASS *cls;
QUERY_CLASS *head,*bot,*tmp;
register long i,end; /* 6.04 Bug Fix */
char *className;
struct defmodule *currentModule;
currentModule = ((struct defmodule *) EnvGetCurrentModule(theEnv));
if (val->type == DEFCLASS_PTR)
{
IncrementDefclassBusyCount(theEnv,(void *) val->value);
head = get_struct(theEnv,query_class);
head->cls = (DEFCLASS *) val->value;
if (DefclassInScope(theEnv,head->cls,currentModule))
head->theModule = currentModule;
else
head->theModule = head->cls->header.whichModule->theModule;
head->chain = NULL;
head->nxt = NULL;
return(head);
}
if (val->type == SYMBOL)
{
/* ===============================================
Allow instance-set query restrictions to have a
module specifier as part of the class name,
but search imported defclasses too if a
module specifier is not given
=============================================== */
cls = LookupDefclassByMdlOrScope(theEnv,DOPToString(val));
if (cls == NULL)
{
ClassExistError(theEnv,func,DOPToString(val));
return(NULL);
}
IncrementDefclassBusyCount(theEnv,(void *) cls);
head = get_struct(theEnv,query_class);
head->cls = cls;
if (DefclassInScope(theEnv,head->cls,currentModule))
head->theModule = currentModule;
else
head->theModule = head->cls->header.whichModule->theModule;
head->chain = NULL;
head->nxt = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -