/****************************************************************************** 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); 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 : 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, EXEC_STATUS, QUERY_CLASS *qchain, int indx) { QUERY_CLASS *qptr; int id; InstanceQueryData(theEnv,execStatus)->AbortQuery = TRUE; for (qptr = qchain ; qptr != NULL ; qptr = qptr->chain) { InstanceQueryData(theEnv,execStatus)->AbortQuery = FALSE; if ((id = GetTraversalID(theEnv,execStatus)) == -1) return(FALSE); if (TestForFirstInstanceInClass(theEnv,execStatus,qptr->theModule,id,qptr->cls,qchain,indx)) { ReleaseTraversalID(theEnv,execStatus); return(TRUE); } ReleaseTraversalID(theEnv,execStatus); if ((execStatus->HaltExecution == TRUE) || (InstanceQueryData(theEnv,execStatus)->AbortQuery == TRUE)) return(FALSE); } return(FALSE); }
/****************************************************** 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 : 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 : 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, EXEC_STATUS, DATA_OBJECT *result) { QUERY_CLASS *qclasses; unsigned rcnt; result->type = SYMBOL; result->value = EnvFalseSymbol(theEnv,execStatus); qclasses = DetermineQueryClasses(theEnv,execStatus,GetFirstArgument()->nextArg->nextArg, "do-for-instance",&rcnt); if (qclasses == NULL) return; PushQueryCore(theEnv,execStatus); InstanceQueryData(theEnv,execStatus)->QueryCore = get_struct(theEnv,execStatus,query_core); InstanceQueryData(theEnv,execStatus)->QueryCore->solns = (INSTANCE_TYPE **) gm2(theEnv,execStatus,(sizeof(INSTANCE_TYPE *) * rcnt)); InstanceQueryData(theEnv,execStatus)->QueryCore->query = GetFirstArgument(); InstanceQueryData(theEnv,execStatus)->QueryCore->action = GetFirstArgument()->nextArg; if (TestForFirstInChain(theEnv,execStatus,qclasses,0) == TRUE) EvaluateExpression(theEnv,execStatus,InstanceQueryData(theEnv,execStatus)->QueryCore->action,result); InstanceQueryData(theEnv,execStatus)->AbortQuery = FALSE; ProcedureFunctionData(theEnv,execStatus)->BreakFlag = FALSE; rm(theEnv,execStatus,(void *) InstanceQueryData(theEnv,execStatus)->QueryCore->solns,(sizeof(INSTANCE_TYPE *) * rcnt)); rtn_struct(theEnv,execStatus,query_core,InstanceQueryData(theEnv,execStatus)->QueryCore); PopQueryCore(theEnv,execStatus); DeleteQueryClasses(theEnv,execStatus,qclasses); }
/*************************************************** 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 : 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)); }
/************************************************************ 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 : SetupQuery DESCRIPTION : Initializes instance query H/L functions and parsers INPUTS : None RETURNS : Nothing useful SIDE EFFECTS : Sets up kernel functions and parsers NOTES : None ****************************************************/ globle void SetupQuery( void *theEnv, EXEC_STATUS) { AllocateEnvironmentData(theEnv,execStatus,INSTANCE_QUERY_DATA,sizeof(struct instanceQueryData),NULL); #if ! RUN_TIME InstanceQueryData(theEnv,execStatus)->QUERY_DELIMETER_SYMBOL = (SYMBOL_HN *) EnvAddSymbol(theEnv,execStatus,QUERY_DELIMETER_STRING); IncrementSymbolCount(InstanceQueryData(theEnv,execStatus)->QUERY_DELIMETER_SYMBOL); EnvDefineFunction2(theEnv,execStatus,"(query-instance)",'o', PTIEF GetQueryInstance,"GetQueryInstance",NULL); EnvDefineFunction2(theEnv,execStatus,"(query-instance-slot)",'u', PTIEF GetQueryInstanceSlot,"GetQueryInstanceSlot",NULL); EnvDefineFunction2(theEnv,execStatus,"any-instancep",'b',PTIEF AnyInstances,"AnyInstances",NULL); AddFunctionParser(theEnv,execStatus,"any-instancep",ParseQueryNoAction); EnvDefineFunction2(theEnv,execStatus,"find-instance",'m', PTIEF QueryFindInstance,"QueryFindInstance",NULL); AddFunctionParser(theEnv,execStatus,"find-instance",ParseQueryNoAction); EnvDefineFunction2(theEnv,execStatus,"find-all-instances",'m', PTIEF QueryFindAllInstances,"QueryFindAllInstances",NULL); AddFunctionParser(theEnv,execStatus,"find-all-instances",ParseQueryNoAction); EnvDefineFunction2(theEnv,execStatus,"do-for-instance",'u', PTIEF QueryDoForInstance,"QueryDoForInstance",NULL); AddFunctionParser(theEnv,execStatus,"do-for-instance",ParseQueryAction); EnvDefineFunction2(theEnv,execStatus,"do-for-all-instances",'u', PTIEF QueryDoForAllInstances,"QueryDoForAllInstances",NULL); AddFunctionParser(theEnv,execStatus,"do-for-all-instances",ParseQueryAction); EnvDefineFunction2(theEnv,execStatus,"delayed-do-for-all-instances",'u', PTIEF DelayedQueryDoForAllInstances, "DelayedQueryDoForAllInstances",NULL); AddFunctionParser(theEnv,execStatus,"delayed-do-for-all-instances",ParseQueryAction); #endif }
/********************************************************** 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, EXEC_STATUS, 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,execStatus,classExp,&temp)) { DeleteQueryClasses(theEnv,execStatus,clist); return(NULL); } if ((temp.type == SYMBOL) && (temp.value == (void *) InstanceQueryData(theEnv,execStatus)->QUERY_DELIMETER_SYMBOL)) { new_list = TRUE; (*rcnt)++; } else if ((tmp = FormChain(theEnv,execStatus,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,execStatus,"instance-set query class restrictions"); DeleteQueryClasses(theEnv,execStatus,clist); SetEvaluationError(theEnv,execStatus,TRUE); return(NULL); } classExp = classExp->nextArg; } return(clist); }
/*************************************************************************** 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 : QueryFindInstance DESCRIPTION : Finds the first set of instances which satisfy the query and stores their names in the user's multi-field variable INPUTS : Caller's result buffer RETURNS : TRUE if the query is satisfied, FALSE otherwise 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). NOTES : H/L Syntax : See ParseQueryNoAction() ******************************************************************************/ globle void QueryFindInstance( void *theEnv, EXEC_STATUS, DATA_OBJECT *result) { QUERY_CLASS *qclasses; unsigned rcnt,i; result->type = MULTIFIELD; result->begin = 0; result->end = -1; qclasses = DetermineQueryClasses(theEnv,execStatus,GetFirstArgument()->nextArg, "find-instance",&rcnt); if (qclasses == NULL) { result->value = (void *) EnvCreateMultifield(theEnv,execStatus,0L); return; } PushQueryCore(theEnv,execStatus); InstanceQueryData(theEnv,execStatus)->QueryCore = get_struct(theEnv,execStatus,query_core); InstanceQueryData(theEnv,execStatus)->QueryCore->solns = (INSTANCE_TYPE **) gm2(theEnv,execStatus,(sizeof(INSTANCE_TYPE *) * rcnt)); InstanceQueryData(theEnv,execStatus)->QueryCore->query = GetFirstArgument(); if (TestForFirstInChain(theEnv,execStatus,qclasses,0) == TRUE) { result->value = (void *) EnvCreateMultifield(theEnv,execStatus,rcnt); SetpDOEnd(result,rcnt); for (i = 1 ; i <= rcnt ; i++) { SetMFType(result->value,i,INSTANCE_NAME); SetMFValue(result->value,i,GetFullInstanceName(theEnv,execStatus,InstanceQueryData(theEnv,execStatus)->QueryCore->solns[i - 1])); } } else result->value = (void *) EnvCreateMultifield(theEnv,execStatus,0L); InstanceQueryData(theEnv,execStatus)->AbortQuery = FALSE; rm(theEnv,execStatus,(void *) InstanceQueryData(theEnv,execStatus)->QueryCore->solns,(sizeof(INSTANCE_TYPE *) * rcnt)); rtn_struct(theEnv,execStatus,query_core,InstanceQueryData(theEnv,execStatus)->QueryCore); PopQueryCore(theEnv,execStatus); DeleteQueryClasses(theEnv,execStatus,qclasses); }
/****************************************************************************** NAME : AnyInstances DESCRIPTION : Determines if there any existing instances which satisfy the query INPUTS : None RETURNS : TRUE if the query is satisfied, FALSE otherwise 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). NOTES : H/L Syntax : See ParseQueryNoAction() ******************************************************************************/ globle intBool AnyInstances( void *theEnv) { QUERY_CLASS *qclasses; unsigned rcnt; int TestResult; qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg, "any-instancep",&rcnt); if (qclasses == NULL) return(FALSE); 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(); TestResult = TestForFirstInChain(theEnv,qclasses,0); InstanceQueryData(theEnv)->AbortQuery = 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); return(TestResult); }
/*************************************************** NAME : ObjectsRunTimeInitialize DESCRIPTION : Initializes objects system lists in a run-time module INPUTS : 1) Pointer to new class hash table 2) Pointer to new slot name table RETURNS : Nothing useful SIDE EFFECTS : Global pointers set NOTES : None ***************************************************/ globle void ObjectsRunTimeInitialize( void *theEnv, DEFCLASS *ctable[], SLOT_NAME *sntable[], DEFCLASS **cidmap, unsigned mid) { DEFCLASS *cls; void *tmpexp; register unsigned int i,j; if (DefclassData(theEnv)->ClassTable != NULL) { for (j = 0 ; j < CLASS_TABLE_HASH_SIZE ; j++) for (cls = DefclassData(theEnv)->ClassTable[j] ; cls != NULL ; cls = cls->nxtHash) { for (i = 0 ; i < cls->slotCount ; i++) { /* ===================================================================== For static default values, the data object value needs to deinstalled and deallocated, and the expression needs to be restored (which was temporarily stored in the supplementalInfo field of the data object) ===================================================================== */ if ((cls->slots[i].defaultValue != NULL) && (cls->slots[i].dynamicDefault == 0)) { tmpexp = ((DATA_OBJECT *) cls->slots[i].defaultValue)->supplementalInfo; ValueDeinstall(theEnv,(DATA_OBJECT *) cls->slots[i].defaultValue); rtn_struct(theEnv,dataObject,cls->slots[i].defaultValue); cls->slots[i].defaultValue = tmpexp; } } } } InstanceQueryData(theEnv)->QUERY_DELIMETER_SYMBOL = FindSymbolHN(theEnv,QUERY_DELIMETER_STRING); MessageHandlerData(theEnv)->INIT_SYMBOL = FindSymbolHN(theEnv,INIT_STRING); MessageHandlerData(theEnv)->DELETE_SYMBOL = FindSymbolHN(theEnv,DELETE_STRING); MessageHandlerData(theEnv)->CREATE_SYMBOL = FindSymbolHN(theEnv,CREATE_STRING); DefclassData(theEnv)->ISA_SYMBOL = FindSymbolHN(theEnv,SUPERCLASS_RLN); DefclassData(theEnv)->NAME_SYMBOL = FindSymbolHN(theEnv,NAME_RLN); #if DEFRULE_CONSTRUCT DefclassData(theEnv)->INITIAL_OBJECT_SYMBOL = FindSymbolHN(theEnv,INITIAL_OBJECT_NAME); #endif DefclassData(theEnv)->ClassTable = (DEFCLASS **) ctable; DefclassData(theEnv)->SlotNameTable = (SLOT_NAME **) sntable; DefclassData(theEnv)->ClassIDMap = (DEFCLASS **) cidmap; DefclassData(theEnv)->MaxClassID = (unsigned short) mid; DefclassData(theEnv)->PrimitiveClassMap[FLOAT] = LookupDefclassByMdlOrScope(theEnv,FLOAT_TYPE_NAME); DefclassData(theEnv)->PrimitiveClassMap[INTEGER] = LookupDefclassByMdlOrScope(theEnv,INTEGER_TYPE_NAME); DefclassData(theEnv)->PrimitiveClassMap[STRING] = LookupDefclassByMdlOrScope(theEnv,STRING_TYPE_NAME); DefclassData(theEnv)->PrimitiveClassMap[SYMBOL] = LookupDefclassByMdlOrScope(theEnv,SYMBOL_TYPE_NAME); DefclassData(theEnv)->PrimitiveClassMap[MULTIFIELD] = LookupDefclassByMdlOrScope(theEnv,MULTIFIELD_TYPE_NAME); DefclassData(theEnv)->PrimitiveClassMap[EXTERNAL_ADDRESS] = LookupDefclassByMdlOrScope(theEnv,EXTERNAL_ADDRESS_TYPE_NAME); DefclassData(theEnv)->PrimitiveClassMap[FACT_ADDRESS] = LookupDefclassByMdlOrScope(theEnv,FACT_ADDRESS_TYPE_NAME); DefclassData(theEnv)->PrimitiveClassMap[INSTANCE_NAME] = LookupDefclassByMdlOrScope(theEnv,INSTANCE_NAME_TYPE_NAME); DefclassData(theEnv)->PrimitiveClassMap[INSTANCE_ADDRESS] = LookupDefclassByMdlOrScope(theEnv,INSTANCE_ADDRESS_TYPE_NAME); for (j = 0 ; j < CLASS_TABLE_HASH_SIZE ; j++) for (cls = DefclassData(theEnv)->ClassTable[j] ; cls != NULL ; cls = cls->nxtHash) { for (i = 0 ; i < cls->slotCount ; i++) { if ((cls->slots[i].defaultValue != NULL) && (cls->slots[i].dynamicDefault == 0)) { tmpexp = cls->slots[i].defaultValue; cls->slots[i].defaultValue = (void *) get_struct(theEnv,dataObject); EvaluateAndStoreInDataObject(theEnv,(int) cls->slots[i].multiple,(EXPRESSION *) tmpexp, (DATA_OBJECT *) cls->slots[i].defaultValue,TRUE); ValueInstall(theEnv,(DATA_OBJECT *) cls->slots[i].defaultValue); ((DATA_OBJECT *) cls->slots[i].defaultValue)->supplementalInfo = tmpexp; } } } SearchForHashedPatternNodes(theEnv,ObjectReteData(theEnv)->ObjectPatternNetworkPointer); }
/*************************************************************** NAME : ParseQueryRestrictions DESCRIPTION : Parses the class restrictions for a query INPUTS : 1) The top node of the query expression 2) The logical name of the input 3) Caller's token buffer RETURNS : The instance-variable expressions SIDE EFFECTS : Entire query expression deleted on errors Nodes allocated for restrictions and instance variable expressions Class restrictions attached to query-expression as arguments NOTES : Expects top != NULL ***************************************************************/ static EXPRESSION *ParseQueryRestrictions( void *theEnv, EXPRESSION *top, char *readSource, struct token *queryInputToken) { EXPRESSION *insQuerySetVars = NULL,*lastInsQuerySetVars = NULL, *classExp = NULL,*lastClassExp, *tmp,*lastOne = NULL; int error = FALSE; SavePPBuffer(theEnv," "); GetToken(theEnv,readSource,queryInputToken); if (queryInputToken->type != LPAREN) goto ParseQueryRestrictionsError1; GetToken(theEnv,readSource,queryInputToken); if (queryInputToken->type != LPAREN) goto ParseQueryRestrictionsError1; while (queryInputToken->type == LPAREN) { GetToken(theEnv,readSource,queryInputToken); if (queryInputToken->type != SF_VARIABLE) goto ParseQueryRestrictionsError1; tmp = insQuerySetVars; while (tmp != NULL) { if (tmp->value == queryInputToken->value) { PrintErrorID(theEnv,"INSQYPSR",1,FALSE); EnvPrintRouter(theEnv,WERROR,"Duplicate instance member variable name in function "); EnvPrintRouter(theEnv,WERROR,ValueToString(ExpressionFunctionCallName(top))); EnvPrintRouter(theEnv,WERROR,".\n"); goto ParseQueryRestrictionsError2; } tmp = tmp->nextArg; } tmp = GenConstant(theEnv,SF_VARIABLE,queryInputToken->value); if (insQuerySetVars == NULL) insQuerySetVars = tmp; else lastInsQuerySetVars->nextArg = tmp; lastInsQuerySetVars = tmp; SavePPBuffer(theEnv," "); classExp = ArgumentParse(theEnv,readSource,&error); if (error) goto ParseQueryRestrictionsError2; if (classExp == NULL) goto ParseQueryRestrictionsError1; if (ReplaceClassNameWithReference(theEnv,classExp) == FALSE) goto ParseQueryRestrictionsError2; lastClassExp = classExp; SavePPBuffer(theEnv," "); while ((tmp = ArgumentParse(theEnv,readSource,&error)) != NULL) { if (ReplaceClassNameWithReference(theEnv,tmp) == FALSE) goto ParseQueryRestrictionsError2; lastClassExp->nextArg = tmp; lastClassExp = tmp; SavePPBuffer(theEnv," "); } if (error) goto ParseQueryRestrictionsError2; PPBackup(theEnv); PPBackup(theEnv); SavePPBuffer(theEnv,")"); tmp = GenConstant(theEnv,SYMBOL,(void *) InstanceQueryData(theEnv)->QUERY_DELIMETER_SYMBOL); lastClassExp->nextArg = tmp; lastClassExp = tmp; if (top->argList == NULL) top->argList = classExp; else lastOne->nextArg = classExp; lastOne = lastClassExp; classExp = NULL; SavePPBuffer(theEnv," "); GetToken(theEnv,readSource,queryInputToken); } if (queryInputToken->type != RPAREN) goto ParseQueryRestrictionsError1; PPBackup(theEnv); PPBackup(theEnv); SavePPBuffer(theEnv,")"); return(insQuerySetVars); ParseQueryRestrictionsError1: SyntaxErrorMessage(theEnv,"instance-set query function"); ParseQueryRestrictionsError2: ReturnExpression(theEnv,classExp); ReturnExpression(theEnv,top); ReturnExpression(theEnv,insQuerySetVars); return(NULL); }
/***************************************************************** 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, EXEC_STATUS, struct defmodule *theModule, int id, DEFCLASS *cls, QUERY_CLASS *qchain, int indx) { long i; INSTANCE_TYPE *ins; DATA_OBJECT temp; if (TestTraversalID(cls->traversalRecord,id)) return(FALSE); SetTraversalID(cls->traversalRecord,id); if (DefclassInScope(theEnv,execStatus,cls,theModule) == FALSE) return(FALSE); ins = cls->instanceList; while (ins != NULL) { InstanceQueryData(theEnv,execStatus)->QueryCore->solns[indx] = ins; if (qchain->nxt != NULL) { ins->busy++; if (TestForFirstInChain(theEnv,execStatus,qchain->nxt,indx+1) == TRUE) { ins->busy--; break; } ins->busy--; if ((execStatus->HaltExecution == TRUE) || (InstanceQueryData(theEnv,execStatus)->AbortQuery == TRUE)) break; } else { ins->busy++; execStatus->CurrentEvaluationDepth++; EvaluateExpression(theEnv,execStatus,InstanceQueryData(theEnv,execStatus)->QueryCore->query,&temp); execStatus->CurrentEvaluationDepth--; PeriodicCleanup(theEnv,execStatus,FALSE,TRUE); ins->busy--; if (execStatus->HaltExecution == TRUE) break; if ((temp.type != SYMBOL) ? TRUE : (temp.value != EnvFalseSymbol(theEnv,execStatus))) break; } ins = ins->nxtClass; while ((ins != NULL) ? (ins->garbage == 1) : FALSE) ins = ins->nxtClass; } if (ins != NULL) return(((execStatus->HaltExecution == TRUE) || (InstanceQueryData(theEnv,execStatus)->AbortQuery == TRUE)) ? FALSE : TRUE); for (i = 0 ; i < cls->directSubclasses.classCount ; i++) { if (TestForFirstInstanceInClass(theEnv,execStatus,theModule,id,cls->directSubclasses.classArray[i], qchain,indx)) return(TRUE); if ((execStatus->HaltExecution == TRUE) || (InstanceQueryData(theEnv,execStatus)->AbortQuery == TRUE)) return(FALSE); } return(FALSE); }
/****************************************************************************** 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; struct garbageFrame newGarbageFrame; struct garbageFrame *oldGarbageFrame; 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; oldGarbageFrame = UtilityData(theEnv)->CurrentGarbageFrame; memset(&newGarbageFrame,0,sizeof(struct garbageFrame)); newGarbageFrame.priorFrame = oldGarbageFrame; UtilityData(theEnv)->CurrentGarbageFrame = &newGarbageFrame; 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); EvaluateExpression(theEnv,InstanceQueryData(theEnv)->QueryCore->action,result); if (EvaluationData(theEnv)->HaltExecution || ProcedureFunctionData(theEnv)->BreakFlag || ProcedureFunctionData(theEnv)->ReturnFlag) { while (InstanceQueryData(theEnv)->QueryCore->soln_set != NULL) PopQuerySoln(theEnv); break; } CleanCurrentGarbageFrame(theEnv,NULL); CallPeriodicTasks(theEnv); } RestorePriorGarbageFrame(theEnv,&newGarbageFrame,oldGarbageFrame,result); CallPeriodicTasks(theEnv); 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 : 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) { long i; INSTANCE_TYPE *ins; DATA_OBJECT temp; struct garbageFrame newGarbageFrame; struct garbageFrame *oldGarbageFrame; if (TestTraversalID(cls->traversalRecord,id)) return(FALSE); SetTraversalID(cls->traversalRecord,id); if (DefclassInScope(theEnv,cls,theModule) == FALSE) return(FALSE); oldGarbageFrame = UtilityData(theEnv)->CurrentGarbageFrame; memset(&newGarbageFrame,0,sizeof(struct garbageFrame)); newGarbageFrame.priorFrame = oldGarbageFrame; UtilityData(theEnv)->CurrentGarbageFrame = &newGarbageFrame; 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++; EvaluateExpression(theEnv,InstanceQueryData(theEnv)->QueryCore->query,&temp); ins->busy--; if (EvaluationData(theEnv)->HaltExecution == TRUE) break; if ((temp.type != SYMBOL) ? TRUE : (temp.value != EnvFalseSymbol(theEnv))) break; } CleanCurrentGarbageFrame(theEnv,NULL); CallPeriodicTasks(theEnv); ins = ins->nxtClass; while ((ins != NULL) ? (ins->garbage == 1) : FALSE) ins = ins->nxtClass; } RestorePriorGarbageFrame(theEnv,&newGarbageFrame, oldGarbageFrame,NULL); CallPeriodicTasks(theEnv); 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 : 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, EXEC_STATUS, DATA_OBJECT *result) { QUERY_CLASS *qclasses; unsigned rcnt; register unsigned i; result->type = SYMBOL; result->value = EnvFalseSymbol(theEnv,execStatus); qclasses = DetermineQueryClasses(theEnv,execStatus,GetFirstArgument()->nextArg->nextArg, "delayed-do-for-all-instances",&rcnt); if (qclasses == NULL) return; PushQueryCore(theEnv,execStatus); InstanceQueryData(theEnv,execStatus)->QueryCore = get_struct(theEnv,execStatus,query_core); InstanceQueryData(theEnv,execStatus)->QueryCore->solns = (INSTANCE_TYPE **) gm2(theEnv,execStatus,(sizeof(INSTANCE_TYPE *) * rcnt)); InstanceQueryData(theEnv,execStatus)->QueryCore->query = GetFirstArgument(); InstanceQueryData(theEnv,execStatus)->QueryCore->action = NULL; InstanceQueryData(theEnv,execStatus)->QueryCore->soln_set = NULL; InstanceQueryData(theEnv,execStatus)->QueryCore->soln_size = rcnt; InstanceQueryData(theEnv,execStatus)->QueryCore->soln_cnt = 0; TestEntireChain(theEnv,execStatus,qclasses,0); InstanceQueryData(theEnv,execStatus)->AbortQuery = FALSE; InstanceQueryData(theEnv,execStatus)->QueryCore->action = GetFirstArgument()->nextArg; while (InstanceQueryData(theEnv,execStatus)->QueryCore->soln_set != NULL) { for (i = 0 ; i < rcnt ; i++) InstanceQueryData(theEnv,execStatus)->QueryCore->solns[i] = InstanceQueryData(theEnv,execStatus)->QueryCore->soln_set->soln[i]; PopQuerySoln(theEnv,execStatus); execStatus->CurrentEvaluationDepth++; EvaluateExpression(theEnv,execStatus,InstanceQueryData(theEnv,execStatus)->QueryCore->action,result); execStatus->CurrentEvaluationDepth--; if (ProcedureFunctionData(theEnv,execStatus)->ReturnFlag == TRUE) { PropagateReturnValue(theEnv,execStatus,result); } PeriodicCleanup(theEnv,execStatus,FALSE,TRUE); if (execStatus->HaltExecution || ProcedureFunctionData(theEnv,execStatus)->BreakFlag || ProcedureFunctionData(theEnv,execStatus)->ReturnFlag) { while (InstanceQueryData(theEnv,execStatus)->QueryCore->soln_set != NULL) PopQuerySoln(theEnv,execStatus); break; } } ProcedureFunctionData(theEnv,execStatus)->BreakFlag = FALSE; rm(theEnv,execStatus,(void *) InstanceQueryData(theEnv,execStatus)->QueryCore->solns,(sizeof(INSTANCE_TYPE *) * rcnt)); rtn_struct(theEnv,execStatus,query_core,InstanceQueryData(theEnv,execStatus)->QueryCore); PopQueryCore(theEnv,execStatus); DeleteQueryClasses(theEnv,execStatus,qclasses); }
/****************************************************************************** NAME : QueryFindAllInstances DESCRIPTION : Finds all sets of instances which satisfy the query and stores their names in the user's multi-field variable The sets are stored sequentially : Number of sets = (Multi-field length) / (Set length) The first set is if the first (set length) atoms of the multi-field variable, and so on. 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. NOTES : H/L Syntax : See ParseQueryNoAction() ******************************************************************************/ globle void QueryFindAllInstances( void *theEnv, EXEC_STATUS, DATA_OBJECT *result) { QUERY_CLASS *qclasses; unsigned rcnt; register unsigned i,j; result->type = MULTIFIELD; result->begin = 0; result->end = -1; qclasses = DetermineQueryClasses(theEnv,execStatus,GetFirstArgument()->nextArg, "find-all-instances",&rcnt); if (qclasses == NULL) { result->value = (void *) EnvCreateMultifield(theEnv,execStatus,0L); return; } PushQueryCore(theEnv,execStatus); InstanceQueryData(theEnv,execStatus)->QueryCore = get_struct(theEnv,execStatus,query_core); InstanceQueryData(theEnv,execStatus)->QueryCore->solns = (INSTANCE_TYPE **) gm2(theEnv,execStatus,(sizeof(INSTANCE_TYPE *) * rcnt)); InstanceQueryData(theEnv,execStatus)->QueryCore->query = GetFirstArgument(); InstanceQueryData(theEnv,execStatus)->QueryCore->action = NULL; InstanceQueryData(theEnv,execStatus)->QueryCore->soln_set = NULL; InstanceQueryData(theEnv,execStatus)->QueryCore->soln_size = rcnt; InstanceQueryData(theEnv,execStatus)->QueryCore->soln_cnt = 0; TestEntireChain(theEnv,execStatus,qclasses,0); InstanceQueryData(theEnv,execStatus)->AbortQuery = FALSE; result->value = (void *) EnvCreateMultifield(theEnv,execStatus,InstanceQueryData(theEnv,execStatus)->QueryCore->soln_cnt * rcnt); while (InstanceQueryData(theEnv,execStatus)->QueryCore->soln_set != NULL) { for (i = 0 , j = (unsigned) (result->end + 2) ; i < rcnt ; i++ , j++) { SetMFType(result->value,j,INSTANCE_NAME); SetMFValue(result->value,j,GetFullInstanceName(theEnv,execStatus,InstanceQueryData(theEnv,execStatus)->QueryCore->soln_set->soln[i])); } result->end = (long) j-2; PopQuerySoln(theEnv,execStatus); } rm(theEnv,execStatus,(void *) InstanceQueryData(theEnv,execStatus)->QueryCore->solns,(sizeof(INSTANCE_TYPE *) * rcnt)); rtn_struct(theEnv,execStatus,query_core,InstanceQueryData(theEnv,execStatus)->QueryCore); PopQueryCore(theEnv,execStatus); DeleteQueryClasses(theEnv,execStatus,qclasses); }