📄 tmpltfun.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.05 04/09/97 */ /* */ /* DEFTEMPLATE FUNCTIONS MODULE */ /*******************************************************//*************************************************************//* Purpose: Implements the modify and duplicate functions. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* *//*************************************************************/#define _TMPLTFUN_SOURCE_#include "setup.h"#if DEFTEMPLATE_CONSTRUCT#include <stdio.h>#define _CLIPS_STDIO_#include <string.h>#include "constant.h"#include "clipsmem.h"#include "symbol.h"#include "scanner.h"#include "exprnpsr.h"#include "argacces.h"#include "router.h"#include "cstrnchk.h"#include "default.h"#include "factmngr.h"#include "commline.h"#include "factrhs.h"#include "modulutl.h"#include "reorder.h"#include "tmpltdef.h"#include "tmpltlhs.h"#include "tmpltutl.h"#include "tmpltrhs.h"#include "tmpltfun.h"/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/#if ANSI_COMPILER static VOID DuplicateModifyCommand(int,DATA_OBJECT_PTR);#if (! RUN_TIME) && (! BLOAD_ONLY) static struct expr *ModAndDupParse(struct expr *,char *,char *); static SYMBOL_HN *FindTemplateForFactAddress(SYMBOL_HN *,struct lhsParseNode *);#endif#else static VOID DuplicateModifyCommand();#if (! RUN_TIME) && (! BLOAD_ONLY) static struct expr *ModAndDupParse(); static SYMBOL_HN *FindTemplateForFactAddress();#endif#endif /****************************************************************//* DeftemplateFunctions: Initializes the deftemplate functions. *//****************************************************************/globle VOID DeftemplateFunctions() { #if ! RUN_TIME DefineFunction("modify",'u', PTIF ModifyCommand,"ModifyCommand"); DefineFunction("duplicate",'u', PTIF DuplicateCommand,"DuplicateCommand");#if (! BLOAD_ONLY) AddFunctionParser("modify",ModifyParse); AddFunctionParser("duplicate",DuplicateParse);#endif FuncSeqOvlFlags("modify",CLIPS_FALSE,CLIPS_FALSE); FuncSeqOvlFlags("duplicate",CLIPS_FALSE,CLIPS_FALSE);#endif } /*********************************************************************//* ModifyCommand: CLIPS access routine for the modify command. Calls *//* the DuplicateModifyCommand function to perform the actual work. *//*********************************************************************/globle VOID ModifyCommand(returnValue) DATA_OBJECT_PTR returnValue; { DuplicateModifyCommand(CLIPS_TRUE,returnValue); }/***************************************************************************//* DuplicateCommand: CLIPS access routine for the duplicate command. Calls *//* the DuplicateModifyCommand function to perform the actual work. *//***************************************************************************/globle VOID DuplicateCommand(returnValue) DATA_OBJECT_PTR returnValue; { DuplicateModifyCommand(CLIPS_FALSE,returnValue); }/***************************************************************//* DuplicateModifyCommand: Implements the duplicate and modify *//* commands. The fact being duplicated or modified is first *//* copied to a new fact. Replacements to the fields of the *//* new fact are then made. If a modify command is being *//* performed, the original fact is retracted. Lastly, the *//* new fact is asserted. *//***************************************************************/static VOID DuplicateModifyCommand(retractIt,returnValue) int retractIt; DATA_OBJECT_PTR returnValue; { long int factNum; struct fact *oldFact, *newFact, *theFact; struct expr *testPtr; DATA_OBJECT computeResult; struct deftemplate *templatePtr; struct templateSlot *slotPtr; int i, position, found; /*===================================================*/ /* Set the default return value to the symbol FALSE. */ /*===================================================*/ SetpType(returnValue,SYMBOL); SetpValue(returnValue,CLIPSFalseSymbol); /*==================================================*/ /* Evaluate the first argument which is used to get */ /* a pointer to the fact to be modified/duplicated. */ /*==================================================*/ testPtr = GetFirstArgument(); EvaluateExpression(testPtr,&computeResult); /*==============================================================*/ /* If an integer is supplied, then treat it as a fact-index and */ /* search the fact-list for the fact with that fact-index. */ /*==============================================================*/ if (computeResult.type == INTEGER) { factNum = ValueToLong(computeResult.value); if (factNum < 0) { if (retractIt) ExpectedTypeError2("modify",1); else ExpectedTypeError2("duplicate",1); SetEvaluationError(CLIPS_TRUE); return; } oldFact = (struct fact *) GetNextFact(NULL); while (oldFact != NULL) { if (oldFact->factIndex == factNum) { break; } else { oldFact = oldFact->nextFact; } } if (oldFact == NULL) { char tempBuffer[20]; sprintf(tempBuffer,"f-%ld",factNum); CantFindItemErrorMessage("fact",tempBuffer); return; } } /*==========================================*/ /* Otherwise, if a pointer is supplied then */ /* no lookup is required. */ /*==========================================*/ else if (computeResult.type == FACT_ADDRESS) { oldFact = (struct fact *) computeResult.value; } /*===========================================*/ /* Otherwise, the first argument is invalid. */ /*===========================================*/ else { if (retractIt) ExpectedTypeError2("modify",1); else ExpectedTypeError2("duplicate",1); SetEvaluationError(CLIPS_TRUE); return; } /*==================================*/ /* See if it is a deftemplate fact. */ /*==================================*/ templatePtr = oldFact->whichDeftemplate; if (templatePtr->implied) return; /*================================================================*/ /* Duplicate the values from the old fact (skipping multifields). */ /*================================================================*/ newFact = (struct fact *) CreateFactBySize((int) oldFact->theProposition.multifieldLength); newFact->whichDeftemplate = templatePtr; for (i = 0; i < (int) oldFact->theProposition.multifieldLength; i++) { newFact->theProposition.theFields[i].type = oldFact->theProposition.theFields[i].type; if (newFact->theProposition.theFields[i].type != MULTIFIELD) { newFact->theProposition.theFields[i].value = oldFact->theProposition.theFields[i].value; } else { newFact->theProposition.theFields[i].value = NULL; } } /*========================*/ /* Start replacing slots. */ /*========================*/ testPtr = testPtr->nextArg; while (testPtr != NULL) { /*============================================================*/ /* If the slot identifier is an integer, then the slot was */ /* previously identified and its position within the template */ /* was stored. Otherwise, the position of the slot within the */ /* deftemplate has to be determined by comparing the name of */ /* the slot against the list of slots for the deftemplate. */ /*============================================================*/ if (testPtr->type == INTEGER) { position = (int) ValueToLong(testPtr->value); } else { found = CLIPS_FALSE; position = 0; slotPtr = templatePtr->slotList; while (slotPtr != NULL) { if (slotPtr->slotName == (SYMBOL_HN *) testPtr->value) { found = CLIPS_TRUE; slotPtr = NULL; } else { slotPtr = slotPtr->next; position++; } } if (! found) { InvalidDeftemplateSlotMessage(ValueToString(testPtr->value), ValueToString(templatePtr->header.name)); SetEvaluationError(CLIPS_TRUE); ReturnFact(newFact); return; } } /*===================================================*/ /* If a single field slot is being replaced, then... */ /*===================================================*/ if (newFact->theProposition.theFields[position].type != MULTIFIELD) { /*======================================================*/ /* If the list of values to store in the slot is empty */ /* or contains more than one member than an error has */ /* occured because a single field slot can only contain */ /* a single value. */ /*======================================================*/ if ((testPtr->argList == NULL) ? TRUE : (testPtr->argList->nextArg != NULL)) { MultiIntoSingleFieldSlotError(GetNthSlot(templatePtr,position),templatePtr); ReturnFact(newFact); return; } /*===================================================*/ /* Evaluate the expression to be stored in the slot. */ /*===================================================*/ EvaluateExpression(testPtr->argList,&computeResult); SetEvaluationError(CLIPS_FALSE); /*====================================================*/ /* If the expression evaluated to a multifield value, */ /* then an error occured since a multifield value can */ /* not be stored in a single field slot. */ /*====================================================*/ if (computeResult.type == MULTIFIELD) { ReturnFact(newFact); MultiIntoSingleFieldSlotError(GetNthSlot(templatePtr,position),templatePtr); return; } /*=============================*/ /* Store the value in the slot */ /*=============================*/ newFact->theProposition.theFields[position].type = (short) computeResult.type; newFact->theProposition.theFields[position].value = computeResult.value; } /*=================================*/ /* Else replace a multifield slot. */ /*=================================*/ else { /*======================================*/ /* Determine the new value of the slot. */ /*======================================*/ StoreInMultifield(&computeResult,testPtr->argList,CLIPS_FALSE); SetEvaluationError(CLIPS_FALSE); /*=============================*/ /* Store the value in the slot */ /*=============================*/ newFact->theProposition.theFields[position].type = (short) computeResult.type; newFact->theProposition.theFields[position].value = computeResult.value; } testPtr = testPtr->nextArg; } /*=====================================*/ /* Copy the multifield values from the */ /* old fact that were not replaced. */ /*=====================================*/ for (i = 0; i < (int) oldFact->theProposition.multifieldLength; i++) { if ((newFact->theProposition.theFields[i].type == MULTIFIELD) && (newFact->theProposition.theFields[i].value == NULL)) { newFact->theProposition.theFields[i].value = CopyMultifield(oldFact->theProposition.theFields[i].value); } } /*======================================*/ /* Perform the duplicate/modify action. */ /*======================================*/ if (retractIt) Retract(oldFact); theFact = (struct fact *) Assert(newFact); /*========================================*/ /* The asserted fact is the return value. */ /*========================================*/ if (theFact != NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -