1 /*******************************************************/
2 /* "C" Language Integrated Production System */
3 /* */
4 /* CLIPS Version 6.30 01/25/15 */
5 /* */
6 /* DEFTEMPLATE MODULE */
7 /*******************************************************/
8
9 /*************************************************************/
10 /* Purpose: Defines basic deftemplate primitive functions */
11 /* such as allocating and deallocating, traversing, and */
12 /* finding deftemplate data structures. */
13 /* */
14 /* Principal Programmer(s): */
15 /* Gary D. Riley */
16 /* */
17 /* Contributing Programmer(s): */
18 /* Brian L. Dantes */
19 /* */
20 /* Revision History: */
21 /* */
22 /* 6.23: Added support for templates maintaining their */
23 /* own list of facts. */
24 /* */
25 /* 6.24: Renamed BOOLEAN macro type to intBool. */
26 /* */
27 /* Corrected code to remove run-time program */
28 /* compiler warnings. */
29 /* */
30 /* 6.30: Added code for deftemplate run time */
31 /* initialization of hashed comparisons to */
32 /* constants. */
33 /* */
34 /* Removed conditional code for unsupported */
35 /* compilers/operating systems (IBM_MCW, */
36 /* MAC_MCW, and IBM_TBC). */
37 /* */
38 /* Support for deftemplate slot facets. */
39 /* */
40 /* Added const qualifiers to remove C++ */
41 /* deprecation warnings. */
42 /* */
43 /* Converted API macros to function calls. */
44 /* */
45 /* Changed find construct functionality so that */
46 /* imported modules are search when locating a */
47 /* named construct. */
48 /* */
49 /*************************************************************/
50
51 #define _TMPLTDEF_SOURCE_
52
53 #include "setup.h"
54
55 #if DEFTEMPLATE_CONSTRUCT
56
57 #include <stdio.h>
58 #define _STDIO_INCLUDED_
59
60 #include "memalloc.h"
61 #include "exprnops.h"
62 #include "cstrccom.h"
63 #include "network.h"
64 #include "tmpltpsr.h"
65 #include "tmpltbsc.h"
66 #include "tmpltutl.h"
67 #include "tmpltfun.h"
68 #include "router.h"
69 #include "modulpsr.h"
70 #include "modulutl.h"
71 #include "cstrnchk.h"
72 #include "envrnmnt.h"
73
74 #if BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE
75 #include "bload.h"
76 #include "tmpltbin.h"
77 #endif
78
79 #if CONSTRUCT_COMPILER && (! RUN_TIME)
80 #include "tmpltcmp.h"
81 #endif
82
83 #include "tmpltdef.h"
84
85 /***************************************/
86 /* LOCAL INTERNAL FUNCTION DEFINITIONS */
87 /***************************************/
88
89 static void *AllocateModule(void *);
90 static void ReturnModule(void *,void *);
91 static void ReturnDeftemplate(void *,void *);
92 static void InitializeDeftemplateModules(void *);
93 static void DeallocateDeftemplateData(void *);
94 static void DestroyDeftemplateAction(void *,struct constructHeader *,void *);
95 static void DestroyDeftemplate(void *,void *);
96 #if RUN_TIME
97 static void RuntimeDeftemplateAction(void *,struct constructHeader *,void *);
98 static void SearchForHashedPatternNodes(void *,struct factPatternNode *);
99 #endif
100
101 /******************************************************************/
102 /* InitializeDeftemplates: Initializes the deftemplate construct. */
103 /******************************************************************/
InitializeDeftemplates(void * theEnv)104 globle void InitializeDeftemplates(
105 void *theEnv)
106 {
107 globle struct entityRecord deftemplatePtrRecord = { "DEFTEMPLATE_PTR",
108 DEFTEMPLATE_PTR,1,0,0,
109 NULL,
110 NULL,NULL,
111 NULL,
112 NULL,
113 DecrementDeftemplateBusyCount,
114 IncrementDeftemplateBusyCount,
115 NULL,NULL,NULL,NULL,NULL };
116 AllocateEnvironmentData(theEnv,DEFTEMPLATE_DATA,sizeof(struct deftemplateData),DeallocateDeftemplateData);
117
118 memcpy(&DeftemplateData(theEnv)->DeftemplatePtrRecord,&deftemplatePtrRecord,sizeof(struct entityRecord));
119
120 InitializeFacts(theEnv);
121
122 InitializeDeftemplateModules(theEnv);
123
124 DeftemplateBasicCommands(theEnv);
125
126 DeftemplateFunctions(theEnv);
127
128 DeftemplateData(theEnv)->DeftemplateConstruct =
129 AddConstruct(theEnv,"deftemplate","deftemplates",ParseDeftemplate,EnvFindDeftemplate,
130 GetConstructNamePointer,GetConstructPPForm,
131 GetConstructModuleItem,EnvGetNextDeftemplate,SetNextConstruct,
132 EnvIsDeftemplateDeletable,EnvUndeftemplate,ReturnDeftemplate);
133
134 InstallPrimitive(theEnv,(ENTITY_RECORD_PTR) &DeftemplateData(theEnv)->DeftemplatePtrRecord,DEFTEMPLATE_PTR);
135 }
136
137 /******************************************************/
138 /* DeallocateDeftemplateData: Deallocates environment */
139 /* data for the deftemplate construct. */
140 /******************************************************/
DeallocateDeftemplateData(void * theEnv)141 static void DeallocateDeftemplateData(
142 void *theEnv)
143 {
144 #if ! RUN_TIME
145 struct deftemplateModule *theModuleItem;
146 void *theModule;
147 #endif
148 #if BLOAD || BLOAD_AND_BSAVE
149 if (Bloaded(theEnv)) return;
150 #endif
151
152 DoForAllConstructs(theEnv,DestroyDeftemplateAction,DeftemplateData(theEnv)->DeftemplateModuleIndex,FALSE,NULL);
153
154 #if ! RUN_TIME
155 for (theModule = EnvGetNextDefmodule(theEnv,NULL);
156 theModule != NULL;
157 theModule = EnvGetNextDefmodule(theEnv,theModule))
158 {
159 theModuleItem = (struct deftemplateModule *)
160 GetModuleItem(theEnv,(struct defmodule *) theModule,
161 DeftemplateData(theEnv)->DeftemplateModuleIndex);
162 rtn_struct(theEnv,deftemplateModule,theModuleItem);
163 }
164 #endif
165 }
166
167 /*****************************************************/
168 /* DestroyDeftemplateAction: Action used to remove */
169 /* deftemplates as a result of DestroyEnvironment. */
170 /*****************************************************/
DestroyDeftemplateAction(void * theEnv,struct constructHeader * theConstruct,void * buffer)171 static void DestroyDeftemplateAction(
172 void *theEnv,
173 struct constructHeader *theConstruct,
174 void *buffer)
175 {
176 #if MAC_XCD
177 #pragma unused(buffer)
178 #endif
179 struct deftemplate *theDeftemplate = (struct deftemplate *) theConstruct;
180
181 if (theDeftemplate == NULL) return;
182
183 DestroyDeftemplate(theEnv,theDeftemplate);
184 }
185
186
187 /*************************************************************/
188 /* InitializeDeftemplateModules: Initializes the deftemplate */
189 /* construct for use with the defmodule construct. */
190 /*************************************************************/
InitializeDeftemplateModules(void * theEnv)191 static void InitializeDeftemplateModules(
192 void *theEnv)
193 {
194 DeftemplateData(theEnv)->DeftemplateModuleIndex = RegisterModuleItem(theEnv,"deftemplate",
195 AllocateModule,
196 ReturnModule,
197 #if BLOAD_AND_BSAVE || BLOAD || BLOAD_ONLY
198 BloadDeftemplateModuleReference,
199 #else
200 NULL,
201 #endif
202 #if CONSTRUCT_COMPILER && (! RUN_TIME)
203 DeftemplateCModuleReference,
204 #else
205 NULL,
206 #endif
207 EnvFindDeftemplateInModule);
208
209 #if (! BLOAD_ONLY) && (! RUN_TIME) && DEFMODULE_CONSTRUCT
210 AddPortConstructItem(theEnv,"deftemplate",SYMBOL);
211 #endif
212 }
213
214 /***************************************************/
215 /* AllocateModule: Allocates a deftemplate module. */
216 /***************************************************/
AllocateModule(void * theEnv)217 static void *AllocateModule(
218 void *theEnv)
219 {
220 return((void *) get_struct(theEnv,deftemplateModule));
221 }
222
223 /*************************************************/
224 /* ReturnModule: Deallocates a deftemplate module. */
225 /*************************************************/
ReturnModule(void * theEnv,void * theItem)226 static void ReturnModule(
227 void *theEnv,
228 void *theItem)
229 {
230 FreeConstructHeaderModule(theEnv,(struct defmoduleItemHeader *) theItem,DeftemplateData(theEnv)->DeftemplateConstruct);
231 rtn_struct(theEnv,deftemplateModule,theItem);
232 }
233
234 /****************************************************************/
235 /* GetDeftemplateModuleItem: Returns a pointer to the defmodule */
236 /* item for the specified deftemplate or defmodule. */
237 /****************************************************************/
GetDeftemplateModuleItem(void * theEnv,struct defmodule * theModule)238 globle struct deftemplateModule *GetDeftemplateModuleItem(
239 void *theEnv,
240 struct defmodule *theModule)
241 {
242 return((struct deftemplateModule *) GetConstructModuleItemByIndex(theEnv,theModule,DeftemplateData(theEnv)->DeftemplateModuleIndex));
243 }
244
245 /*****************************************************/
246 /* EnvFindDeftemplate: Searches for a deftemplate in */
247 /* the list of deftemplates. Returns a pointer to */
248 /* the deftemplate if found, otherwise NULL. */
249 /*****************************************************/
EnvFindDeftemplate(void * theEnv,const char * deftemplateName)250 globle void *EnvFindDeftemplate(
251 void *theEnv,
252 const char *deftemplateName)
253 {
254 return(FindNamedConstructInModuleOrImports(theEnv,deftemplateName,DeftemplateData(theEnv)->DeftemplateConstruct));
255 }
256
257 /*****************************************************/
258 /* EnvFindDeftemplateInModule: Searches for a deftemplate in */
259 /* the list of deftemplates. Returns a pointer to */
260 /* the deftemplate if found, otherwise NULL. */
261 /*****************************************************/
EnvFindDeftemplateInModule(void * theEnv,const char * deftemplateName)262 globle void *EnvFindDeftemplateInModule(
263 void *theEnv,
264 const char *deftemplateName)
265 {
266 return(FindNamedConstructInModule(theEnv,deftemplateName,DeftemplateData(theEnv)->DeftemplateConstruct));
267 }
268
269 /***********************************************************************/
270 /* EnvGetNextDeftemplate: If passed a NULL pointer, returns the first */
271 /* deftemplate in the ListOfDeftemplates. Otherwise returns the next */
272 /* deftemplate following the deftemplate passed as an argument. */
273 /***********************************************************************/
EnvGetNextDeftemplate(void * theEnv,void * deftemplatePtr)274 globle void *EnvGetNextDeftemplate(
275 void *theEnv,
276 void *deftemplatePtr)
277 {
278 return((void *) GetNextConstructItem(theEnv,(struct constructHeader *) deftemplatePtr,DeftemplateData(theEnv)->DeftemplateModuleIndex));
279 }
280
281 /***********************************************************/
282 /* EnvIsDeftemplateDeletable: Returns TRUE if a particular */
283 /* deftemplate can be deleted, otherwise returns FALSE. */
284 /***********************************************************/
EnvIsDeftemplateDeletable(void * theEnv,void * vTheDeftemplate)285 globle intBool EnvIsDeftemplateDeletable(
286 void *theEnv,
287 void *vTheDeftemplate)
288 {
289 struct deftemplate *theDeftemplate = (struct deftemplate *) vTheDeftemplate;
290
291 if (! ConstructsDeletable(theEnv))
292 { return FALSE; }
293
294 if (theDeftemplate->busyCount > 0) return(FALSE);
295 if (theDeftemplate->patternNetwork != NULL) return(FALSE);
296
297 return(TRUE);
298 }
299
300 /**************************************************************/
301 /* ReturnDeftemplate: Returns the data structures associated */
302 /* with a deftemplate construct to the pool of free memory. */
303 /**************************************************************/
ReturnDeftemplate(void * theEnv,void * vTheConstruct)304 static void ReturnDeftemplate(
305 void *theEnv,
306 void *vTheConstruct)
307 {
308 #if (! BLOAD_ONLY) && (! RUN_TIME)
309 struct deftemplate *theConstruct = (struct deftemplate *) vTheConstruct;
310 struct templateSlot *slotPtr;
311
312 if (theConstruct == NULL) return;
313
314 /*====================================================================*/
315 /* If a template is redefined, then we want to save its debug status. */
316 /*====================================================================*/
317
318 #if DEBUGGING_FUNCTIONS
319 DeftemplateData(theEnv)->DeletedTemplateDebugFlags = 0;
320 if (theConstruct->watch) BitwiseSet(DeftemplateData(theEnv)->DeletedTemplateDebugFlags,0);
321 #endif
322
323 /*===========================================*/
324 /* Free storage used by the templates slots. */
325 /*===========================================*/
326
327 slotPtr = theConstruct->slotList;
328 while (slotPtr != NULL)
329 {
330 DecrementSymbolCount(theEnv,slotPtr->slotName);
331 RemoveHashedExpression(theEnv,slotPtr->defaultList);
332 slotPtr->defaultList = NULL;
333 RemoveHashedExpression(theEnv,slotPtr->facetList);
334 slotPtr->facetList = NULL;
335 RemoveConstraint(theEnv,slotPtr->constraints);
336 slotPtr->constraints = NULL;
337 slotPtr = slotPtr->next;
338 }
339
340 ReturnSlots(theEnv,theConstruct->slotList);
341
342 /*==================================*/
343 /* Free storage used by the header. */
344 /*==================================*/
345
346 DeinstallConstructHeader(theEnv,&theConstruct->header);
347
348 rtn_struct(theEnv,deftemplate,theConstruct);
349 #endif
350 }
351
352 /**************************************************************/
353 /* DestroyDeftemplate: Returns the data structures associated */
354 /* with a deftemplate construct to the pool of free memory. */
355 /**************************************************************/
DestroyDeftemplate(void * theEnv,void * vTheConstruct)356 static void DestroyDeftemplate(
357 void *theEnv,
358 void *vTheConstruct)
359 {
360 struct deftemplate *theConstruct = (struct deftemplate *) vTheConstruct;
361 #if (! BLOAD_ONLY) && (! RUN_TIME)
362 struct templateSlot *slotPtr, *nextSlot;
363 #endif
364 if (theConstruct == NULL) return;
365
366 #if (! BLOAD_ONLY) && (! RUN_TIME)
367 slotPtr = theConstruct->slotList;
368
369 while (slotPtr != NULL)
370 {
371 nextSlot = slotPtr->next;
372 rtn_struct(theEnv,templateSlot,slotPtr);
373 slotPtr = nextSlot;
374 }
375 #endif
376
377 DestroyFactPatternNetwork(theEnv,theConstruct->patternNetwork);
378
379 /*==================================*/
380 /* Free storage used by the header. */
381 /*==================================*/
382
383 #if (! BLOAD_ONLY) && (! RUN_TIME)
384 DeinstallConstructHeader(theEnv,&theConstruct->header);
385
386 rtn_struct(theEnv,deftemplate,theConstruct);
387 #endif
388 }
389
390 /***********************************************/
391 /* ReturnSlots: Returns the slot structures of */
392 /* a deftemplate to free memory. */
393 /***********************************************/
ReturnSlots(void * theEnv,struct templateSlot * slotPtr)394 globle void ReturnSlots(
395 void *theEnv,
396 struct templateSlot *slotPtr)
397 {
398 #if (! BLOAD_ONLY) && (! RUN_TIME)
399 struct templateSlot *nextSlot;
400
401 while (slotPtr != NULL)
402 {
403 nextSlot = slotPtr->next;
404 ReturnExpression(theEnv,slotPtr->defaultList);
405 ReturnExpression(theEnv,slotPtr->facetList);
406 RemoveConstraint(theEnv,slotPtr->constraints);
407 rtn_struct(theEnv,templateSlot,slotPtr);
408 slotPtr = nextSlot;
409 }
410 #endif
411 }
412
413 /*************************************************/
414 /* DecrementDeftemplateBusyCount: Decrements the */
415 /* busy count of a deftemplate data structure. */
416 /*************************************************/
DecrementDeftemplateBusyCount(void * theEnv,void * vTheTemplate)417 globle void DecrementDeftemplateBusyCount(
418 void *theEnv,
419 void *vTheTemplate)
420 {
421 struct deftemplate *theTemplate = (struct deftemplate *) vTheTemplate;
422
423 if (! ConstructData(theEnv)->ClearInProgress) theTemplate->busyCount--;
424 }
425
426 /*************************************************/
427 /* IncrementDeftemplateBusyCount: Increments the */
428 /* busy count of a deftemplate data structure. */
429 /*************************************************/
IncrementDeftemplateBusyCount(void * theEnv,void * vTheTemplate)430 globle void IncrementDeftemplateBusyCount(
431 void *theEnv,
432 void *vTheTemplate)
433 {
434 struct deftemplate *theTemplate = (struct deftemplate *) vTheTemplate;
435 #if MAC_XCD
436 #pragma unused(theEnv)
437 #endif
438
439 theTemplate->busyCount++;
440 }
441
442 /*******************************************************************/
443 /* EnvGetNextFactInTemplate: If passed a NULL pointer, returns the */
444 /* first fact in the template's fact-list. Otherwise returns the */
445 /* next template fact following the fact passed as an argument. */
446 /*******************************************************************/
EnvGetNextFactInTemplate(void * theEnv,void * theTemplate,void * factPtr)447 globle void *EnvGetNextFactInTemplate(
448 void *theEnv,
449 void *theTemplate,
450 void *factPtr)
451 {
452 #if MAC_XCD
453 #pragma unused(theEnv)
454 #endif
455 if (factPtr == NULL)
456 { return((void *) ((struct deftemplate *) theTemplate)->factList); }
457
458 if (((struct fact *) factPtr)->garbage) return(NULL);
459
460 return((void *) ((struct fact *) factPtr)->nextTemplateFact);
461 }
462
463 #if ! RUN_TIME
464
465 /******************************/
466 /* CreateDeftemplateScopeMap: */
467 /******************************/
CreateDeftemplateScopeMap(void * theEnv,struct deftemplate * theDeftemplate)468 globle void *CreateDeftemplateScopeMap(
469 void *theEnv,
470 struct deftemplate *theDeftemplate)
471 {
472 unsigned scopeMapSize;
473 char *scopeMap;
474 const char *templateName;
475 struct defmodule *matchModule, *theModule;
476 int moduleID,count;
477 void *theBitMap;
478
479 templateName = ValueToString(theDeftemplate->header.name);
480 matchModule = theDeftemplate->header.whichModule->theModule;
481
482 scopeMapSize = (sizeof(char) * ((GetNumberOfDefmodules(theEnv) / BITS_PER_BYTE) + 1));
483 scopeMap = (char *) gm2(theEnv,scopeMapSize);
484
485 ClearBitString((void *) scopeMap,scopeMapSize);
486 SaveCurrentModule(theEnv);
487 for (theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL) ;
488 theModule != NULL ;
489 theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,(void *) theModule))
490 {
491 EnvSetCurrentModule(theEnv,(void *) theModule);
492 moduleID = (int) theModule->bsaveID;
493 if (FindImportedConstruct(theEnv,"deftemplate",matchModule,
494 templateName,&count,TRUE,NULL) != NULL)
495 SetBitMap(scopeMap,moduleID);
496 }
497 RestoreCurrentModule(theEnv);
498 theBitMap = EnvAddBitMap(theEnv,scopeMap,scopeMapSize);
499 IncrementBitMapCount(theBitMap);
500 rm(theEnv,(void *) scopeMap,scopeMapSize);
501 return(theBitMap);
502 }
503
504 #endif
505
506 #if RUN_TIME
507
508 /**************************************************/
509 /* RuntimeDeftemplateAction: Action to be applied */
510 /* to each deftemplate construct when a runtime */
511 /* initialization occurs. */
512 /**************************************************/
RuntimeDeftemplateAction(void * theEnv,struct constructHeader * theConstruct,void * buffer)513 static void RuntimeDeftemplateAction(
514 void *theEnv,
515 struct constructHeader *theConstruct,
516 void *buffer)
517 {
518 #if MAC_XCD
519 #pragma unused(buffer)
520 #endif
521 struct deftemplate *theDeftemplate = (struct deftemplate *) theConstruct;
522
523 SearchForHashedPatternNodes(theEnv,theDeftemplate->patternNetwork);
524 }
525
526 /*******************************************************************/
527 /* SearchForHashedPatternNodes: */
528 /*******************************************************************/
SearchForHashedPatternNodes(void * theEnv,struct factPatternNode * theNode)529 static void SearchForHashedPatternNodes(
530 void *theEnv,
531 struct factPatternNode *theNode)
532 {
533 while (theNode != NULL)
534 {
535 if ((theNode->lastLevel != NULL) && (theNode->lastLevel->header.selector))
536 { AddHashedPatternNode(theEnv,theNode->lastLevel,theNode,theNode->networkTest->type,theNode->networkTest->value); }
537
538 SearchForHashedPatternNodes(theEnv,theNode->nextLevel);
539
540 theNode = theNode->rightNode;
541 }
542 }
543
544 /*******************************************************************/
545 /* DeftemplateRunTimeInitialize: */
546 /*******************************************************************/
DeftemplateRunTimeInitialize(void * theEnv)547 globle void DeftemplateRunTimeInitialize(
548 void *theEnv)
549 {
550 DoForAllConstructs(theEnv,RuntimeDeftemplateAction,DeftemplateData(theEnv)->DeftemplateModuleIndex,TRUE,NULL);
551 }
552
553 #endif /* RUN_TIME */
554
555 /*##################################*/
556 /* Additional Environment Functions */
557 /*##################################*/
558
EnvDeftemplateModule(void * theEnv,void * theDeftemplate)559 globle const char *EnvDeftemplateModule(
560 void *theEnv,
561 void *theDeftemplate)
562 {
563 return GetConstructModuleName((struct constructHeader *) theDeftemplate);
564 }
565
EnvGetDeftemplateName(void * theEnv,void * theDeftemplate)566 globle const char *EnvGetDeftemplateName(
567 void *theEnv,
568 void *theDeftemplate)
569 {
570 return GetConstructNameString((struct constructHeader *) theDeftemplate);
571 }
572
EnvGetDeftemplatePPForm(void * theEnv,void * theDeftemplate)573 globle const char *EnvGetDeftemplatePPForm(
574 void *theEnv,
575 void *theDeftemplate)
576 {
577 return GetConstructPPForm(theEnv,(struct constructHeader *) theDeftemplate);
578 }
579
580 /*#####################################*/
581 /* ALLOW_ENVIRONMENT_GLOBALS Functions */
582 /*#####################################*/
583
584 #if ALLOW_ENVIRONMENT_GLOBALS
585
DeftemplateModule(void * theDeftemplate)586 globle const char *DeftemplateModule(
587 void *theDeftemplate)
588 {
589 return EnvDeftemplateModule(GetCurrentEnvironment(),theDeftemplate);
590 }
591
FindDeftemplate(const char * deftemplateName)592 globle void *FindDeftemplate(
593 const char *deftemplateName)
594 {
595 return EnvFindDeftemplate(GetCurrentEnvironment(),deftemplateName);
596 }
597
GetDeftemplateName(void * theDeftemplate)598 globle const char *GetDeftemplateName(
599 void *theDeftemplate)
600 {
601 return EnvGetDeftemplateName(GetCurrentEnvironment(),theDeftemplate);
602 }
603
GetDeftemplatePPForm(void * theDeftemplate)604 globle const char *GetDeftemplatePPForm(
605 void *theDeftemplate)
606 {
607 return EnvGetDeftemplatePPForm(GetCurrentEnvironment(),theDeftemplate);
608 }
609
GetNextDeftemplate(void * deftemplatePtr)610 globle void *GetNextDeftemplate(
611 void *deftemplatePtr)
612 {
613 return EnvGetNextDeftemplate(GetCurrentEnvironment(),deftemplatePtr);
614 }
615
IsDeftemplateDeletable(void * vTheDeftemplate)616 globle intBool IsDeftemplateDeletable(
617 void *vTheDeftemplate)
618 {
619 return EnvIsDeftemplateDeletable(GetCurrentEnvironment(),vTheDeftemplate);
620 }
621
GetNextFactInTemplate(void * theTemplate,void * factPtr)622 globle void *GetNextFactInTemplate(
623 void *theTemplate,
624 void *factPtr)
625 {
626 return EnvGetNextFactInTemplate(GetCurrentEnvironment(),theTemplate,factPtr);
627 }
628
629 #endif /* ALLOW_ENVIRONMENT_GLOBALS */
630
631 #endif /* DEFTEMPLATE_CONSTRUCT */
632
633
634