1    /*******************************************************/
2    /*      "C" Language Integrated Production System      */
3    /*                                                     */
4    /*             CLIPS Version 6.30  08/16/14            */
5    /*                                                     */
6    /*             EXPRESSION BSAVE/BLOAD MODULE           */
7    /*******************************************************/
8 
9 /*************************************************************/
10 /* Purpose: Implements the binary save/load feature for the  */
11 /*    expression data structure.                             */
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 /*************************************************************/
24 
25 #define _EXPRNBIN_SOURCE_
26 
27 #include "setup.h"
28 
29 #if (BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE)
30 
31 #include <stdio.h>
32 #define _STDIO_INCLUDED_
33 
34 #include "memalloc.h"
35 #include "dffctdef.h"
36 #include "moduldef.h"
37 #include "constrct.h"
38 #include "extnfunc.h"
39 #include "bload.h"
40 #include "bsave.h"
41 #include "envrnmnt.h"
42 
43 #if DEFRULE_CONSTRUCT
44 #include "network.h"
45 #endif
46 
47 #if DEFGENERIC_CONSTRUCT
48 #include "genrcbin.h"
49 #endif
50 
51 #if DEFFUNCTION_CONSTRUCT
52 #include "dffnxbin.h"
53 #endif
54 
55 #if DEFTEMPLATE_CONSTRUCT
56 #include "tmpltbin.h"
57 #endif
58 
59 #if DEFGLOBAL_CONSTRUCT
60 #include "globlbin.h"
61 #endif
62 
63 #if OBJECT_SYSTEM
64 #include "objbin.h"
65 #include "insfun.h"
66 #include "inscom.h"
67 #endif
68 
69 #include "exprnbin.h"
70 
71 /***************************************/
72 /* LOCAL INTERNAL FUNCTION DEFINITIONS */
73 /***************************************/
74 
75    static void                        UpdateExpression(void *,void *,long);
76 
77 /***********************************************************/
78 /* AllocateExpressions: Determines the amount of space     */
79 /*   required for loading the binary image of expressions  */
80 /*   and allocates that amount of space.                   */
81 /***********************************************************/
AllocateExpressions(void * theEnv)82 globle void AllocateExpressions(
83   void *theEnv)
84   {
85    size_t space;
86 
87    GenReadBinary(theEnv,(void *) &ExpressionData(theEnv)->NumberOfExpressions,sizeof(long));
88    if (ExpressionData(theEnv)->NumberOfExpressions == 0L)
89      ExpressionData(theEnv)->ExpressionArray = NULL;
90    else
91      {
92       space = ExpressionData(theEnv)->NumberOfExpressions * sizeof(struct expr);
93       ExpressionData(theEnv)->ExpressionArray = (struct expr *) genalloc(theEnv,space);
94      }
95   }
96 
97 /**********************************************/
98 /* RefreshExpressions: Refreshes the pointers */
99 /*   used by the expression binary image.     */
100 /**********************************************/
RefreshExpressions(void * theEnv)101 globle void RefreshExpressions(
102   void *theEnv)
103   {
104    if (ExpressionData(theEnv)->ExpressionArray == NULL) return;
105 
106    BloadandRefresh(theEnv,ExpressionData(theEnv)->NumberOfExpressions,
107                    (unsigned) sizeof(BSAVE_EXPRESSION),UpdateExpression);
108   }
109 
110 /*********************************************************
111   NAME         : UpdateExpression
112   DESCRIPTION  : Given a bloaded expression buffer,
113                    this routine refreshes the pointers
114                    in the expression array
115   INPUTS       : 1) a bloaded expression buffer
116                  2) the index of the expression to refresh
117   RETURNS      : Nothing useful
118   SIDE EFFECTS : Expression updated
119   NOTES        : None
120  *********************************************************/
UpdateExpression(void * theEnv,void * buf,long obji)121 static void UpdateExpression(
122   void *theEnv,
123   void *buf,
124   long obji)
125   {
126    BSAVE_EXPRESSION *bexp;
127    long theIndex;
128 
129    bexp = (BSAVE_EXPRESSION *) buf;
130    ExpressionData(theEnv)->ExpressionArray[obji].type = bexp->type;
131    switch(bexp->type)
132      {
133       case FCALL:
134         ExpressionData(theEnv)->ExpressionArray[obji].value = (void *) BloadData(theEnv)->FunctionArray[bexp->value];
135         break;
136 
137       case GCALL:
138 #if DEFGENERIC_CONSTRUCT
139         ExpressionData(theEnv)->ExpressionArray[obji].value = (void *) GenericPointer(bexp->value);
140 #else
141         ExpressionData(theEnv)->ExpressionArray[obji].value = NULL;
142 #endif
143         break;
144 
145       case PCALL:
146 #if DEFFUNCTION_CONSTRUCT
147         ExpressionData(theEnv)->ExpressionArray[obji].value = (void *) DeffunctionPointer(bexp->value);
148 #else
149         ExpressionData(theEnv)->ExpressionArray[obji].value = NULL;
150 #endif
151         break;
152 
153       case DEFTEMPLATE_PTR:
154 #if DEFTEMPLATE_CONSTRUCT
155         ExpressionData(theEnv)->ExpressionArray[obji].value = (void *) DeftemplatePointer(bexp->value);
156 #else
157         ExpressionData(theEnv)->ExpressionArray[obji].value = NULL;
158 #endif
159         break;
160 
161      case DEFCLASS_PTR:
162 #if OBJECT_SYSTEM
163         ExpressionData(theEnv)->ExpressionArray[obji].value = (void *) DefclassPointer(bexp->value);
164 #else
165         ExpressionData(theEnv)->ExpressionArray[obji].value = NULL;
166 #endif
167         break;
168 
169       case DEFGLOBAL_PTR:
170 
171 #if DEFGLOBAL_CONSTRUCT
172         ExpressionData(theEnv)->ExpressionArray[obji].value = (void *) DefglobalPointer(bexp->value);
173 #else
174         ExpressionData(theEnv)->ExpressionArray[obji].value = NULL;
175 #endif
176         break;
177 
178 
179       case INTEGER:
180         ExpressionData(theEnv)->ExpressionArray[obji].value = (void *) SymbolData(theEnv)->IntegerArray[bexp->value];
181         IncrementIntegerCount((INTEGER_HN *) ExpressionData(theEnv)->ExpressionArray[obji].value);
182         break;
183 
184       case FLOAT:
185         ExpressionData(theEnv)->ExpressionArray[obji].value = (void *) SymbolData(theEnv)->FloatArray[bexp->value];
186         IncrementFloatCount((FLOAT_HN *) ExpressionData(theEnv)->ExpressionArray[obji].value);
187         break;
188 
189       case INSTANCE_NAME:
190 #if ! OBJECT_SYSTEM
191         ExpressionData(theEnv)->ExpressionArray[obji].type = SYMBOL;
192 #endif
193       case GBL_VARIABLE:
194       case SYMBOL:
195       case STRING:
196         ExpressionData(theEnv)->ExpressionArray[obji].value = (void *) SymbolData(theEnv)->SymbolArray[bexp->value];
197         IncrementSymbolCount((SYMBOL_HN *) ExpressionData(theEnv)->ExpressionArray[obji].value);
198         break;
199 
200 #if DEFTEMPLATE_CONSTRUCT
201       case FACT_ADDRESS:
202         ExpressionData(theEnv)->ExpressionArray[obji].value = (void *) &FactData(theEnv)->DummyFact;
203         EnvIncrementFactCount(theEnv,ExpressionData(theEnv)->ExpressionArray[obji].value);
204         break;
205 #endif
206 
207 #if OBJECT_SYSTEM
208       case INSTANCE_ADDRESS:
209         ExpressionData(theEnv)->ExpressionArray[obji].value = (void *) &InstanceData(theEnv)->DummyInstance;
210         EnvIncrementInstanceCount(theEnv,ExpressionData(theEnv)->ExpressionArray[obji].value);
211         break;
212 #endif
213 
214       case EXTERNAL_ADDRESS:
215         ExpressionData(theEnv)->ExpressionArray[obji].value = NULL;
216         break;
217 
218       case RVOID:
219         break;
220 
221       default:
222         if (EvaluationData(theEnv)->PrimitivesArray[bexp->type] == NULL) break;
223         if (EvaluationData(theEnv)->PrimitivesArray[bexp->type]->bitMap)
224           {
225            ExpressionData(theEnv)->ExpressionArray[obji].value = (void *) SymbolData(theEnv)->BitMapArray[bexp->value];
226            IncrementBitMapCount((BITMAP_HN *) ExpressionData(theEnv)->ExpressionArray[obji].value);
227           }
228         break;
229      }
230 
231    theIndex = (long int) bexp->nextArg;
232    if (theIndex == -1L)
233      { ExpressionData(theEnv)->ExpressionArray[obji].nextArg = NULL; }
234    else
235      { ExpressionData(theEnv)->ExpressionArray[obji].nextArg = (struct expr *) &ExpressionData(theEnv)->ExpressionArray[theIndex]; }
236 
237    theIndex = (long int) bexp->argList;
238    if (theIndex == -1L)
239      { ExpressionData(theEnv)->ExpressionArray[obji].argList = NULL; }
240    else
241      { ExpressionData(theEnv)->ExpressionArray[obji].argList = (struct expr *) &ExpressionData(theEnv)->ExpressionArray[theIndex]; }
242   }
243 
244 /*********************************************/
245 /* ClearBloadedExpressions: Clears the space */
246 /*   utilized by an expression binary image. */
247 /*********************************************/
ClearBloadedExpressions(void * theEnv)248 globle void ClearBloadedExpressions(
249   void *theEnv)
250   {
251    unsigned long int i;
252    size_t space;
253 
254    /*===============================================*/
255    /* Update the busy counts of atomic data values. */
256    /*===============================================*/
257 
258    for (i = 0; i < (unsigned long) ExpressionData(theEnv)->NumberOfExpressions; i++)
259      {
260       switch (ExpressionData(theEnv)->ExpressionArray[i].type)
261         {
262          case SYMBOL          :
263          case STRING          :
264          case INSTANCE_NAME   :
265          case GBL_VARIABLE    :
266            DecrementSymbolCount(theEnv,(SYMBOL_HN *) ExpressionData(theEnv)->ExpressionArray[i].value);
267            break;
268          case FLOAT           :
269            DecrementFloatCount(theEnv,(FLOAT_HN *) ExpressionData(theEnv)->ExpressionArray[i].value);
270            break;
271          case INTEGER         :
272            DecrementIntegerCount(theEnv,(INTEGER_HN *) ExpressionData(theEnv)->ExpressionArray[i].value);
273            break;
274 
275 #if DEFTEMPLATE_CONSTRUCT
276          case FACT_ADDRESS    :
277            EnvDecrementFactCount(theEnv,ExpressionData(theEnv)->ExpressionArray[i].value);
278            break;
279 #endif
280 
281 #if OBJECT_SYSTEM
282          case INSTANCE_ADDRESS :
283            EnvDecrementInstanceCount(theEnv,ExpressionData(theEnv)->ExpressionArray[i].value);
284            break;
285 #endif
286 
287          case RVOID:
288            break;
289 
290          default:
291            if (EvaluationData(theEnv)->PrimitivesArray[ExpressionData(theEnv)->ExpressionArray[i].type] == NULL) break;
292            if (EvaluationData(theEnv)->PrimitivesArray[ExpressionData(theEnv)->ExpressionArray[i].type]->bitMap)
293              { DecrementBitMapCount(theEnv,(BITMAP_HN *) ExpressionData(theEnv)->ExpressionArray[i].value); }
294            break;
295         }
296      }
297 
298    /*===================================*/
299    /* Free the binary expression array. */
300    /*===================================*/
301 
302    space = ExpressionData(theEnv)->NumberOfExpressions * sizeof(struct expr);
303    if (space != 0) genfree(theEnv,(void *) ExpressionData(theEnv)->ExpressionArray,space);
304    ExpressionData(theEnv)->ExpressionArray = 0;
305   }
306 
307 
308 #if BLOAD_AND_BSAVE
309 
310 /***************************************************
311   NAME         : FindHashedExpressions
312   DESCRIPTION  : Sets the bsave expression array
313                  indices for hashed expression nodes
314                  and marks the items needed by
315                  these expressions
316   INPUTS       : None
317   RETURNS      : Nothing useful
318   SIDE EFFECTS : Atoms marked and ids set
319   NOTES        : None
320  ***************************************************/
FindHashedExpressions(void * theEnv)321 globle void FindHashedExpressions(
322   void *theEnv)
323   {
324    register unsigned i;
325    EXPRESSION_HN *exphash;
326 
327    for (i = 0 ; i < EXPRESSION_HASH_SIZE ; i++)
328      for (exphash = ExpressionData(theEnv)->ExpressionHashTable[i] ; exphash != NULL ; exphash = exphash->next)
329        {
330         MarkNeededItems(theEnv,exphash->exp);
331         exphash->bsaveID = ExpressionData(theEnv)->ExpressionCount;
332         ExpressionData(theEnv)->ExpressionCount += ExpressionSize(exphash->exp);
333        }
334   }
335 
336 /***************************************************
337   NAME         : BsaveHashedExpressions
338   DESCRIPTION  : Writes out hashed expressions
339   INPUTS       : Bsave file stream pointer
340   RETURNS      : Nothing useful
341   SIDE EFFECTS : Expressions written
342   NOTES        : None
343  ***************************************************/
BsaveHashedExpressions(void * theEnv,FILE * fp)344 globle void BsaveHashedExpressions(
345   void *theEnv,
346   FILE *fp)
347   {
348    register unsigned i;
349    EXPRESSION_HN *exphash;
350 
351    for (i = 0 ; i < EXPRESSION_HASH_SIZE ; i++)
352      for (exphash = ExpressionData(theEnv)->ExpressionHashTable[i] ; exphash != NULL ; exphash = exphash->next)
353        BsaveExpression(theEnv,exphash->exp,fp);
354   }
355 
356 /***************************************************************/
357 /* BsaveConstructExpressions: Writes all expression needed by  */
358 /*   constructs for this binary image to the binary save file. */
359 /***************************************************************/
BsaveConstructExpressions(void * theEnv,FILE * fp)360 globle void BsaveConstructExpressions(
361   void *theEnv,
362   FILE *fp)
363   {
364    struct BinaryItem *biPtr;
365 
366    for (biPtr = BsaveData(theEnv)->ListOfBinaryItems;
367         biPtr != NULL;
368         biPtr = biPtr->next)
369      {
370       if (biPtr->expressionFunction != NULL)
371         { (*biPtr->expressionFunction)(theEnv,fp); }
372      }
373   }
374 
375 /***************************************/
376 /* BsaveExpression: Recursively saves  */
377 /*   an expression to the binary file. */
378 /***************************************/
BsaveExpression(void * theEnv,struct expr * testPtr,FILE * fp)379 globle void BsaveExpression(
380   void *theEnv,
381   struct expr *testPtr,
382   FILE *fp)
383   {
384    BSAVE_EXPRESSION newTest;
385    long int newIndex;
386 
387    while (testPtr != NULL)
388      {
389       ExpressionData(theEnv)->ExpressionCount++;
390 
391       /*================*/
392       /* Copy the type. */
393       /*================*/
394 
395       newTest.type = testPtr->type;
396 
397       /*=======================================*/
398       /* Convert the argList slot to an index. */
399       /*=======================================*/
400 
401       if (testPtr->argList == NULL)
402         { newTest.argList = -1L; }
403       else
404         { newTest.argList = ExpressionData(theEnv)->ExpressionCount; }
405 
406       /*========================================*/
407       /* Convert the nextArg slot to an index. */
408       /*========================================*/
409 
410       if (testPtr->nextArg == NULL)
411         { newTest.nextArg = -1L; }
412       else
413         {
414          newIndex = ExpressionData(theEnv)->ExpressionCount + ExpressionSize(testPtr->argList);
415          newTest.nextArg = newIndex;
416         }
417 
418       /*=========================*/
419       /* Convert the value slot. */
420       /*=========================*/
421 
422       switch(testPtr->type)
423         {
424          case FLOAT:
425            newTest.value = (long) ((FLOAT_HN *) testPtr->value)->bucket;
426            break;
427 
428          case INTEGER:
429            newTest.value = (long) ((INTEGER_HN *) testPtr->value)->bucket;
430            break;
431 
432          case FCALL:
433            newTest.value = (long) ((struct FunctionDefinition *)
434                                    testPtr->value)->bsaveIndex;
435            break;
436 
437          case GCALL:
438 #if DEFGENERIC_CONSTRUCT
439            if (testPtr->value != NULL)
440              newTest.value = ((struct constructHeader *) testPtr->value)->bsaveID;
441            else
442 #endif
443              newTest.value = -1L;
444            break;
445 
446          case PCALL:
447 #if DEFFUNCTION_CONSTRUCT
448            if (testPtr->value != NULL)
449              newTest.value = ((struct constructHeader *) testPtr->value)->bsaveID;
450            else
451 #endif
452              newTest.value = -1L;
453            break;
454 
455          case DEFTEMPLATE_PTR:
456 #if DEFTEMPLATE_CONSTRUCT
457            if (testPtr->value != NULL)
458              newTest.value = ((struct constructHeader *) testPtr->value)->bsaveID;
459            else
460 #endif
461              newTest.value = -1L;
462            break;
463 
464          case DEFCLASS_PTR:
465 #if OBJECT_SYSTEM
466            if (testPtr->value != NULL)
467              newTest.value = ((struct constructHeader *) testPtr->value)->bsaveID;
468            else
469 #endif
470              newTest.value = -1L;
471            break;
472 
473          case DEFGLOBAL_PTR:
474 #if DEFGLOBAL_CONSTRUCT
475            if (testPtr->value != NULL)
476              newTest.value = ((struct defglobal *) testPtr->value)->header.bsaveID;
477            else
478 #endif
479              newTest.value = -1L;
480            break;
481 
482 #if OBJECT_SYSTEM
483          case INSTANCE_NAME:
484 #endif
485          case SYMBOL:
486          case GBL_VARIABLE:
487          case STRING:
488            newTest.value = (long) ((SYMBOL_HN *) testPtr->value)->bucket;
489            break;
490 
491          case FACT_ADDRESS:
492          case INSTANCE_ADDRESS:
493          case EXTERNAL_ADDRESS:
494            newTest.value = -1L;
495            break;
496 
497          case RVOID:
498            break;
499 
500          default:
501            if (EvaluationData(theEnv)->PrimitivesArray[testPtr->type] == NULL) break;
502            if (EvaluationData(theEnv)->PrimitivesArray[testPtr->type]->bitMap)
503              { newTest.value = (long) ((BITMAP_HN *) testPtr->value)->bucket; }
504            break;
505         }
506 
507      /*===========================*/
508      /* Write out the expression. */
509      /*===========================*/
510 
511      GenWrite(&newTest,(unsigned long) sizeof(BSAVE_EXPRESSION),fp);
512 
513      /*==========================*/
514      /* Write out argument list. */
515      /*==========================*/
516 
517      if (testPtr->argList != NULL)
518        {
519         BsaveExpression(theEnv,testPtr->argList,fp);
520        }
521 
522      testPtr = testPtr->nextArg;
523     }
524   }
525 
526 #endif /* BLOAD_AND_BSAVE */
527 
528 #endif /* (BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE) */
529 
530