1    /*******************************************************/
2    /*      "C" Language Integrated Production System      */
3    /*                                                     */
4    /*             CLIPS Version 6.30  08/16/14            */
5    /*                                                     */
6    /*                FACT BSAVE/BLOAD MODULE              */
7    /*******************************************************/
8 
9 /*************************************************************/
10 /* Purpose: Implements the binary save/load feature for the  */
11 /*    fact pattern network.                                  */
12 /*                                                           */
13 /* Principal Programmer(s):                                  */
14 /*      Gary D. Riley                                        */
15 /*                                                           */
16 /* Contributing Programmer(s):                               */
17 /*      Brian L. Dantes                                      */
18 /*                                                           */
19 /* Revision History:                                         */
20 /*                                                           */
21 /*      6.30: Added support for hashed alpha memories.       */
22 /*                                                           */
23 /*            Changed integer type/precision.                */
24 /*                                                           */
25 /*************************************************************/
26 
27 #define _FACTBIN_SOURCE_
28 
29 #include "setup.h"
30 
31 #if DEFTEMPLATE_CONSTRUCT && (BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE) && (! RUN_TIME)
32 
33 #include <stdio.h>
34 #define _STDIO_INCLUDED_
35 
36 #include "memalloc.h"
37 #include "tmpltdef.h"
38 #include "bload.h"
39 #include "bsave.h"
40 #include "reteutil.h"
41 #include "rulebin.h"
42 #include "moduldef.h"
43 #include "envrnmnt.h"
44 
45 #include "factbin.h"
46 
47 /********************************************/
48 /* INTERNAL DATA STRUCTURES AND DEFINITIONS */
49 /********************************************/
50 
51 struct bsaveFactPatternNode
52   {
53    struct bsavePatternNodeHeader header;
54    unsigned short whichSlot;
55    unsigned short whichField;
56    unsigned short leaveFields;
57    long networkTest;
58    long nextLevel;
59    long lastLevel;
60    long leftNode;
61    long rightNode;
62   };
63 
64 #define BSAVE_FIND         0
65 #define BSAVE_PATTERNS     1
66 
67 /***************************************/
68 /* LOCAL INTERNAL FUNCTION DEFINITIONS */
69 /***************************************/
70 
71 #if BLOAD_AND_BSAVE
72    static void                    BsaveDriver(void *,int,FILE *,struct factPatternNode *);
73    static void                    BsaveFind(void *);
74    static void                    BsaveStorage(void *,FILE *);
75    static void                    BsaveFactPatterns(void *,FILE *);
76    static void                    BsavePatternNode(void *,struct factPatternNode *,FILE *);
77 #endif
78    static void                    BloadStorage(void *);
79    static void                    BloadBinaryItem(void *);
80    static void                    UpdateFactPatterns(void *,void *,long);
81    static void                    ClearBload(void *);
82    static void                    DeallocateFactBloadData(void *);
83 
84 /*****************************************************/
85 /* FactBinarySetup: Initializes the binary load/save */
86 /*   feature for the fact pattern network.           */
87 /*****************************************************/
FactBinarySetup(void * theEnv)88 globle void FactBinarySetup(
89   void *theEnv)
90   {
91    AllocateEnvironmentData(theEnv,FACTBIN_DATA,sizeof(struct factBinaryData),DeallocateFactBloadData);
92 
93 #if BLOAD_AND_BSAVE
94    AddBinaryItem(theEnv,"facts",0,BsaveFind,NULL,
95                             BsaveStorage,BsaveFactPatterns,
96                             BloadStorage,BloadBinaryItem,
97                             ClearBload);
98 #endif
99 #if BLOAD || BLOAD_ONLY
100    AddBinaryItem(theEnv,"facts",0,NULL,NULL,NULL,NULL,
101                             BloadStorage,BloadBinaryItem,
102                             ClearBload);
103 #endif
104   }
105 
106 /****************************************************/
107 /* DeallocateFactBloadData: Deallocates environment */
108 /*    data for the fact bsave functionality.        */
109 /****************************************************/
DeallocateFactBloadData(void * theEnv)110 static void DeallocateFactBloadData(
111   void *theEnv)
112   {
113    size_t space;
114    int i;
115 
116    for (i = 0; i < FactBinaryData(theEnv)->NumberOfPatterns; i++)
117      { DestroyAlphaMemory(theEnv,&FactBinaryData(theEnv)->FactPatternArray[i].header,FALSE); }
118 
119    space = FactBinaryData(theEnv)->NumberOfPatterns * sizeof(struct factPatternNode);
120    if (space != 0) genfree(theEnv,(void *) FactBinaryData(theEnv)->FactPatternArray,space);
121   }
122 
123 #if BLOAD_AND_BSAVE
124 
125 /*********************************************************/
126 /* BsaveFind: Counts the number of data structures which */
127 /*   must be saved in the binary image for the fact      */
128 /*   pattern network in the current environment.         */
129 /*********************************************************/
BsaveFind(void * theEnv)130 static void BsaveFind(
131   void *theEnv)
132   {
133    struct deftemplate *theDeftemplate;
134    struct defmodule *theModule;
135 
136    /*=======================================================*/
137    /* If a binary image is already loaded, then temporarily */
138    /* save the count values since these will be overwritten */
139    /* in the process of saving the binary image.            */
140    /*=======================================================*/
141 
142    SaveBloadCount(theEnv,FactBinaryData(theEnv)->NumberOfPatterns);
143 
144    /*=======================================*/
145    /* Set the count of fact pattern network */
146    /* data structures to zero.              */
147    /*=======================================*/
148 
149    FactBinaryData(theEnv)->NumberOfPatterns = 0L;
150 
151    /*===========================*/
152    /* Loop through each module. */
153    /*===========================*/
154 
155    for (theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
156         theModule != NULL;
157         theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,theModule))
158      {
159       /*===============================*/
160       /* Set the current module to the */
161       /* module being examined.        */
162       /*===============================*/
163 
164       EnvSetCurrentModule(theEnv,(void *) theModule);
165 
166       /*=====================================================*/
167       /* Loop through each deftemplate in the current module */
168       /* and count the number of data structures which must  */
169       /* be saved for its pattern network.                   */
170       /*=====================================================*/
171 
172       for (theDeftemplate = (struct deftemplate *) EnvGetNextDeftemplate(theEnv,NULL);
173            theDeftemplate != NULL;
174            theDeftemplate = (struct deftemplate *) EnvGetNextDeftemplate(theEnv,theDeftemplate))
175         { BsaveDriver(theEnv,BSAVE_FIND,NULL,theDeftemplate->patternNetwork); }
176      }
177   }
178 
179 /**********************************************************/
180 /* BsaveDriver: Binary save driver routine which handles  */
181 /*   both finding/marking the data structures to be saved */
182 /*   and saving the data structures to a file.            */
183 /**********************************************************/
BsaveDriver(void * theEnv,int action,FILE * fp,struct factPatternNode * thePattern)184 static void BsaveDriver(
185   void *theEnv,
186   int action,
187   FILE *fp,
188   struct factPatternNode *thePattern)
189   {
190    while (thePattern != NULL)
191      {
192       switch(action)
193         {
194          case BSAVE_FIND:
195            thePattern->bsaveID = FactBinaryData(theEnv)->NumberOfPatterns++;
196            break;
197 
198          case BSAVE_PATTERNS:
199            BsavePatternNode(theEnv,thePattern,fp);
200            break;
201 
202          default:
203            break;
204         }
205 
206       if (thePattern->nextLevel == NULL)
207         {
208          while (thePattern->rightNode == NULL)
209            {
210             thePattern = thePattern->lastLevel;
211             if (thePattern == NULL) return;
212            }
213          thePattern = thePattern->rightNode;
214         }
215       else
216         { thePattern = thePattern->nextLevel; }
217      }
218   }
219 
220 /*********************************************************/
221 /* BsaveStorage: Writes out storage requirements for all */
222 /*   factPatternNode data structures to the binary file  */
223 /*********************************************************/
BsaveStorage(void * theEnv,FILE * fp)224 static void BsaveStorage(
225   void *theEnv,
226   FILE *fp)
227   {
228    size_t space;
229 
230    space = sizeof(long);
231    GenWrite(&space,sizeof(size_t),fp);
232    GenWrite(&FactBinaryData(theEnv)->NumberOfPatterns,sizeof(long int),fp);
233   }
234 
235 /*****************************************************/
236 /* BsaveFactPatterns: Writes out all factPatternNode */
237 /*    data structures to the binary file.            */
238 /*****************************************************/
BsaveFactPatterns(void * theEnv,FILE * fp)239 static void BsaveFactPatterns(
240   void *theEnv,
241   FILE *fp)
242   {
243    size_t space;
244    struct deftemplate *theDeftemplate;
245    struct defmodule *theModule;
246 
247    /*========================================*/
248    /* Write out the amount of space taken up */
249    /* by the factPatternNode data structures */
250    /* in the binary image.                   */
251    /*========================================*/
252 
253    space = FactBinaryData(theEnv)->NumberOfPatterns * sizeof(struct bsaveFactPatternNode);
254    GenWrite(&space,sizeof(size_t),fp);
255 
256    /*===========================*/
257    /* Loop through each module. */
258    /*===========================*/
259 
260    for (theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
261         theModule != NULL;
262         theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,theModule))
263      {
264       /*=====================================================*/
265       /* Loop through each deftemplate in the current module */
266       /* and save its fact pattern network to the file.      */
267       /*=====================================================*/
268 
269       EnvSetCurrentModule(theEnv,(void *) theModule);
270       for (theDeftemplate = (struct deftemplate *) EnvGetNextDeftemplate(theEnv,NULL);
271            theDeftemplate != NULL;
272            theDeftemplate = (struct deftemplate *) EnvGetNextDeftemplate(theEnv,theDeftemplate))
273         { BsaveDriver(theEnv,BSAVE_PATTERNS,fp,theDeftemplate->patternNetwork); }
274     }
275 
276    /*=============================================================*/
277    /* If a binary image was already loaded when the bsave command */
278    /* was issued, then restore the counts indicating the number   */
279    /* of factPatternNode data structures in the binary image      */
280    /* (these were overwritten by the binary save).                */
281    /*=============================================================*/
282 
283    RestoreBloadCount(theEnv,&FactBinaryData(theEnv)->NumberOfPatterns);
284   }
285 
286 /******************************************************/
287 /* BsavePatternNode: Writes out a single fact pattern */
288 /*   node to the binary image save file.              */
289 /******************************************************/
BsavePatternNode(void * theEnv,struct factPatternNode * thePattern,FILE * fp)290 static void BsavePatternNode(
291   void *theEnv,
292   struct factPatternNode *thePattern,
293   FILE *fp)
294   {
295    struct bsaveFactPatternNode tempNode;
296 
297    AssignBsavePatternHeaderValues(theEnv,&tempNode.header,&thePattern->header);
298 
299    tempNode.whichField = thePattern->whichField;
300    tempNode.leaveFields = thePattern->leaveFields;
301    tempNode.whichSlot = thePattern->whichSlot;
302    tempNode.networkTest = HashedExpressionIndex(theEnv,thePattern->networkTest);
303    tempNode.nextLevel =  BsaveFactPatternIndex(thePattern->nextLevel);
304    tempNode.lastLevel =  BsaveFactPatternIndex(thePattern->lastLevel);
305    tempNode.leftNode =  BsaveFactPatternIndex(thePattern->leftNode);
306    tempNode.rightNode =  BsaveFactPatternIndex(thePattern->rightNode);
307 
308    GenWrite(&tempNode,(unsigned long) sizeof(struct bsaveFactPatternNode),fp);
309   }
310 
311 #endif /* BLOAD_AND_BSAVE */
312 
313 /*****************************************************/
314 /* BloadStorage: Allocates storage requirements for  */
315 /*   the factPatternNodes used by this binary image. */
316 /*****************************************************/
BloadStorage(void * theEnv)317 static void BloadStorage(
318   void *theEnv)
319   {
320    size_t space;
321 
322    /*=========================================*/
323    /* Determine the number of factPatternNode */
324    /* data structures to be read.             */
325    /*=========================================*/
326 
327    GenReadBinary(theEnv,&space,sizeof(size_t));
328    GenReadBinary(theEnv,&FactBinaryData(theEnv)->NumberOfPatterns,sizeof(long int));
329 
330    /*===================================*/
331    /* Allocate the space needed for the */
332    /* factPatternNode data structures.  */
333    /*===================================*/
334 
335    if (FactBinaryData(theEnv)->NumberOfPatterns == 0)
336      {
337       FactBinaryData(theEnv)->FactPatternArray = NULL;
338       return;
339      }
340 
341    space = FactBinaryData(theEnv)->NumberOfPatterns * sizeof(struct factPatternNode);
342    FactBinaryData(theEnv)->FactPatternArray = (struct factPatternNode *) genalloc(theEnv,space);
343   }
344 
345 /************************************************************/
346 /* BloadBinaryItem: Loads and refreshes the factPatternNode */
347 /*   data structures used by this binary image.             */
348 /************************************************************/
BloadBinaryItem(void * theEnv)349 static void BloadBinaryItem(
350   void *theEnv)
351   {
352    size_t space;
353    long i;
354 
355    /*======================================================*/
356    /* Read in the amount of space used by the binary image */
357    /* (this is used to skip the construct in the event it  */
358    /* is not available in the version being run).          */
359    /*======================================================*/
360 
361    GenReadBinary(theEnv,&space,sizeof(size_t));
362 
363    /*=============================================*/
364    /* Read in the factPatternNode data structures */
365    /* and refresh the pointers.                   */
366    /*=============================================*/
367 
368    BloadandRefresh(theEnv,FactBinaryData(theEnv)->NumberOfPatterns,(unsigned) sizeof(struct bsaveFactPatternNode),
369                    UpdateFactPatterns);
370 
371    for (i = 0; i < FactBinaryData(theEnv)->NumberOfPatterns; i++)
372      {
373       if ((FactBinaryData(theEnv)->FactPatternArray[i].lastLevel != NULL) &&
374           (FactBinaryData(theEnv)->FactPatternArray[i].lastLevel->header.selector))
375         {
376          AddHashedPatternNode(theEnv,FactBinaryData(theEnv)->FactPatternArray[i].lastLevel,
377                                      &FactBinaryData(theEnv)->FactPatternArray[i],
378                                      FactBinaryData(theEnv)->FactPatternArray[i].networkTest->type,
379                                      FactBinaryData(theEnv)->FactPatternArray[i].networkTest->value);
380         }
381      }
382   }
383 
384 /*************************************************/
385 /* UpdateFactPatterns: Bload refresh routine for */
386 /*   the factPatternNode structure.              */
387 /*************************************************/
UpdateFactPatterns(void * theEnv,void * buf,long obji)388 static void UpdateFactPatterns(
389   void *theEnv,
390   void *buf,
391   long obji)
392   {
393    struct bsaveFactPatternNode *bp;
394 
395    bp = (struct bsaveFactPatternNode *) buf;
396 
397    UpdatePatternNodeHeader(theEnv,&FactBinaryData(theEnv)->FactPatternArray[obji].header,&bp->header);
398 
399    FactBinaryData(theEnv)->FactPatternArray[obji].bsaveID = 0L;
400    FactBinaryData(theEnv)->FactPatternArray[obji].whichField = bp->whichField;
401    FactBinaryData(theEnv)->FactPatternArray[obji].leaveFields = bp->leaveFields;
402    FactBinaryData(theEnv)->FactPatternArray[obji].whichSlot = bp->whichSlot;
403 
404    FactBinaryData(theEnv)->FactPatternArray[obji].networkTest = HashedExpressionPointer(bp->networkTest);
405    FactBinaryData(theEnv)->FactPatternArray[obji].rightNode = BloadFactPatternPointer(bp->rightNode);
406    FactBinaryData(theEnv)->FactPatternArray[obji].nextLevel = BloadFactPatternPointer(bp->nextLevel);
407    FactBinaryData(theEnv)->FactPatternArray[obji].lastLevel = BloadFactPatternPointer(bp->lastLevel);
408    FactBinaryData(theEnv)->FactPatternArray[obji].leftNode  = BloadFactPatternPointer(bp->leftNode);
409   }
410 
411 /***************************************************/
412 /* ClearBload:  Fact pattern network clear routine */
413 /*   when a binary load is in effect.              */
414 /***************************************************/
ClearBload(void * theEnv)415 static void ClearBload(
416   void *theEnv)
417   {
418    size_t space;
419    long i;
420 
421    for (i = 0; i < FactBinaryData(theEnv)->NumberOfPatterns; i++)
422      {
423       if ((FactBinaryData(theEnv)->FactPatternArray[i].lastLevel != NULL) &&
424           (FactBinaryData(theEnv)->FactPatternArray[i].lastLevel->header.selector))
425         {
426          RemoveHashedPatternNode(theEnv,FactBinaryData(theEnv)->FactPatternArray[i].lastLevel,
427                                         &FactBinaryData(theEnv)->FactPatternArray[i],
428                                         FactBinaryData(theEnv)->FactPatternArray[i].networkTest->type,
429                                         FactBinaryData(theEnv)->FactPatternArray[i].networkTest->value);
430         }
431      }
432 
433 
434    space = FactBinaryData(theEnv)->NumberOfPatterns * sizeof(struct factPatternNode);
435    if (space != 0) genfree(theEnv,(void *) FactBinaryData(theEnv)->FactPatternArray,space);
436    FactBinaryData(theEnv)->NumberOfPatterns = 0;
437   }
438 
439 #endif /* DEFTEMPLATE_CONSTRUCT && (BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE) && (! RUN_TIME) */
440 
441 
442