1    /*******************************************************/
2    /*      "C" Language Integrated Production System      */
3    /*                                                     */
4    /*             CLIPS Version 6.30  01/25/15            */
5    /*                                                     */
6    /*                  CONSTRUCT MODULE                   */
7    /*******************************************************/
8 
9 /*************************************************************/
10 /* Purpose: Provides basic functionality for creating new    */
11 /*   types of constructs, saving constructs to a file, and   */
12 /*   adding new functionality to the clear and reset         */
13 /*   commands.                                               */
14 /*                                                           */
15 /* Principal Programmer(s):                                  */
16 /*      Gary D. Riley                                        */
17 /*                                                           */
18 /* Contributing Programmer(s):                               */
19 /*                                                           */
20 /* Revision History:                                         */
21 /*                                                           */
22 /*      6.24: Added environment parameter to GenClose.       */
23 /*            Added environment parameter to GenOpen.        */
24 /*                                                           */
25 /*            Renamed BOOLEAN macro type to intBool.         */
26 /*                                                           */
27 /*      6.30: Changed garbage collection algorithm.          */
28 /*                                                           */
29 /*            Removed conditional code for unsupported       */
30 /*            compilers/operating systems (IBM_MCW and       */
31 /*            MAC_MCW).                                      */
32 /*                                                           */
33 /*            Added code for capturing errors/warnings       */
34 /*            (EnvSetParserErrorCallback).                   */
35 /*                                                           */
36 /*            Fixed issue with save function when multiple   */
37 /*            defmodules exist.                              */
38 /*                                                           */
39 /*            Added const qualifiers to remove C++           */
40 /*            deprecation warnings.                          */
41 /*                                                           */
42 /*            Converted API macros to function calls.        */
43 /*                                                           */
44 /*            Fixed linkage issue when BLOAD_ONLY compiler   */
45 /*            flag is set to 1.                              */
46 /*                                                           */
47 /*            Added code to prevent a clear command from     */
48 /*            being executed during fact assertions via      */
49 /*            Increment/DecrementClearReadyLocks API.        */
50 /*                                                           */
51 /*            Added code to keep track of pointers to        */
52 /*            constructs that are contained externally to    */
53 /*            to constructs, DanglingConstructs.             */
54 /*                                                           */
55 /*************************************************************/
56 
57 #define _CONSTRCT_SOURCE_
58 
59 #include <stdio.h>
60 #define _STDIO_INCLUDED_
61 #include <string.h>
62 
63 #include "setup.h"
64 
65 #include "constant.h"
66 #include "envrnmnt.h"
67 #include "memalloc.h"
68 #include "router.h"
69 #include "scanner.h"
70 #include "watch.h"
71 #include "prcdrfun.h"
72 #include "prcdrpsr.h"
73 #include "argacces.h"
74 #include "exprnpsr.h"
75 #include "multifld.h"
76 #include "moduldef.h"
77 #include "modulutl.h"
78 #include "sysdep.h"
79 #include "utility.h"
80 #include "commline.h"
81 #include "cstrcpsr.h"
82 
83 #include "ruledef.h" /* TBD Remove */
84 #include "constrct.h"
85 
86 /***************************************/
87 /* LOCAL INTERNAL FUNCTION DEFINITIONS */
88 /***************************************/
89 
90    static void                        DeallocateConstructData(void *);
91 
92 /**************************************************/
93 /* InitializeConstructData: Allocates environment */
94 /*    data for constructs.                        */
95 /**************************************************/
InitializeConstructData(void * theEnv)96 globle void InitializeConstructData(
97   void *theEnv)
98   {
99    AllocateEnvironmentData(theEnv,CONSTRUCT_DATA,sizeof(struct constructData),DeallocateConstructData);
100 
101 #if (! RUN_TIME) && (! BLOAD_ONLY)
102    ConstructData(theEnv)->WatchCompilations = ON;
103 #endif
104   }
105 
106 /****************************************************/
107 /* DeallocateConstructData: Deallocates environment */
108 /*    data for constructs.                          */
109 /****************************************************/
DeallocateConstructData(void * theEnv)110 static void DeallocateConstructData(
111   void *theEnv)
112   {
113    struct construct *tmpPtr, *nextPtr;
114 
115 #if (! RUN_TIME) && (! BLOAD_ONLY)
116    DeallocateCallList(theEnv,ConstructData(theEnv)->ListOfSaveFunctions);
117 #endif
118    DeallocateCallList(theEnv,ConstructData(theEnv)->ListOfResetFunctions);
119    DeallocateCallList(theEnv,ConstructData(theEnv)->ListOfClearFunctions);
120    DeallocateCallList(theEnv,ConstructData(theEnv)->ListOfClearReadyFunctions);
121 
122 #if (! RUN_TIME) && (! BLOAD_ONLY)
123    if (ConstructData(theEnv)->ErrorString != NULL)
124      { genfree(theEnv,ConstructData(theEnv)->ErrorString,sizeof(ConstructData(theEnv)->ErrorString) + 1); }
125 
126    if (ConstructData(theEnv)->WarningString != NULL)
127      { genfree(theEnv,ConstructData(theEnv)->WarningString,sizeof(ConstructData(theEnv)->WarningString) + 1); }
128 
129    ConstructData(theEnv)->ErrorString = NULL;
130    ConstructData(theEnv)->WarningString = NULL;
131 
132    EnvSetParsingFileName(theEnv,NULL);
133    EnvSetWarningFileName(theEnv,NULL);
134    EnvSetErrorFileName(theEnv,NULL);
135 #endif
136 
137    tmpPtr = ConstructData(theEnv)->ListOfConstructs;
138    while (tmpPtr != NULL)
139      {
140       nextPtr = tmpPtr->next;
141       rtn_struct(theEnv,construct,tmpPtr);
142       tmpPtr = nextPtr;
143      }
144   }
145 
146 #if (! RUN_TIME) && (! BLOAD_ONLY)
147 
148 /**************************************************/
149 /* EnvSetParserErrorCallback: Allows the function */
150 /*   which is called when a construct parsing     */
151 /*    error occurs to be changed.                 */
152 /**************************************************/
EnvSetParserErrorCallback(void * theEnv,void (* functionPtr)(void *,const char *,const char *,const char *,long))153 globle void (*EnvSetParserErrorCallback(void *theEnv,
154                                         void (*functionPtr)(void *,const char *,const char *,const char *,long)))
155             (void *,const char *,const char *,const char*,long)
156   {
157    void (*tmpPtr)(void *,const char *,const char *,const char *,long);
158 
159    tmpPtr = ConstructData(theEnv)->ParserErrorCallback;
160    ConstructData(theEnv)->ParserErrorCallback = functionPtr;
161    return(tmpPtr);
162   }
163 
164 /*************************************************/
165 /* FindConstruct: Determines whether a construct */
166 /*   type is in the ListOfConstructs.            */
167 /*************************************************/
FindConstruct(void * theEnv,const char * name)168 globle struct construct *FindConstruct(
169   void *theEnv,
170   const char *name)
171   {
172    struct construct *currentPtr;
173 
174    for (currentPtr = ConstructData(theEnv)->ListOfConstructs;
175         currentPtr != NULL;
176         currentPtr = currentPtr->next)
177      {
178       if (strcmp(name,currentPtr->constructName) == 0)
179         { return(currentPtr); }
180      }
181 
182    return(NULL);
183   }
184 
185 /***********************************************************/
186 /* RemoveConstruct: Removes a construct and its associated */
187 /*   parsing function from the ListOfConstructs. Returns   */
188 /*   TRUE if the construct type was removed, otherwise     */
189 /*   FALSE.                                                */
190 /***********************************************************/
RemoveConstruct(void * theEnv,const char * name)191 globle int RemoveConstruct(
192   void *theEnv,
193   const char *name)
194   {
195    struct construct *currentPtr, *lastPtr = NULL;
196 
197    for (currentPtr = ConstructData(theEnv)->ListOfConstructs;
198         currentPtr != NULL;
199         currentPtr = currentPtr->next)
200      {
201       if (strcmp(name,currentPtr->constructName) == 0)
202         {
203          if (lastPtr == NULL)
204            { ConstructData(theEnv)->ListOfConstructs = currentPtr->next; }
205          else
206            { lastPtr->next = currentPtr->next; }
207          rtn_struct(theEnv,construct,currentPtr);
208          return(TRUE);
209         }
210 
211       lastPtr = currentPtr;
212      }
213 
214    return(FALSE);
215   }
216 
217 /************************************************/
218 /* Save: C access routine for the save command. */
219 /************************************************/
EnvSave(void * theEnv,const char * fileName)220 globle int EnvSave(
221   void *theEnv,
222   const char *fileName)
223   {
224    struct callFunctionItem *saveFunction;
225    FILE *filePtr;
226    struct defmodule *defmodulePtr;
227    intBool updated = FALSE;
228    intBool unvisited = TRUE;
229 
230    /*=====================*/
231    /* Open the save file. */
232    /*=====================*/
233 
234    if ((filePtr = GenOpen(theEnv,fileName,"w")) == NULL)
235      { return(FALSE); }
236 
237    /*===========================*/
238    /* Bypass the router system. */
239    /*===========================*/
240 
241    SetFastSave(theEnv,filePtr);
242 
243    /*================================*/
244    /* Mark all modules as unvisited. */
245    /*================================*/
246 
247    MarkModulesAsUnvisited(theEnv);
248 
249    /*===============================================*/
250    /* Save the constructs. Repeatedly loop over the */
251    /* modules until each module has been save.      */
252    /*===============================================*/
253 
254    while (unvisited)
255      {
256       unvisited = FALSE;
257       updated = FALSE;
258 
259       for (defmodulePtr = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
260            defmodulePtr != NULL;
261            defmodulePtr = (struct defmodule *) EnvGetNextDefmodule(theEnv,defmodulePtr))
262         {
263          /*=================================================================*/
264          /* We only want to save a module if all of the modules it imports  */
265          /* from have already been saved. Since there can't be circular     */
266          /* dependencies in imported modules, this should save the modules  */
267          /* that don't import anything first and then work back from those. */
268          /*=================================================================*/
269 
270          if (defmodulePtr->visitedFlag)
271            { /* Module has already been saved. */ }
272          else if (AllImportedModulesVisited(theEnv,defmodulePtr))
273            {
274             for (saveFunction = ConstructData(theEnv)->ListOfSaveFunctions;
275                  saveFunction != NULL;
276                  saveFunction = saveFunction->next)
277               {
278                ((* (void (*)(void *,void *,char *)) saveFunction->func))(theEnv,defmodulePtr,(char *) filePtr);
279               }
280 
281             updated = TRUE;
282             defmodulePtr->visitedFlag = TRUE;
283            }
284          else
285            { unvisited = TRUE; }
286         }
287 
288       /*=====================================================================*/
289       /* At least one module should be saved in every pass. If all have been */
290       /* visited/saved, then both flags will be FALSE. If all remaining      */
291       /* unvisited/unsaved modules were visited/saved, then unvisited will   */
292       /* be FALSE and updated will be TRUE. If some, but not all, remaining  */
293       /* unvisited/unsaved modules are visited/saved, then  unvisited will   */
294       /* be TRUE and updated will be TRUE. This leaves the case where there  */
295       /* are remaining unvisited/unsaved modules, but none were              */
296       /* visited/saved: unvisited is TRUE and updated is FALSE.              */
297       /*=====================================================================*/
298 
299       if (unvisited && (! updated))
300         {
301          SystemError(theEnv,"CONSTRCT",2);
302          break;
303         }
304      }
305 
306    /*======================*/
307    /* Close the save file. */
308    /*======================*/
309 
310    GenClose(theEnv,filePtr);
311 
312    /*===========================*/
313    /* Remove the router bypass. */
314    /*===========================*/
315 
316    SetFastSave(theEnv,NULL);
317 
318    /*=========================*/
319    /* Return TRUE to indicate */
320    /* successful completion.  */
321    /*=========================*/
322 
323    return(TRUE);
324   }
325 
326 /*******************************************************/
327 /* RemoveSaveFunction: Removes a function from the     */
328 /*   ListOfSaveFunctions. Returns TRUE if the function */
329 /*   was successfully removed, otherwise FALSE.        */
330 /*******************************************************/
RemoveSaveFunction(void * theEnv,const char * name)331 globle intBool RemoveSaveFunction(
332   void *theEnv,
333   const char *name)
334   {
335    int found;
336 
337    ConstructData(theEnv)->ListOfSaveFunctions =
338      RemoveFunctionFromCallList(theEnv,name,ConstructData(theEnv)->ListOfSaveFunctions,&found);
339 
340    if (found) return(TRUE);
341 
342    return(FALSE);
343   }
344 
345 /**********************************/
346 /* SetCompilationsWatch: Sets the */
347 /*   value of WatchCompilations.  */
348 /**********************************/
SetCompilationsWatch(void * theEnv,unsigned value)349 globle void SetCompilationsWatch(
350   void *theEnv,
351   unsigned value)
352   {
353    ConstructData(theEnv)->WatchCompilations = value;
354   }
355 
356 /*************************************/
357 /* GetCompilationsWatch: Returns the */
358 /*   value of WatchCompilations.     */
359 /*************************************/
GetCompilationsWatch(void * theEnv)360 globle unsigned GetCompilationsWatch(
361   void *theEnv)
362   {
363    return(ConstructData(theEnv)->WatchCompilations);
364   }
365 
366 /**********************************/
367 /* SetPrintWhileLoading: Sets the */
368 /*   value of PrintWhileLoading.  */
369 /**********************************/
SetPrintWhileLoading(void * theEnv,intBool value)370 globle void SetPrintWhileLoading(
371   void *theEnv,
372   intBool value)
373   {
374    ConstructData(theEnv)->PrintWhileLoading = value;
375   }
376 
377 /*************************************/
378 /* GetPrintWhileLoading: Returns the */
379 /*   value of PrintWhileLoading.     */
380 /*************************************/
GetPrintWhileLoading(void * theEnv)381 globle intBool GetPrintWhileLoading(
382   void *theEnv)
383   {
384    return(ConstructData(theEnv)->PrintWhileLoading);
385   }
386 #endif
387 
388 /*************************************/
389 /* InitializeConstructs: Initializes */
390 /*   the Construct Manager.          */
391 /*************************************/
InitializeConstructs(void * theEnv)392 globle void InitializeConstructs(
393   void *theEnv)
394   {
395 #if (! RUN_TIME)
396    EnvDefineFunction2(theEnv,"clear",   'v', PTIEF ClearCommand,   "ClearCommand", "00");
397    EnvDefineFunction2(theEnv,"reset",   'v', PTIEF ResetCommand,   "ResetCommand", "00");
398 
399 #if DEBUGGING_FUNCTIONS && (! BLOAD_ONLY)
400    AddWatchItem(theEnv,"compilations",0,&ConstructData(theEnv)->WatchCompilations,30,NULL,NULL);
401 #endif
402 #else
403 #if MAC_XCD
404 #pragma unused(theEnv)
405 #endif
406 #endif
407   }
408 
409 /**************************************/
410 /* ClearCommand: H/L access routine   */
411 /*   for the clear command.           */
412 /**************************************/
ClearCommand(void * theEnv)413 globle void ClearCommand(
414   void *theEnv)
415   {
416    if (EnvArgCountCheck(theEnv,"clear",EXACTLY,0) == -1) return;
417    EnvClear(theEnv);
418    return;
419   }
420 
421 /**************************************/
422 /* ResetCommand: H/L access routine   */
423 /*   for the reset command.           */
424 /**************************************/
ResetCommand(void * theEnv)425 globle void ResetCommand(
426   void *theEnv)
427   {
428    if (EnvArgCountCheck(theEnv,"reset",EXACTLY,0) == -1) return;
429    EnvReset(theEnv);
430    return;
431   }
432 
433 /******************************/
434 /* EnvReset: C access routine */
435 /*   for the reset command.   */
436 /******************************/
EnvReset(void * theEnv)437 globle void EnvReset(
438   void *theEnv)
439   {
440    struct callFunctionItem *resetPtr;
441 
442    /*=====================================*/
443    /* The reset command can't be executed */
444    /* while a reset is in progress.       */
445    /*=====================================*/
446 
447    if (ConstructData(theEnv)->ResetInProgress) return;
448 
449    ConstructData(theEnv)->ResetInProgress = TRUE;
450    ConstructData(theEnv)->ResetReadyInProgress = TRUE;
451 
452    /*================================================*/
453    /* If the reset is performed from the top level   */
454    /* command prompt, reset the halt execution flag. */
455    /*================================================*/
456 
457    if (UtilityData(theEnv)->CurrentGarbageFrame->topLevel) SetHaltExecution(theEnv,FALSE);
458 
459    /*=======================================================*/
460    /* Call the before reset function to determine if the    */
461    /* reset should continue. [Used by the some of the       */
462    /* windowed interfaces to query the user whether a       */
463    /* reset should proceed with activations on the agenda.] */
464    /*=======================================================*/
465 
466    if ((ConstructData(theEnv)->BeforeResetFunction != NULL) ?
467        ((*ConstructData(theEnv)->BeforeResetFunction)(theEnv) == FALSE) :
468                                        FALSE)
469      {
470       ConstructData(theEnv)->ResetReadyInProgress = FALSE;
471       ConstructData(theEnv)->ResetInProgress = FALSE;
472       return;
473      }
474    ConstructData(theEnv)->ResetReadyInProgress = FALSE;
475 
476    /*===========================*/
477    /* Call each reset function. */
478    /*===========================*/
479 
480    for (resetPtr = ConstructData(theEnv)->ListOfResetFunctions;
481         (resetPtr != NULL) && (GetHaltExecution(theEnv) == FALSE);
482         resetPtr = resetPtr->next)
483      {
484       if (resetPtr->environmentAware)
485         { (*resetPtr->func)(theEnv); }
486       else
487         { (* (void (*)(void)) resetPtr->func)(); }
488      }
489 
490    /*============================================*/
491    /* Set the current module to the MAIN module. */
492    /*============================================*/
493 
494    EnvSetCurrentModule(theEnv,(void *) EnvFindDefmodule(theEnv,"MAIN"));
495 
496    /*===========================================*/
497    /* Perform periodic cleanup if the reset was */
498    /* issued from an embedded controller.       */
499    /*===========================================*/
500 
501    if ((UtilityData(theEnv)->CurrentGarbageFrame->topLevel) && (! CommandLineData(theEnv)->EvaluatingTopLevelCommand) &&
502        (EvaluationData(theEnv)->CurrentExpression == NULL) && (UtilityData(theEnv)->GarbageCollectionLocks == 0))
503      {
504       CleanCurrentGarbageFrame(theEnv,NULL);
505       CallPeriodicTasks(theEnv);
506      }
507 
508    /*===================================*/
509    /* A reset is no longer in progress. */
510    /*===================================*/
511 
512    ConstructData(theEnv)->ResetInProgress = FALSE;
513   }
514 
515 /************************************/
516 /* SetBeforeResetFunction: Sets the */
517 /*  value of BeforeResetFunction.   */
518 /************************************/
SetBeforeResetFunction(void * theEnv,int (* theFunction)(void *))519 globle int (*SetBeforeResetFunction(void *theEnv,
520                                     int (*theFunction)(void *)))(void *)
521   {
522    int (*tempFunction)(void *);
523 
524    tempFunction = ConstructData(theEnv)->BeforeResetFunction;
525    ConstructData(theEnv)->BeforeResetFunction = theFunction;
526    return(tempFunction);
527   }
528 
529 /****************************************/
530 /* EnvAddResetFunction: Adds a function */
531 /*   to ListOfResetFunctions.           */
532 /****************************************/
EnvAddResetFunction(void * theEnv,const char * name,void (* functionPtr)(void *),int priority)533 globle intBool EnvAddResetFunction(
534   void *theEnv,
535   const char *name,
536   void (*functionPtr)(void *),
537   int priority)
538   {
539    ConstructData(theEnv)->ListOfResetFunctions = AddFunctionToCallList(theEnv,name,priority,
540                                                 functionPtr,
541                                                 ConstructData(theEnv)->ListOfResetFunctions,TRUE);
542    return(TRUE);
543   }
544 
545 /**********************************************/
546 /* EnvRemoveResetFunction: Removes a function */
547 /*   from the ListOfResetFunctions.           */
548 /**********************************************/
EnvRemoveResetFunction(void * theEnv,const char * name)549 globle intBool EnvRemoveResetFunction(
550   void *theEnv,
551   const char *name)
552   {
553    int found;
554 
555    ConstructData(theEnv)->ListOfResetFunctions =
556       RemoveFunctionFromCallList(theEnv,name,ConstructData(theEnv)->ListOfResetFunctions,&found);
557 
558    if (found) return(TRUE);
559 
560    return(FALSE);
561   }
562 
563 /*******************************************/
564 /* EnvIncrementClearReadyLocks: Increments */
565 /*   the number of clear ready locks.      */
566 /*******************************************/
EnvIncrementClearReadyLocks(void * theEnv)567 globle void EnvIncrementClearReadyLocks(
568   void *theEnv)
569   {
570    ConstructData(theEnv)->ClearReadyLocks++;
571   }
572 
573 /*******************************************/
574 /* EnvDecrementClearReadyLocks: Decrements */
575 /*   the number of clear locks.            */
576 /*******************************************/
EnvDecrementClearReadyLocks(void * theEnv)577 globle void EnvDecrementClearReadyLocks(
578   void *theEnv)
579   {
580    if (ConstructData(theEnv)->ClearReadyLocks > 0)
581      { ConstructData(theEnv)->ClearReadyLocks--; }
582   }
583 
584 /*****************************************************/
585 /* EnvClear: C access routine for the clear command. */
586 /*****************************************************/
EnvClear(void * theEnv)587 globle void EnvClear(
588   void *theEnv)
589   {
590    struct callFunctionItem *theFunction;
591 
592    /*==========================================*/
593    /* Activate the watch router which captures */
594    /* trace output so that it is not displayed */
595    /* during a clear.                          */
596    /*==========================================*/
597 
598 #if DEBUGGING_FUNCTIONS
599    EnvActivateRouter(theEnv,WTRACE);
600 #endif
601 
602    /*===================================*/
603    /* Determine if a clear is possible. */
604    /*===================================*/
605 
606    ConstructData(theEnv)->ClearReadyInProgress = TRUE;
607    if ((ConstructData(theEnv)->ClearReadyLocks > 0) ||
608        (ConstructData(theEnv)->DanglingConstructs > 0) ||
609        (ClearReady(theEnv) == FALSE))
610      {
611       PrintErrorID(theEnv,"CONSTRCT",1,FALSE);
612       EnvPrintRouter(theEnv,WERROR,"Some constructs are still in use. Clear cannot continue.\n");
613 #if DEBUGGING_FUNCTIONS
614       EnvDeactivateRouter(theEnv,WTRACE);
615 #endif
616       ConstructData(theEnv)->ClearReadyInProgress = FALSE;
617       return;
618      }
619    ConstructData(theEnv)->ClearReadyInProgress = FALSE;
620 
621    /*===========================*/
622    /* Call all clear functions. */
623    /*===========================*/
624 
625    ConstructData(theEnv)->ClearInProgress = TRUE;
626 
627    for (theFunction = ConstructData(theEnv)->ListOfClearFunctions;
628         theFunction != NULL;
629         theFunction = theFunction->next)
630      {
631       if (theFunction->environmentAware)
632         { (*theFunction->func)(theEnv); }
633       else
634         { (* (void (*)(void)) theFunction->func)(); }
635      }
636 
637    /*=============================*/
638    /* Deactivate the watch router */
639    /* for capturing output.       */
640    /*=============================*/
641 
642 #if DEBUGGING_FUNCTIONS
643    EnvDeactivateRouter(theEnv,WTRACE);
644 #endif
645 
646    /*===========================================*/
647    /* Perform periodic cleanup if the clear was */
648    /* issued from an embedded controller.       */
649    /*===========================================*/
650 
651    if ((UtilityData(theEnv)->CurrentGarbageFrame->topLevel) && (! CommandLineData(theEnv)->EvaluatingTopLevelCommand) &&
652        (EvaluationData(theEnv)->CurrentExpression == NULL) && (UtilityData(theEnv)->GarbageCollectionLocks == 0))
653      {
654       CleanCurrentGarbageFrame(theEnv,NULL);
655       CallPeriodicTasks(theEnv);
656      }
657 
658    /*===========================*/
659    /* Clear has been completed. */
660    /*===========================*/
661 
662    ConstructData(theEnv)->ClearInProgress = FALSE;
663 
664 #if DEFRULE_CONSTRUCT
665    if ((DefruleData(theEnv)->RightPrimeJoins != NULL) ||
666        (DefruleData(theEnv)->LeftPrimeJoins != NULL))
667      { SystemError(theEnv,"CONSTRCT",1); }
668 #endif
669 
670    /*============================*/
671    /* Perform reset after clear. */
672    /*============================*/
673 
674    EnvReset(theEnv);
675   }
676 
677 /*********************************************************/
678 /* ClearReady: Returns TRUE if a clear can be performed, */
679 /*   otherwise FALSE. Note that this is destructively    */
680 /*   determined (e.g. facts will be deleted as part of   */
681 /*   the determination).                                 */
682 /*********************************************************/
ClearReady(void * theEnv)683 globle intBool ClearReady(
684   void *theEnv)
685   {
686    struct callFunctionItem *theFunction;
687    int (*tempFunction)(void *);
688 
689    for (theFunction = ConstructData(theEnv)->ListOfClearReadyFunctions;
690         theFunction != NULL;
691         theFunction = theFunction->next)
692      {
693       tempFunction = (int (*)(void *)) theFunction->func;
694       if ((*tempFunction)(theEnv) == FALSE)
695         { return(FALSE); }
696      }
697 
698    return(TRUE);
699   }
700 
701 /******************************************/
702 /* AddClearReadyFunction: Adds a function */
703 /*   to ListOfClearReadyFunctions.        */
704 /******************************************/
AddClearReadyFunction(void * theEnv,const char * name,int (* functionPtr)(void *),int priority)705 globle intBool AddClearReadyFunction(
706   void *theEnv,
707   const char *name,
708   int (*functionPtr)(void *),
709   int priority)
710   {
711    ConstructData(theEnv)->ListOfClearReadyFunctions =
712      AddFunctionToCallList(theEnv,name,priority,
713                            (void (*)(void *)) functionPtr,
714                            ConstructData(theEnv)->ListOfClearReadyFunctions,TRUE);
715    return(1);
716   }
717 
718 /************************************************/
719 /* RemoveClearReadyFunction: Removes a function */
720 /*   from the ListOfClearReadyFunctions.        */
721 /************************************************/
RemoveClearReadyFunction(void * theEnv,const char * name)722 globle intBool RemoveClearReadyFunction(
723   void *theEnv,
724   const char *name)
725   {
726    int found;
727 
728    ConstructData(theEnv)->ListOfClearReadyFunctions =
729       RemoveFunctionFromCallList(theEnv,name,ConstructData(theEnv)->ListOfClearReadyFunctions,&found);
730 
731    if (found) return(TRUE);
732 
733    return(FALSE);
734   }
735 
736 /****************************************/
737 /* EnvAddClearFunction: Adds a function */
738 /*   to ListOfClearFunctions.           */
739 /****************************************/
EnvAddClearFunction(void * theEnv,const char * name,void (* functionPtr)(void *),int priority)740 globle intBool EnvAddClearFunction(
741   void *theEnv,
742   const char *name,
743   void (*functionPtr)(void *),
744   int priority)
745   {
746    ConstructData(theEnv)->ListOfClearFunctions =
747       AddFunctionToCallList(theEnv,name,priority,
748                             (void (*)(void *)) functionPtr,
749                             ConstructData(theEnv)->ListOfClearFunctions,TRUE);
750    return(1);
751   }
752 
753 /**********************************************/
754 /* EnvRemoveClearFunction: Removes a function */
755 /*    from the ListOfClearFunctions.          */
756 /**********************************************/
EnvRemoveClearFunction(void * theEnv,const char * name)757 globle intBool EnvRemoveClearFunction(
758   void *theEnv,
759   const char *name)
760   {
761    int found;
762 
763    ConstructData(theEnv)->ListOfClearFunctions =
764      RemoveFunctionFromCallList(theEnv,name,ConstructData(theEnv)->ListOfClearFunctions,&found);
765 
766    if (found) return(TRUE);
767 
768    return(FALSE);
769   }
770 
771 /***********************************************/
772 /* ExecutingConstruct: Returns TRUE if a */
773 /*   construct is currently being executed,    */
774 /*   otherwise FALSE.                    */
775 /***********************************************/
ExecutingConstruct(void * theEnv)776 globle int ExecutingConstruct(
777   void *theEnv)
778   {
779    return(ConstructData(theEnv)->Executing);
780   }
781 
782 /********************************************/
783 /* SetExecutingConstruct: Sets the value of */
784 /*   the executing variable indicating that */
785 /*   actions such as reset, clear, etc      */
786 /*   should not be performed.               */
787 /********************************************/
SetExecutingConstruct(void * theEnv,int value)788 globle void SetExecutingConstruct(
789   void *theEnv,
790   int value)
791   {
792    ConstructData(theEnv)->Executing = value;
793   }
794 
795 /*******************************************************/
796 /* DeinstallConstructHeader: Decrements the busy count */
797 /*   of a construct name and frees its pretty print    */
798 /*   representation string (both of which are stored   */
799 /*   in the generic construct header).                 */
800 /*******************************************************/
DeinstallConstructHeader(void * theEnv,struct constructHeader * theHeader)801 globle void DeinstallConstructHeader(
802   void *theEnv,
803   struct constructHeader *theHeader)
804   {
805    DecrementSymbolCount(theEnv,theHeader->name);
806    if (theHeader->ppForm != NULL)
807      {
808       rm(theEnv,(void *) theHeader->ppForm,
809          sizeof(char) * (strlen(theHeader->ppForm) + 1));
810       theHeader->ppForm = NULL;
811      }
812 
813    if (theHeader->usrData != NULL)
814      {
815       ClearUserDataList(theEnv,theHeader->usrData);
816       theHeader->usrData = NULL;
817      }
818   }
819 
820 /**************************************************/
821 /* DestroyConstructHeader: Frees the pretty print */
822 /*   representation string and user data (both of */
823 /*   which are stored in the generic construct    */
824 /*   header).                                     */
825 /**************************************************/
DestroyConstructHeader(void * theEnv,struct constructHeader * theHeader)826 globle void DestroyConstructHeader(
827   void *theEnv,
828   struct constructHeader *theHeader)
829   {
830    if (theHeader->ppForm != NULL)
831      {
832       rm(theEnv,(void *) theHeader->ppForm,
833          sizeof(char) * (strlen(theHeader->ppForm) + 1));
834       theHeader->ppForm = NULL;
835      }
836 
837    if (theHeader->usrData != NULL)
838      {
839       ClearUserDataList(theEnv,theHeader->usrData);
840       theHeader->usrData = NULL;
841      }
842   }
843 
844 /*****************************************************/
845 /* AddConstruct: Adds a construct and its associated */
846 /*   parsing function to the ListOfConstructs.       */
847 /*****************************************************/
AddConstruct(void * theEnv,const char * name,const char * pluralName,int (* parseFunction)(void *,const char *),void * (* findFunction)(void *,const char *),SYMBOL_HN * (* getConstructNameFunction)(struct constructHeader *),const char * (* getPPFormFunction)(void *,struct constructHeader *),struct defmoduleItemHeader * (* getModuleItemFunction)(struct constructHeader *),void * (* getNextItemFunction)(void *,void *),void (* setNextItemFunction)(struct constructHeader *,struct constructHeader *),intBool (* isConstructDeletableFunction)(void *,void *),int (* deleteFunction)(void *,void *),void (* freeFunction)(void *,void *))848 globle struct construct *AddConstruct(
849   void *theEnv,
850   const char *name,
851   const char *pluralName,
852   int (*parseFunction)(void *,const char *),
853   void *(*findFunction)(void *,const char *),
854   SYMBOL_HN *(*getConstructNameFunction)(struct constructHeader *),
855   const char *(*getPPFormFunction)(void *,struct constructHeader *),
856   struct defmoduleItemHeader *(*getModuleItemFunction)(struct constructHeader *),
857   void *(*getNextItemFunction)(void *,void *),
858   void (*setNextItemFunction)(struct constructHeader *,struct constructHeader *),
859   intBool (*isConstructDeletableFunction)(void *,void *),
860   int (*deleteFunction)(void *,void *),
861   void (*freeFunction)(void *,void *))
862   {
863    struct construct *newPtr;
864 
865    /*=============================*/
866    /* Allocate and initialize the */
867    /* construct data structure.   */
868    /*=============================*/
869 
870    newPtr = get_struct(theEnv,construct);
871 
872    newPtr->constructName = name;
873    newPtr->pluralName = pluralName;
874    newPtr->parseFunction = parseFunction;
875    newPtr->findFunction = findFunction;
876    newPtr->getConstructNameFunction = getConstructNameFunction;
877    newPtr->getPPFormFunction = getPPFormFunction;
878    newPtr->getModuleItemFunction = getModuleItemFunction;
879    newPtr->getNextItemFunction = getNextItemFunction;
880    newPtr->setNextItemFunction = setNextItemFunction;
881    newPtr->isConstructDeletableFunction = isConstructDeletableFunction;
882    newPtr->deleteFunction = deleteFunction;
883    newPtr->freeFunction = freeFunction;
884 
885    /*===============================*/
886    /* Add the construct to the list */
887    /* of constructs and return it.  */
888    /*===============================*/
889 
890    newPtr->next = ConstructData(theEnv)->ListOfConstructs;
891    ConstructData(theEnv)->ListOfConstructs = newPtr;
892    return(newPtr);
893   }
894 
895 /************************************/
896 /* AddSaveFunction: Adds a function */
897 /*   to the ListOfSaveFunctions.    */
898 /************************************/
AddSaveFunction(void * theEnv,const char * name,void (* functionPtr)(void *,void *,const char *),int priority)899 globle intBool AddSaveFunction(
900   void *theEnv,
901   const char *name,
902   void (*functionPtr)(void *,void *,const char *),
903   int priority)
904   {
905 #if (! RUN_TIME) && (! BLOAD_ONLY)
906    ConstructData(theEnv)->ListOfSaveFunctions =
907      AddFunctionToCallList(theEnv,name,priority,
908                            (void (*)(void *)) functionPtr,
909                            ConstructData(theEnv)->ListOfSaveFunctions,TRUE);
910 #else
911 #if MAC_XCD
912 #pragma unused(theEnv)
913 #endif
914 #endif
915 
916    return(1);
917   }
918 
919 /*#####################################*/
920 /* ALLOW_ENVIRONMENT_GLOBALS Functions */
921 /*#####################################*/
922 
923 #if ALLOW_ENVIRONMENT_GLOBALS
924 
AddClearFunction(const char * name,void (* functionPtr)(void),int priority)925 globle intBool AddClearFunction(
926   const char *name,
927   void (*functionPtr)(void),
928   int priority)
929   {
930    void *theEnv;
931 
932    theEnv = GetCurrentEnvironment();
933 
934    ConstructData(theEnv)->ListOfClearFunctions =
935       AddFunctionToCallList(theEnv,name,priority,
936                             (void (*)(void *)) functionPtr,
937                             ConstructData(theEnv)->ListOfClearFunctions,FALSE);
938    return(1);
939   }
940 
AddResetFunction(const char * name,void (* functionPtr)(void),int priority)941 globle intBool AddResetFunction(
942   const char *name,
943   void (*functionPtr)(void),
944   int priority)
945   {
946    void *theEnv;
947 
948    theEnv = GetCurrentEnvironment();
949 
950    ConstructData(theEnv)->ListOfResetFunctions =
951       AddFunctionToCallList(theEnv,name,priority,(void (*)(void *)) functionPtr,
952                             ConstructData(theEnv)->ListOfResetFunctions,FALSE);
953    return(TRUE);
954   }
955 
Clear()956 globle void Clear()
957   {
958    EnvClear(GetCurrentEnvironment());
959   }
960 
RemoveClearFunction(const char * name)961 globle intBool RemoveClearFunction(
962   const char *name)
963   {
964    return EnvRemoveClearFunction(GetCurrentEnvironment(),name);
965   }
966 
RemoveResetFunction(const char * name)967 globle intBool RemoveResetFunction(
968   const char *name)
969   {
970    return EnvRemoveResetFunction(GetCurrentEnvironment(),name);
971   }
972 
Reset()973 globle void Reset()
974   {
975    EnvReset(GetCurrentEnvironment());
976   }
977 
978 #if (! RUN_TIME) && (! BLOAD_ONLY)
979 
Save(const char * fileName)980 globle int Save(
981   const char *fileName)
982   {
983    return EnvSave(GetCurrentEnvironment(),fileName);
984   }
985 #endif
986 
987 #endif
988 
989 
990