📄 insquery.c
字号:
return(head);
}
if (val->type == MULTIFIELD)
{
head = bot = NULL;
end = GetpDOEnd(val);
for (i = GetpDOBegin(val) ; i <= end ; i++)
{
if (GetMFType(val->value,i) == SYMBOL)
{
className = ValueToString(GetMFValue(val->value,i));
cls = LookupDefclassByMdlOrScope(theEnv,className);
if (cls == NULL)
{
ClassExistError(theEnv,func,className);
DeleteQueryClasses(theEnv,head);
return(NULL);
}
}
else
{
DeleteQueryClasses(theEnv,head);
return(NULL);
}
IncrementDefclassBusyCount(theEnv,(void *) cls);
tmp = get_struct(theEnv,query_class);
tmp->cls = cls;
if (DefclassInScope(theEnv,tmp->cls,currentModule))
tmp->theModule = currentModule;
else
tmp->theModule = tmp->cls->header.whichModule->theModule;
tmp->chain = NULL;
tmp->nxt = NULL;
if (head == NULL)
head = tmp;
else
bot->chain = tmp;
bot = tmp;
}
return(head);
}
return(NULL);
}
/******************************************************
NAME : DeleteQueryClasses
DESCRIPTION : Deletes a query class-list
INPUTS : The query list address
RETURNS : Nothing useful
SIDE EFFECTS : Nodes deallocated
Busy count decremented for all classes
NOTES : None
******************************************************/
static void DeleteQueryClasses(
void *theEnv,
QUERY_CLASS *qlist)
{
QUERY_CLASS *tmp;
while (qlist != NULL)
{
while (qlist->chain != NULL)
{
tmp = qlist->chain;
qlist->chain = qlist->chain->chain;
DecrementDefclassBusyCount(theEnv,(void *) tmp->cls);
rtn_struct(theEnv,query_class,tmp);
}
tmp = qlist;
qlist = qlist->nxt;
DecrementDefclassBusyCount(theEnv,(void *) tmp->cls);
rtn_struct(theEnv,query_class,tmp);
}
}
/************************************************************
NAME : TestForFirstInChain
DESCRIPTION : Processes all classes in a restriction chain
until success or done
INPUTS : 1) The current chain
2) The index of the chain restriction
(e.g. the 4th query-variable)
RETURNS : TRUE if query succeeds, FALSE otherwise
SIDE EFFECTS : Sets current restriction class
Instance variable values set
NOTES : None
************************************************************/
static int TestForFirstInChain(
void *theEnv,
QUERY_CLASS *qchain,
int indx)
{
QUERY_CLASS *qptr;
int id;
InstanceQueryData(theEnv)->AbortQuery = TRUE;
for (qptr = qchain ; qptr != NULL ; qptr = qptr->chain)
{
InstanceQueryData(theEnv)->AbortQuery = FALSE;
if ((id = GetTraversalID(theEnv)) == -1)
return(FALSE);
if (TestForFirstInstanceInClass(theEnv,qptr->theModule,id,qptr->cls,qchain,indx))
{
ReleaseTraversalID(theEnv);
return(TRUE);
}
ReleaseTraversalID(theEnv);
if ((EvaluationData(theEnv)->HaltExecution == TRUE) || (InstanceQueryData(theEnv)->AbortQuery == TRUE))
return(FALSE);
}
return(FALSE);
}
/*****************************************************************
NAME : TestForFirstInstanceInClass
DESCRIPTION : Processes all instances in a class and then
all subclasses of a class until success or done
INPUTS : 1) The module for which classes tested must be
in scope
2) Visitation traversal id
3) The class
4) The current class restriction chain
5) The index of the current restriction
RETURNS : TRUE if query succeeds, FALSE otherwise
SIDE EFFECTS : Instance variable values set
NOTES : None
*****************************************************************/
static int TestForFirstInstanceInClass(
void *theEnv,
struct defmodule *theModule,
int id,
DEFCLASS *cls,
QUERY_CLASS *qchain,
int indx)
{
register unsigned i;
INSTANCE_TYPE *ins;
DATA_OBJECT temp;
if (TestTraversalID(cls->traversalRecord,id))
return(FALSE);
SetTraversalID(cls->traversalRecord,id);
if (DefclassInScope(theEnv,cls,theModule) == FALSE)
return(FALSE);
ins = cls->instanceList;
while (ins != NULL)
{
InstanceQueryData(theEnv)->QueryCore->solns[indx] = ins;
if (qchain->nxt != NULL)
{
ins->busy++;
if (TestForFirstInChain(theEnv,qchain->nxt,indx+1) == TRUE)
{
ins->busy--;
break;
}
ins->busy--;
if ((EvaluationData(theEnv)->HaltExecution == TRUE) || (InstanceQueryData(theEnv)->AbortQuery == TRUE))
break;
}
else
{
ins->busy++;
EvaluationData(theEnv)->CurrentEvaluationDepth++;
EvaluateExpression(theEnv,InstanceQueryData(theEnv)->QueryCore->query,&temp);
EvaluationData(theEnv)->CurrentEvaluationDepth--;
PeriodicCleanup(theEnv,FALSE,TRUE);
ins->busy--;
if (EvaluationData(theEnv)->HaltExecution == TRUE)
break;
if ((temp.type != SYMBOL) ? TRUE :
(temp.value != EnvFalseSymbol(theEnv)))
break;
}
ins = ins->nxtClass;
while ((ins != NULL) ? (ins->garbage == 1) : FALSE)
ins = ins->nxtClass;
}
if (ins != NULL)
return(((EvaluationData(theEnv)->HaltExecution == TRUE) || (InstanceQueryData(theEnv)->AbortQuery == TRUE))
? FALSE : TRUE);
for (i = 0 ; i < cls->directSubclasses.classCount ; i++)
{
if (TestForFirstInstanceInClass(theEnv,theModule,id,cls->directSubclasses.classArray[i],
qchain,indx))
return(TRUE);
if ((EvaluationData(theEnv)->HaltExecution == TRUE) || (InstanceQueryData(theEnv)->AbortQuery == TRUE))
return(FALSE);
}
return(FALSE);
}
/************************************************************
NAME : TestEntireChain
DESCRIPTION : Processes all classes in a restriction chain
until done
INPUTS : 1) The current chain
2) The index of the chain restriction
(i.e. the 4th query-variable)
RETURNS : Nothing useful
SIDE EFFECTS : Sets current restriction class
Query instance variables set
Solution sets stored in global list
NOTES : None
************************************************************/
static void TestEntireChain(
void *theEnv,
QUERY_CLASS *qchain,
int indx)
{
QUERY_CLASS *qptr;
int id;
InstanceQueryData(theEnv)->AbortQuery = TRUE;
for (qptr = qchain ; qptr != NULL ; qptr = qptr->chain)
{
InstanceQueryData(theEnv)->AbortQuery = FALSE;
if ((id = GetTraversalID(theEnv)) == -1)
return;
TestEntireClass(theEnv,qptr->theModule,id,qptr->cls,qchain,indx);
ReleaseTraversalID(theEnv);
if ((EvaluationData(theEnv)->HaltExecution == TRUE) || (InstanceQueryData(theEnv)->AbortQuery == TRUE))
return;
}
}
/*****************************************************************
NAME : TestEntireClass
DESCRIPTION : Processes all instances in a class and then
all subclasses of a class until done
INPUTS : 1) The module for which classes tested must be
in scope
2) Visitation traversal id
3) The class
4) The current class restriction chain
5) The index of the current restriction
RETURNS : Nothing useful
SIDE EFFECTS : Instance variable values set
Solution sets stored in global list
NOTES : None
*****************************************************************/
static void TestEntireClass(
void *theEnv,
struct defmodule *theModule,
int id,
DEFCLASS *cls,
QUERY_CLASS *qchain,
int indx)
{
register unsigned i;
INSTANCE_TYPE *ins;
DATA_OBJECT temp;
if (TestTraversalID(cls->traversalRecord,id))
return;
SetTraversalID(cls->traversalRecord,id);
if (DefclassInScope(theEnv,cls,theModule) == FALSE)
return;
ins = cls->instanceList;
while (ins != NULL)
{
InstanceQueryData(theEnv)->QueryCore->solns[indx] = ins;
if (qchain->nxt != NULL)
{
ins->busy++;
TestEntireChain(theEnv,qchain->nxt,indx+1);
ins->busy--;
if ((EvaluationData(theEnv)->HaltExecution == TRUE) || (InstanceQueryData(theEnv)->AbortQuery == TRUE))
break;
}
else
{
ins->busy++;
EvaluationData(theEnv)->CurrentEvaluationDepth++;
EvaluateExpression(theEnv,InstanceQueryData(theEnv)->QueryCore->query,&temp);
EvaluationData(theEnv)->CurrentEvaluationDepth--;
PeriodicCleanup(theEnv,FALSE,TRUE);
ins->busy--;
if (EvaluationData(theEnv)->HaltExecution == TRUE)
break;
if ((temp.type != SYMBOL) ? TRUE :
(temp.value != EnvFalseSymbol(theEnv)))
{
if (InstanceQueryData(theEnv)->QueryCore->action != NULL)
{
ins->busy++;
EvaluationData(theEnv)->CurrentEvaluationDepth++;
ValueDeinstall(theEnv,InstanceQueryData(theEnv)->QueryCore->result);
EvaluateExpression(theEnv,InstanceQueryData(theEnv)->QueryCore->action,InstanceQueryData(theEnv)->QueryCore->result);
ValueInstall(theEnv,InstanceQueryData(theEnv)->QueryCore->result);
EvaluationData(theEnv)->CurrentEvaluationDepth--;
PeriodicCleanup(theEnv,FALSE,TRUE);
ins->busy--;
if (ProcedureFunctionData(theEnv)->BreakFlag || ProcedureFunctionData(theEnv)->ReturnFlag)
{
InstanceQueryData(theEnv)->AbortQuery = TRUE;
break;
}
if (EvaluationData(theEnv)->HaltExecution == TRUE)
break;
}
else
AddSolution(theEnv);
}
}
ins = ins->nxtClass;
while ((ins != NULL) ? (ins->garbage == 1) : FALSE)
ins = ins->nxtClass;
}
if (ins != NULL)
return;
for (i = 0 ; i < cls->directSubclasses.classCount ; i++)
{
TestEntireClass(theEnv,theModule,id,cls->directSubclasses.classArray[i],qchain,indx);
if ((EvaluationData(theEnv)->HaltExecution == TRUE) || (InstanceQueryData(theEnv)->AbortQuery == TRUE))
return;
}
}
/***************************************************************************
NAME : AddSolution
DESCRIPTION : Adds the current instance set to a global list of
solutions
INPUTS : None
RETURNS : Nothing useful
SIDE EFFECTS : Global list and count updated
NOTES : Solutions are stored as sequential arrays of INSTANCE_TYPE *
***************************************************************************/
static void AddSolution(
void *theEnv)
{
QUERY_SOLN *new_soln;
register unsigned i;
new_soln = (QUERY_SOLN *) gm2(theEnv,(int) sizeof(QUERY_SOLN));
new_soln->soln = (INSTANCE_TYPE **)
gm2(theEnv,(sizeof(INSTANCE_TYPE *) * (InstanceQueryData(theEnv)->QueryCore->soln_size)));
for (i = 0 ; i < InstanceQueryData(theEnv)->QueryCore->soln_size ; i++)
new_soln->soln[i] = InstanceQueryData(theEnv)->QueryCore->solns[i];
new_soln->nxt = NULL;
if (InstanceQueryData(theEnv)->QueryCore->soln_set == NULL)
InstanceQueryData(theEnv)->QueryCore->soln_set = new_soln;
else
InstanceQueryData(theEnv)->QueryCore->soln_bottom->nxt = new_soln;
InstanceQueryData(theEnv)->QueryCore->soln_bottom = new_soln;
InstanceQueryData(theEnv)->QueryCore->soln_cnt++;
}
/***************************************************
NAME : PopQuerySoln
DESCRIPTION : Deallocates the topmost solution
set for an instance-set query
INPUTS : None
RETURNS : Nothing useful
SIDE EFFECTS : Solution set deallocated
NOTES : Assumes QueryCore->soln_set != 0
***************************************************/
static void PopQuerySoln(
void *theEnv)
{
InstanceQueryData(theEnv)->QueryCore->soln_bottom = InstanceQueryData(theEnv)->QueryCore->soln_set;
InstanceQueryData(theEnv)->QueryCore->soln_set = InstanceQueryData(theEnv)->QueryCore->soln_set->nxt;
rm(theEnv,(void *) InstanceQueryData(theEnv)->QueryCore->soln_bottom->soln,
(sizeof(INSTANCE_TYPE *) * InstanceQueryData(theEnv)->QueryCore->soln_size));
rm(theEnv,(void *) InstanceQueryData(theEnv)->QueryCore->soln_bottom,sizeof(QUERY_SOLN));
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -