📄 tmpltutl.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 06/05/06 */
/* */
/* DEFTEMPLATE UTILITIES MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Provides utility routines for deftemplates. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* Brian L. Donnell */
/* */
/* Revision History: */
/* 6.23: Added support for templates maintaining their */
/* own list of facts. */
/* */
/* 6.24: Renamed BOOLEAN macro type to intBool. */
/* */
/* Added additional arguments to */
/* InvalidDeftemplateSlotMessage function. */
/* */
/* Added additional arguments to */
/* PrintTemplateFact function. */
/* */
/*************************************************************/
#define _TMPLTUTL_SOURCE_
#include "setup.h"
#if DEFTEMPLATE_CONSTRUCT
#include <stdio.h>
#define _STDIO_INCLUDED_
#include <string.h>
#include "extnfunc.h"
#include "memalloc.h"
#include "constrct.h"
#include "router.h"
#include "argacces.h"
#include "cstrnchk.h"
#include "envrnmnt.h"
#include "tmpltfun.h"
#include "tmpltpsr.h"
#include "modulutl.h"
#include "watch.h"
#include "tmpltbsc.h"
#include "tmpltdef.h"
#include "tmpltutl.h"
/********************************************************/
/* InvalidDeftemplateSlotMessage: Generic error message */
/* for use when a specified slot name isn't defined */
/* in its corresponding deftemplate. */
/********************************************************/
globle void InvalidDeftemplateSlotMessage(
void *theEnv,
char *slotName,
char *deftemplateName,
int printCR)
{
PrintErrorID(theEnv,"TMPLTDEF",1,printCR);
EnvPrintRouter(theEnv,WERROR,"Invalid slot ");
EnvPrintRouter(theEnv,WERROR,slotName);
EnvPrintRouter(theEnv,WERROR," not defined in corresponding deftemplate ");
EnvPrintRouter(theEnv,WERROR,deftemplateName);
EnvPrintRouter(theEnv,WERROR,".\n");
}
/**********************************************************/
/* SingleFieldSlotCardinalityError: Generic error message */
/* used when an attempt is made to placed a multifield */
/* value into a single field slot. */
/**********************************************************/
globle void SingleFieldSlotCardinalityError(
void *theEnv,
char *slotName)
{
PrintErrorID(theEnv,"TMPLTDEF",2,TRUE);
EnvPrintRouter(theEnv,WERROR,"The single field slot ");
EnvPrintRouter(theEnv,WERROR,slotName);
EnvPrintRouter(theEnv,WERROR," can only contain a single field value.\n");
}
/**********************************************************************/
/* MultiIntoSingleFieldSlotError: Determines if a multifield value is */
/* being placed into a single field slot of a deftemplate fact. */
/**********************************************************************/
globle void MultiIntoSingleFieldSlotError(
void *theEnv,
struct templateSlot *theSlot,
struct deftemplate *theDeftemplate)
{
PrintErrorID(theEnv,"TMPLTFUN",2,TRUE);
EnvPrintRouter(theEnv,WERROR,"Attempted to assert a multifield value \n");
EnvPrintRouter(theEnv,WERROR,"into the single field slot ");
if (theSlot != NULL) EnvPrintRouter(theEnv,WERROR,theSlot->slotName->contents);
else EnvPrintRouter(theEnv,WERROR,"<<unknown>>");
EnvPrintRouter(theEnv,WERROR," of deftemplate ");
if (theDeftemplate != NULL) EnvPrintRouter(theEnv,WERROR,theDeftemplate->header.name->contents);
else EnvPrintRouter(theEnv,WERROR,"<<unknown>>");
EnvPrintRouter(theEnv,WERROR,".\n");
SetEvaluationError(theEnv,TRUE);
}
/**************************************************************/
/* CheckTemplateFact: Checks a fact to see if it violates any */
/* deftemplate type, allowed-..., or range specifications. */
/**************************************************************/
globle void CheckTemplateFact(
void *theEnv,
struct fact *theFact)
{
struct field *sublist;
int i;
struct deftemplate *theDeftemplate;
struct templateSlot *slotPtr;
DATA_OBJECT theData;
char thePlace[20];
int rv;
if (! EnvGetDynamicConstraintChecking(theEnv)) return;
sublist = theFact->theProposition.theFields;
/*========================================================*/
/* If the deftemplate corresponding to the first field of */
/* of the fact cannot be found, then the fact cannot be */
/* checked against the deftemplate format. */
/*========================================================*/
theDeftemplate = theFact->whichDeftemplate;
if (theDeftemplate == NULL) return;
if (theDeftemplate->implied) return;
/*=============================================*/
/* Check each of the slots of the deftemplate. */
/*=============================================*/
i = 0;
for (slotPtr = theDeftemplate->slotList;
slotPtr != NULL;
slotPtr = slotPtr->next)
{
/*================================================*/
/* Store the slot value in the appropriate format */
/* for a call to the constraint checking routine. */
/*================================================*/
if (slotPtr->multislot == FALSE)
{
theData.type = sublist[i].type;
theData.value = sublist[i].value;
i++;
}
else
{
theData.type = MULTIFIELD;
theData.value = (void *) sublist[i].value;
SetDOBegin(theData,1);
SetDOEnd(theData,((struct multifield *) sublist[i].value)->multifieldLength);
i++;
}
/*=============================================*/
/* Call the constraint checking routine to see */
/* if a constraint violation occurred. */
/*=============================================*/
rv = ConstraintCheckDataObject(theEnv,&theData,slotPtr->constraints);
if (rv != NO_VIOLATION)
{
sprintf(thePlace,"fact f-%-5ld ",theFact->factIndex);
PrintErrorID(theEnv,"CSTRNCHK",1,TRUE);
EnvPrintRouter(theEnv,WERROR,"Slot value ");
PrintDataObject(theEnv,WERROR,&theData);
EnvPrintRouter(theEnv,WERROR," ");
ConstraintViolationErrorMessage(theEnv,NULL,thePlace,FALSE,0,slotPtr->slotName,
0,rv,slotPtr->constraints,TRUE);
SetHaltExecution(theEnv,TRUE);
return;
}
}
return;
}
/***********************************************************************/
/* CheckRHSSlotTypes: Checks the validity of a change to a slot as the */
/* result of an assert, modify, or duplicate command. This checking */
/* is performed statically (i.e. when the command is being parsed). */
/***********************************************************************/
globle intBool CheckRHSSlotTypes(
void *theEnv,
struct expr *rhsSlots,
struct templateSlot *slotPtr,
char *thePlace)
{
int rv;
char *theName;
if (EnvGetStaticConstraintChecking(theEnv) == FALSE) return(TRUE);
rv = ConstraintCheckExpressionChain(theEnv,rhsSlots,slotPtr->constraints);
if (rv != NO_VIOLATION)
{
if (rv != CARDINALITY_VIOLATION) theName = "A literal slot value";
else theName = "Literal slot values";
ConstraintViolationErrorMessage(theEnv,theName,thePlace,TRUE,0,
slotPtr->slotName,0,rv,slotPtr->constraints,TRUE);
return(0);
}
return(1);
}
/*********************************************************/
/* GetNthSlot: Given a deftemplate and an integer index, */
/* returns the nth slot of a deftemplate. */
/*********************************************************/
globle struct templateSlot *GetNthSlot(
struct deftemplate *theDeftemplate,
int position)
{
struct templateSlot *slotPtr;
int i = 0;
slotPtr = theDeftemplate->slotList;
while (slotPtr != NULL)
{
if (i == position) return(slotPtr);
slotPtr = slotPtr->next;
i++;
}
return(NULL);
}
/*******************************************************/
/* FindSlotPosition: Finds the position of a specified */
/* slot in a deftemplate structure. */
/*******************************************************/
globle int FindSlotPosition(
struct deftemplate *theDeftemplate,
SYMBOL_HN *name)
{
struct templateSlot *slotPtr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -