1    /*******************************************************/
2    /*      "C" Language Integrated Production System      */
3    /*                                                     */
4    /*             CLIPS Version 6.30  08/16/14            */
5    /*                                                     */
6    /*            DEFGLOBAL BSAVE/BLOAD MODULE             */
7    /*******************************************************/
8 
9 /*************************************************************/
10 /* Purpose: Implements the binary save/load feature for the  */
11 /*    defglobal construct.                                   */
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: Changed integer type/precision.                */
22 /*                                                           */
23 /*            Moved WatchGlobals global to defglobalData.    */
24 /*                                                           */
25 /*************************************************************/
26 
27 #define _GLOBLBIN_SOURCE_
28 
29 #include "setup.h"
30 
31 #if DEFGLOBAL_CONSTRUCT && (BLOAD || BLOAD_AND_BSAVE || BLOAD_ONLY) && (! RUN_TIME)
32 
33 #include <stdio.h>
34 #define _STDIO_INCLUDED_
35 
36 #include "memalloc.h"
37 #include "multifld.h"
38 #include "globldef.h"
39 #include "bload.h"
40 #include "bsave.h"
41 #include "moduldef.h"
42 #include "globlbsc.h"
43 #include "envrnmnt.h"
44 
45 #include "globlbin.h"
46 
47 /***************************************/
48 /* LOCAL INTERNAL FUNCTION DEFINITIONS */
49 /***************************************/
50 
51 #if BLOAD_AND_BSAVE
52    static void                    BsaveFind(void *);
53    static void                    BsaveStorage(void *,FILE *);
54    static void                    BsaveBinaryItem(void *,FILE *);
55 #endif
56    static void                    BloadStorageDefglobals(void *);
57    static void                    BloadBinaryItem(void *);
58    static void                    UpdateDefglobalModule(void *,void *,long);
59    static void                    UpdateDefglobal(void *,void *,long);
60    static void                    ClearBload(void *);
61    static void                    DeallocateDefglobalBloadData(void *);
62 
63 /*********************************************/
64 /* DefglobalBinarySetup: Installs the binary */
65 /*   save/load feature for the defglobals.   */
66 /*********************************************/
DefglobalBinarySetup(void * theEnv)67 globle void DefglobalBinarySetup(
68   void *theEnv)
69   {
70    AllocateEnvironmentData(theEnv,GLOBLBIN_DATA,sizeof(struct defglobalBinaryData),DeallocateDefglobalBloadData);
71 #if (BLOAD_AND_BSAVE || BLOAD)
72    AddAfterBloadFunction(theEnv,"defglobal",ResetDefglobals,50);
73 #endif
74 
75 #if BLOAD_AND_BSAVE
76    AddBinaryItem(theEnv,"defglobal",0,BsaveFind,NULL,
77                              BsaveStorage,BsaveBinaryItem,
78                              BloadStorageDefglobals,BloadBinaryItem,
79                              ClearBload);
80 #endif
81 
82 #if (BLOAD || BLOAD_ONLY)
83    AddBinaryItem(theEnv,"defglobal",0,NULL,NULL,NULL,NULL,
84                              BloadStorageDefglobals,BloadBinaryItem,
85                              ClearBload);
86 #endif
87   }
88 
89 /*********************************************************/
90 /* DeallocateDefglobalBloadData: Deallocates environment */
91 /*    data for the defglobal bsave functionality.        */
92 /*********************************************************/
DeallocateDefglobalBloadData(void * theEnv)93 static void DeallocateDefglobalBloadData(
94   void *theEnv)
95   {
96 #if (BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE) && (! RUN_TIME)
97    size_t space;
98    long i;
99 
100    for (i = 0; i < DefglobalBinaryData(theEnv)->NumberOfDefglobals; i++)
101      {
102       if (DefglobalBinaryData(theEnv)->DefglobalArray[i].current.type == MULTIFIELD)
103         { ReturnMultifield(theEnv,(struct multifield *) DefglobalBinaryData(theEnv)->DefglobalArray[i].current.value); }
104      }
105 
106    space = DefglobalBinaryData(theEnv)->NumberOfDefglobals * sizeof(struct defglobal);
107    if (space != 0)
108      { genfree(theEnv,(void *) DefglobalBinaryData(theEnv)->DefglobalArray,space); }
109 
110    space =  DefglobalBinaryData(theEnv)->NumberOfDefglobalModules * sizeof(struct defglobalModule);
111    if (space != 0)
112      { genfree(theEnv,(void *) DefglobalBinaryData(theEnv)->ModuleArray,space); }
113 #endif
114   }
115 
116 #if BLOAD_AND_BSAVE
117 
118 /****************************************************/
119 /* BsaveFind:  Counts the number of data structures */
120 /*   which must be saved in the binary image for    */
121 /*   the defglobals in the current environment.     */
122 /****************************************************/
BsaveFind(void * theEnv)123 static void BsaveFind(
124   void *theEnv)
125   {
126    struct defglobal *defglobalPtr;
127    struct defmodule *theModule;
128 
129    /*=======================================================*/
130    /* If a binary image is already loaded, then temporarily */
131    /* save the count values since these will be overwritten */
132    /* in the process of saving the binary image.            */
133    /*=======================================================*/
134 
135    SaveBloadCount(theEnv,DefglobalBinaryData(theEnv)->NumberOfDefglobalModules);
136    SaveBloadCount(theEnv,DefglobalBinaryData(theEnv)->NumberOfDefglobals);
137 
138    /*============================================*/
139    /* Set the count of defglobals and defglobals */
140    /* module data structures to zero.            */
141    /*============================================*/
142 
143    DefglobalBinaryData(theEnv)->NumberOfDefglobals = 0;
144    DefglobalBinaryData(theEnv)->NumberOfDefglobalModules = 0;
145 
146    for (theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
147         theModule != NULL;
148         theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,theModule))
149      {
150       /*================================================*/
151       /* Set the current module to the module being     */
152       /* examined and increment the number of defglobal */
153       /* modules encountered.                           */
154       /*================================================*/
155 
156       EnvSetCurrentModule(theEnv,(void *) theModule);
157       DefglobalBinaryData(theEnv)->NumberOfDefglobalModules++;
158 
159       /*====================================================*/
160       /* Loop through each defglobal in the current module. */
161       /*====================================================*/
162 
163       for (defglobalPtr = (struct defglobal *) EnvGetNextDefglobal(theEnv,NULL);
164            defglobalPtr != NULL;
165            defglobalPtr = (struct defglobal *) EnvGetNextDefglobal(theEnv,defglobalPtr))
166         {
167          /*======================================================*/
168          /* Initialize the construct header for the binary save. */
169          /*======================================================*/
170 
171          MarkConstructHeaderNeededItems(&defglobalPtr->header,DefglobalBinaryData(theEnv)->NumberOfDefglobals++);
172         }
173      }
174   }
175 
176 /*****************************************************/
177 /* BsaveStorage: Writes out storage requirements for */
178 /*   all defglobal structures to the binary file     */
179 /*****************************************************/
BsaveStorage(void * theEnv,FILE * fp)180 static void BsaveStorage(
181   void *theEnv,
182   FILE *fp)
183   {
184    size_t space;
185 
186    /*===========================================================*/
187    /* Only two data structures are saved as part of a defglobal */
188    /* binary image: the defglobal data structure and the        */
189    /* defglobalModule data structure.                           */
190    /*===========================================================*/
191 
192    space = sizeof(long) * 2;
193    GenWrite(&space,sizeof(size_t),fp);
194    GenWrite(&DefglobalBinaryData(theEnv)->NumberOfDefglobals,sizeof(long int),fp);
195    GenWrite(&DefglobalBinaryData(theEnv)->NumberOfDefglobalModules,sizeof(long int),fp);
196   }
197 
198 /*********************************************/
199 /* BsaveBinaryItem: Writes out all defglobal */
200 /*   structures to the binary file           */
201 /*********************************************/
BsaveBinaryItem(void * theEnv,FILE * fp)202 static void BsaveBinaryItem(
203   void *theEnv,
204   FILE *fp)
205   {
206    size_t space;
207    struct defglobal *theDefglobal;
208    struct bsaveDefglobal newDefglobal;
209    struct defmodule *theModule;
210    struct bsaveDefglobalModule tempDefglobalModule;
211    struct defglobalModule *theModuleItem;
212 
213    /*==========================================================*/
214    /* Write out the amount of space taken up by the defglobal  */
215    /* and defglobalModule data structures in the binary image. */
216    /*==========================================================*/
217 
218    space = DefglobalBinaryData(theEnv)->NumberOfDefglobals * sizeof(struct bsaveDefglobal) +
219            (DefglobalBinaryData(theEnv)->NumberOfDefglobalModules * sizeof(struct bsaveDefglobalModule));
220    GenWrite(&space,sizeof(size_t),fp);
221 
222    /*=================================================*/
223    /* Write out each defglobal module data structure. */
224    /*=================================================*/
225 
226    DefglobalBinaryData(theEnv)->NumberOfDefglobals = 0;
227    for (theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
228         theModule != NULL;
229         theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,theModule))
230      {
231       EnvSetCurrentModule(theEnv,(void *) theModule);
232 
233       theModuleItem = (struct defglobalModule *)
234                       GetModuleItem(theEnv,NULL,FindModuleItem(theEnv,"defglobal")->moduleIndex);
235       AssignBsaveDefmdlItemHdrVals(&tempDefglobalModule.header,
236                                            &theModuleItem->header);
237       GenWrite(&tempDefglobalModule,sizeof(struct bsaveDefglobalModule),fp);
238      }
239 
240    /*===========================*/
241    /* Write out each defglobal. */
242    /*===========================*/
243 
244    DefglobalBinaryData(theEnv)->NumberOfDefglobals = 0;
245    for (theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
246         theModule != NULL;
247         theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,theModule))
248      {
249       EnvSetCurrentModule(theEnv,(void *) theModule);
250 
251       for (theDefglobal = (struct defglobal *) EnvGetNextDefglobal(theEnv,NULL);
252            theDefglobal != NULL;
253            theDefglobal = (struct defglobal *) EnvGetNextDefglobal(theEnv,theDefglobal))
254         {
255          AssignBsaveConstructHeaderVals(&newDefglobal.header,
256                                           &theDefglobal->header);
257          newDefglobal.initial = HashedExpressionIndex(theEnv,theDefglobal->initial);
258 
259          GenWrite(&newDefglobal,sizeof(struct bsaveDefglobal),fp);
260         }
261      }
262 
263    /*=============================================================*/
264    /* If a binary image was already loaded when the bsave command */
265    /* was issued, then restore the counts indicating the number   */
266    /* of defglobals and defglobal modules in the binary image     */
267    /* (these were overwritten by the binary save).                */
268    /*=============================================================*/
269 
270    RestoreBloadCount(theEnv,&DefglobalBinaryData(theEnv)->NumberOfDefglobalModules);
271    RestoreBloadCount(theEnv,&DefglobalBinaryData(theEnv)->NumberOfDefglobals);
272   }
273 
274 #endif /* BLOAD_AND_BSAVE */
275 
276 /***********************************************/
277 /* BloadStorageDefglobals: Allocates space for */
278 /*   the defglobals used by this binary image. */
279 /***********************************************/
BloadStorageDefglobals(void * theEnv)280 static void BloadStorageDefglobals(
281   void *theEnv)
282   {
283    size_t space;
284 
285    /*=======================================================*/
286    /* Determine the number of defglobal and defglobalModule */
287    /* data structures to be read.                           */
288    /*=======================================================*/
289 
290    GenReadBinary(theEnv,&space,sizeof(size_t));
291    GenReadBinary(theEnv,&DefglobalBinaryData(theEnv)->NumberOfDefglobals,sizeof(long int));
292    GenReadBinary(theEnv,&DefglobalBinaryData(theEnv)->NumberOfDefglobalModules,sizeof(long int));
293 
294    /*===================================*/
295    /* Allocate the space needed for the */
296    /* defglobalModule data structures.  */
297    /*===================================*/
298 
299    if (DefglobalBinaryData(theEnv)->NumberOfDefglobalModules == 0)
300      {
301       DefglobalBinaryData(theEnv)->DefglobalArray = NULL;
302       DefglobalBinaryData(theEnv)->ModuleArray = NULL;
303      }
304 
305    space = DefglobalBinaryData(theEnv)->NumberOfDefglobalModules * sizeof(struct defglobalModule);
306    DefglobalBinaryData(theEnv)->ModuleArray = (struct defglobalModule *) genalloc(theEnv,space);
307 
308    /*===================================*/
309    /* Allocate the space needed for the */
310    /* defglobal data structures.        */
311    /*===================================*/
312 
313    if (DefglobalBinaryData(theEnv)->NumberOfDefglobals == 0)
314      {
315       DefglobalBinaryData(theEnv)->DefglobalArray = NULL;
316       return;
317      }
318 
319    space = (DefglobalBinaryData(theEnv)->NumberOfDefglobals * sizeof(struct defglobal));
320    DefglobalBinaryData(theEnv)->DefglobalArray = (struct defglobal *) genalloc(theEnv,space);
321   }
322 
323 /******************************************************/
324 /* BloadBinaryItem: Loads and refreshes the defglobal */
325 /*   constructs used by this binary image.            */
326 /******************************************************/
BloadBinaryItem(void * theEnv)327 static void BloadBinaryItem(
328   void *theEnv)
329   {
330    size_t space;
331 
332    /*======================================================*/
333    /* Read in the amount of space used by the binary image */
334    /* (this is used to skip the construct in the event it  */
335    /* is not available in the version being run).          */
336    /*======================================================*/
337 
338    GenReadBinary(theEnv,&space,sizeof(size_t));
339 
340    /*=============================================*/
341    /* Read in the defglobalModule data structures */
342    /* and refresh the pointers.                   */
343    /*=============================================*/
344 
345    BloadandRefresh(theEnv,DefglobalBinaryData(theEnv)->NumberOfDefglobalModules,
346                    sizeof(struct bsaveDefglobalModule),
347                    UpdateDefglobalModule);
348 
349    /*=======================================*/
350    /* Read in the defglobal data structures */
351    /* and refresh the pointers.             */
352    /*=======================================*/
353 
354    BloadandRefresh(theEnv,DefglobalBinaryData(theEnv)->NumberOfDefglobals,
355                    sizeof(struct bsaveDefglobal),
356                    UpdateDefglobal);
357   }
358 
359 /************************************************/
360 /* UpdateDefglobalModule: Bload refresh routine */
361 /*   for defglobal module data structures.      */
362 /************************************************/
UpdateDefglobalModule(void * theEnv,void * buf,long obji)363 static void UpdateDefglobalModule(
364   void *theEnv,
365   void *buf,
366   long obji)
367   {
368    struct bsaveDefglobalModule *bdmPtr;
369 
370    bdmPtr = (struct bsaveDefglobalModule *) buf;
371 
372    UpdateDefmoduleItemHeader(theEnv,&bdmPtr->header,&DefglobalBinaryData(theEnv)->ModuleArray[obji].header,
373                              (int) sizeof(struct defglobal),
374                              (void *) DefglobalBinaryData(theEnv)->DefglobalArray);
375   }
376 
377 /******************************************/
378 /* UpdateDefglobal: Bload refresh routine */
379 /*   for defglobal data structures.       */
380 /******************************************/
UpdateDefglobal(void * theEnv,void * buf,long obji)381 static void UpdateDefglobal(
382   void *theEnv,
383   void *buf,
384   long obji)
385   {
386    struct bsaveDefglobal *bdp;
387 
388    bdp = (struct bsaveDefglobal *) buf;
389    UpdateConstructHeader(theEnv,&bdp->header,&DefglobalBinaryData(theEnv)->DefglobalArray[obji].header,
390                          (int) sizeof(struct defglobalModule),(void *) DefglobalBinaryData(theEnv)->ModuleArray,
391                          (int) sizeof(struct defglobal),(void *) DefglobalBinaryData(theEnv)->DefglobalArray);
392 
393 #if DEBUGGING_FUNCTIONS
394    DefglobalBinaryData(theEnv)->DefglobalArray[obji].watch = DefglobalData(theEnv)->WatchGlobals;
395 #endif
396    DefglobalBinaryData(theEnv)->DefglobalArray[obji].initial = HashedExpressionPointer(bdp->initial);
397    DefglobalBinaryData(theEnv)->DefglobalArray[obji].current.type = RVOID;
398 
399   }
400 
401 /***************************************/
402 /* ClearBload: Defglobal clear routine */
403 /*   when a binary load is in effect.  */
404 /***************************************/
ClearBload(void * theEnv)405 static void ClearBload(
406   void *theEnv)
407   {
408    long i;
409    size_t space;
410 
411    /*=======================================================*/
412    /* Decrement in use counters for atomic values contained */
413    /* in the construct headers. Also decrement data         */
414    /* structures used to store the defglobal's value.       */
415    /*=======================================================*/
416 
417    for (i = 0; i < DefglobalBinaryData(theEnv)->NumberOfDefglobals; i++)
418      {
419       UnmarkConstructHeader(theEnv,&DefglobalBinaryData(theEnv)->DefglobalArray[i].header);
420 
421       ValueDeinstall(theEnv,&(DefglobalBinaryData(theEnv)->DefglobalArray[i].current));
422       if (DefglobalBinaryData(theEnv)->DefglobalArray[i].current.type == MULTIFIELD)
423         { ReturnMultifield(theEnv,(struct multifield *) DefglobalBinaryData(theEnv)->DefglobalArray[i].current.value); }
424      }
425 
426    /*==============================================================*/
427    /* Deallocate the space used for the defglobal data structures. */
428    /*==============================================================*/
429 
430    space = DefglobalBinaryData(theEnv)->NumberOfDefglobals * sizeof(struct defglobal);
431    if (space != 0) genfree(theEnv,(void *) DefglobalBinaryData(theEnv)->DefglobalArray,space);
432    DefglobalBinaryData(theEnv)->NumberOfDefglobals = 0;
433 
434    /*=====================================================================*/
435    /* Deallocate the space used for the defglobal module data structures. */
436    /*=====================================================================*/
437 
438    space = DefglobalBinaryData(theEnv)->NumberOfDefglobalModules * sizeof(struct defglobalModule);
439    if (space != 0) genfree(theEnv,(void *) DefglobalBinaryData(theEnv)->ModuleArray,space);
440    DefglobalBinaryData(theEnv)->NumberOfDefglobalModules = 0;
441   }
442 
443 /********************************************************/
444 /* BloadDefglobalModuleReference: Returns the defglobal */
445 /*   module pointer for using with the bload function.  */
446 /********************************************************/
BloadDefglobalModuleReference(void * theEnv,int theIndex)447 globle void *BloadDefglobalModuleReference(
448   void *theEnv,
449   int theIndex)
450   {
451    return ((void *) &DefglobalBinaryData(theEnv)->ModuleArray[theIndex]);
452   }
453 
454 #endif /* DEFGLOBAL_CONSTRUCT && (BLOAD || BLOAD_AND_BSAVE || BLOAD_ONLY) && (! RUN_TIME) */
455 
456 
457 
458